You are on page 1of 2212

Customization Guide

11.0 M020
December 2016
Document Version 11.02.01
Copyright © 2016 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.

User and training guides and related documentation from PTC Inc. and its subsidiary companies (collectively
"PTC") are subject to the copyright laws of the United States and other countries and are provided under a
license agreement that restricts copying, disclosure, and use of such documentation. PTC hereby grants to the
licensed software user the right to make copies in printed form of this documentation if provided on software
media, but only for internal/personal use and in accordance with the license agreement under which the
applicable software is licensed. Any copy made shall include the PTC copyright notice and any other
proprietary notice provided by PTC. Training materials may not be copied without the express written consent
of PTC. This documentation may not be disclosed, transferred, modified, or reduced to any form, including
electronic media, or transmitted or made publicly available by any means without the prior written consent of
PTC and no authorization is granted to make copies for such purposes. Information described herein is
furnished for general information only, is subject to change without notice, and should not be construed as a
warranty or commitment by PTC. PTC assumes no responsibility or liability for any errors or inaccuracies
that may appear in this document.

The software described in this document is provided under written license agreement, contains valuable trade
secrets and proprietary information, and is protected by the copyright laws of the United States and other
countries. It may not be copied or distributed in any form or medium, disclosed to third parties, or used in any
manner not provided for in the software licenses agreement except with written prior approval from PTC.

UNAUTHORIZED USE OF SOFTWARE OR ITS DOCUMENTATION CAN RESULT IN CIVIL


DAMAGES AND CRIMINAL PROSECUTION.

PTC regards software piracy as the crime it is, and we view offenders accordingly. We do not tolerate the
piracy of PTC software products, and we pursue (both civilly and criminally) those who do so using all legal
means available, including public and private surveillance resources. As part of these efforts, PTC uses data
monitoring and scouring technologies to obtain and transmit data on users of illegal copies of our software.
This data collection is not performed on users of legally licensed software from PTC and its authorized
distributors. If you are using an illegal copy of our software and do not consent to the collection and
transmission of such data (including to the United States), cease using the illegal version, and contact PTC to
obtain a legally licensed copy.

Important Copyright, Trademark, Patent, and Licensing Information: See the About Box, or copyright
notice, of your PTC software.

UNITED STATES GOVERNMENT RIGHTS

PTC software products and software documentation are “commercial items” as that term is defined at 48 C.F.
R. 2.101. Pursuant to Federal Acquisition Regulation (FAR) 12.212 (a)-(b) (Computer Software) (MAY 2014)
for civilian agencies or the Defense Federal Acquisition Regulation Supplement (DFARS) at 227.7202-1(a)
(Policy) and 227.7202-3 (a) (Rights in commercial computer software or commercial computer software
documentation) (FEB 2014) for the Department of Defense, PTC software products and software
documentation are provided to the U.S. Government under the PTC commercial license agreement. Use,
duplication or disclosure by the U.S. Government is subject solely to the terms and conditions set forth in the
applicable PTC software license agreement.

PTC Inc., 140 Kendrick Street, Needham, MA 02494 USA


Contents

Windchill Customization Basics ...........................................................................27


Customization Overview......................................................................................29
Configuration Options...................................................................................30
Customizations ............................................................................................33
Windchill Customization Points .....................................................................36
The Windchill Development Environment .............................................................39
Directory Structure .......................................................................................40
Environment Variables..................................................................................46
Property Files ..............................................................................................47
Properties and Property Files ........................................................................51
Getting Started With Windchill Customization .......................................................55
Example Overview .......................................................................................56
Windchill Development Environment .............................................................57
Customization Setup ....................................................................................58
Creating the Class .......................................................................................59
Creating a UI ...............................................................................................68
Customizations — Next Steps.......................................................................90
Modeling Business Objects .................................................................................91
Windchill Modeling Heuristics........................................................................92
Windchill Foundation Abstractions.................................................................95
Managing Customizations ................................................................................. 100
Setting Up a Directory Structure for Managing Customized Files and Text
Tailoring ................................................................................................. 101
Best Practices for Customizing Files Supplied by PTC .................................. 109
Best Practices for Adding New Packages and Files ...................................... 129
Modeled To Subtype Conversion................................................................. 133
Monitoring a Customized Windchill Environment .......................................... 160
Customization with Windchill Queues .......................................................... 161
Windchill Utilities .............................................................................................. 163
Using the xconfmanager Utility.................................................................... 164
Formatting Property Value Guidelines.......................................................... 176
Windchill Command ................................................................................... 177
Windchill Shell ........................................................................................... 180
Customization Tutorial ...................................................................................... 181
Tutorial Overview ....................................................................................... 182
Create Administrator and User .................................................................... 184
Create a Library and Document................................................................... 194

3
Allocate Database Columns for Local Attributes ........................................... 200
Create a New Attribute Definition and Add it to the Document Type................ 202
As the End User, Create a Document with the new Attribute .......................... 209
Create a Document Subtype ....................................................................... 212
Create an Instance of the New Document Subtype ....................................... 216
Model a New Document Subclass ............................................................... 217
Create an Instance of the New Document Subclass...................................... 224
Verify the Customizations ........................................................................... 227
Customization Tutorial Summary................................................................. 228
User Interface Customization............................................................................. 229
User Interface Technology Overview .................................................................. 231
Windchill Client Architecture Overview......................................................... 232
Windchill Client Architecture Common Objects Overview .............................. 245
Javascript Functions Overview.................................................................... 248
Adding Custom Code to all Windchill Client Architecture Pages ..................... 255
MVC Components ............................................................................................ 257
MVC Components Overview ....................................................................... 258
MVC Tables ............................................................................................... 287
Customizing HTML Clients Using the Windchill JSP Framework........................... 289
Customizing Generic Aspects of JSP Pages ................................................ 290
Bread Crumbs Component ......................................................................... 299
Client Tabs ................................................................................................ 311
Checkin/Checkout...................................................................................... 325
Component Access Control ........................................................................ 330
Attachments .............................................................................................. 337
Attribute Panels ......................................................................................... 348
Customizing Access Control For Packages .................................................. 400
Customization Tools Overview .................................................................... 404
Adding Validation Logic for Actions and Properties ....................................... 442
Split Pane / Two Pane ................................................................................ 463
Defining Layouts in a Type Load File ........................................................... 474
Configuring the Drag and Drop Zone ........................................................... 478
Generic UI Customizations ................................................................................ 481
Customizing Role-Based UI Functions - Attribute Visibility............................. 482
Customizing Role-Based UI Functions — Action Visibility.............................. 494
Preference Framework ............................................................................... 495
Constructing URLs ..................................................................................... 501
Offline Package Customization ................................................................... 502
System Banner Alert Message .................................................................... 506
Adding a Status Glyph ................................................................................ 508
Adding Actions and Hooking Them Up in the UI .................................................. 511
Action Framework for Windchill Client Architecture ....................................... 512
Tab Models................................................................................................ 539
Customizing Role-based Visibility................................................................ 549
User Interface Stickiness ............................................................................ 561

4 Customization Guide
Defining Menus.......................................................................................... 562
Adding Custom Content to the Home Page .................................................. 578
Gathering the Data for the UI ............................................................................. 583
Acquiring Data via Info*Engine.................................................................... 584
NmObject Utilities ...................................................................................... 590
File Download............................................................................................ 596
Presenting Information in the UI ......................................................................... 603
Dynamically Resolved Attributes for Customizations..................................... 604
Constructing and Rendering a Table Using the JSP Framework..................... 606
Windchill Client Architecture Tree ................................................................ 642
Attribute Customization .............................................................................. 658
Adding Custom Modeled Attributes to all Table Views ................................... 736
Attribute Tables.......................................................................................... 737
Icon Delegates........................................................................................... 742
Creating Custom Graphical Representations................................................ 749
UI Validation .............................................................................................. 770
URL Authorization...................................................................................... 823
Customizing the Find Number Field ............................................................. 826
Inline Messaging........................................................................................ 832
Constructing Wizards........................................................................................ 837
Windchill Client Architecture Wizard ............................................................ 838
Wizard Processing ..................................................................................... 866
Building Wizards to Create a Single Object .................................................. 892
Building Wizards to Edit a Single Object....................................................... 914
Customizing Reusable Wizard Steps .......................................................... 928
Handling External Requests Using an MVC Controller .................................. 959
Client Generated Form Data ....................................................................... 964
Information Pages ............................................................................................ 971
Customizing Information Page Components................................................. 972
Incorporating Pickers in JSP Clients................................................................. 1005
Configuring Pickers .................................................................................. 1006
Configuring a Context Picker..................................................................... 1015
Configuring an Item Picker........................................................................ 1025
Configuring an Organization Picker ........................................................... 1034
Configuring a Type Picker ......................................................................... 1043
Configuring a User Picker ......................................................................... 1061
Configuring a Participant Picker in JCA...................................................... 1068
Configuring a Participant Picker in AngularJS............................................. 1083
Configurable Links .......................................................................................... 1089
Configurable Link Tables .......................................................................... 1090
Configurable Revision Links...................................................................... 1100
Customizing Online Help ................................................................................. 1105
Customizing Windchill Help Center Content ............................................... 1107
Adding Topics to the Help Center TOC....................................................... 1108

Contents 5
Linking to Help Topics................................................................................1114
Windchill Help Center Logging ...................................................................1115
Windchill Search Customization........................................................................1119
Customizing Indexing Behavior ................................................................. 1120
Customizing Solr...................................................................................... 1122
Customizing Faceted Search .................................................................... 1128
Business Logic Customization ......................................................................... 1131
Encrypted Passwords ..................................................................................... 1135
Encrypted Passwords............................................................................... 1136
Customizing the Login Page ............................................................................ 1155
Login Page Customization ........................................................................ 1156
Customizing Business Logic ............................................................................ 1157
Customizing a Bill of Materials .................................................................. 1158
Customizing Logic for Structure Compare .................................................. 1160
Context Builder Customization Example .................................................... 1163
Customizing Change Management .................................................................. 1169
Association Constraints ............................................................................ 1170
Customizing Multiple Inventory Dispositions............................................... 1174
Mass Change Operations ......................................................................... 1185
Mass Change Supported Types ................................................................ 1193
Sponsored Problem Reports and Variances ............................................... 1197
Change Management Cardinality .............................................................. 1200
Change Management Delegate................................................................. 1204
Change Management Transitions.............................................................. 1206
Change Template Initialization Rules ........................................................ 1210
Replicated Objects as Change Task Resulting Objects ............................... 1213
Evaluating Business Rules On Demand..................................................... 1219
Editing Attributes on the Links of Change Relationship Tables ..................... 1228
Change Workflow Closure ........................................................................ 1243
Flexible Change Links for Query Builder .................................................... 1253
Business Rules............................................................................................... 1263
Customizing Business Rules..................................................................... 1264
Bypassing Business Rules........................................................................ 1284
Loading Business Rule Objects................................................................. 1291
Customizing Workflow Administration............................................................... 1311
Customizing Change Management Workflow Process Templates ................ 1312
Customizing Promotion Request Workflow Processes ................................ 1318
Enhanced Promotion Process................................................................... 1322
Customizing Workflow Events on an Object ............................................... 1333
Customizing Workflow Task Pages ............................................................ 1335
Refine and Review Workflow Transitions ................................................... 1359
Adding Custom Workflow Attribute to Workflow Processes.......................... 1366
Workflow Email Notifications ..................................................................... 1369
Multiple Participant Selection Wizard Customization ................................... 1374

6 Customization Guide
Customizing Change Activity Workflow Assignments .................................. 1382
Customizing Change Tables Designed for Workflow ................................... 1392
Locking Annotations In Change Workflows ................................................ 1398
Customizing Life Cycle Administration.............................................................. 1401
Customizing the Display of Life Cycle Information....................................... 1402
Defining Custom Life Cycle Transitions...................................................... 1404
Setting Up a Customized State-Based Versioning Scheme ......................... 1407
Customizations in Type and Attribute Management ........................................... 1415
Using a BusinessAlgorithm in a Calculated Attribute ................................... 1416
Options and Variants....................................................................................... 1425
Customizing Options and Variants ............................................................. 1426
Customizing Security Labels............................................................................ 1431
Customizing Security Labels ..................................................................... 1432
Customizing Windchill Visualization Services.................................................... 1453
Custom Publishing ................................................................................... 1454
Customizing Publishing Queues................................................................ 1473
Interference Detection .............................................................................. 1479
Modifying the Default Behavior of Dynamic Part Generation ........................ 1487
Report Generation .......................................................................................... 1491
Report Generation Overview..................................................................... 1493
Basic Report Example .............................................................................. 1493
Import and Export of Report Templates ...................................................... 1494
Java Methods .......................................................................................... 1497
Customization Details............................................................................... 1498
Cognos Presentation Customization.......................................................... 1518
Reporting Info*Engine Task Data Source Customization ............................. 1524
Report Loading ........................................................................................ 1530
ReportTemplate Data Source Customization .............................................. 1539
Reporting Input Page Customization ......................................................... 1543
Report Localization Customization ............................................................ 1548
Report Selection List Customization .......................................................... 1554
Packages Customization................................................................................. 1565
Package Type-Based Properties ............................................................... 1566
Identifying Users in Context Replication and Activating Replicated
Users................................................................................................... 1580
Select Files – Copy Forward Exclusion Decisions ....................................... 1594
Windchill Replication Package Command Line Sample Scripts.................... 1597
DTI Customization Framework......................................................................... 1599
Add Custom Attributes to Microsoft Office .................................................. 1600
Customize the Windchill tab in Microsoft Office........................................... 1602
Customize Windchill Actions in Windows Explorer ...................................... 1617
Customize the DTI Document Search Window ........................................... 1620
Using DTI with Form-Based Authentication ................................................ 1621

Contents 7
Customizing Action Item Attributes................................................................... 1623
Customizable Action Item Attributes .......................................................... 1624
Customizations for PDM.................................................................................. 1629
Customizing the HTML Client Object Selection Page ................................. 1630
Customizing Auto Associate ..................................................................... 1638
Enabling Support for Custom Parts............................................................ 1646
Customizing the Parameters in the Download Service ................................ 1648
Reservation Service........................................................................................ 1651
Reservation Service APIs ......................................................................... 1655
Using the Reservation Service .................................................................. 1655
Using the Reservation Client Tools ............................................................ 1657
Using the Update Count Client Tools ......................................................... 1658
Adding the Undo Reservation Action to a Menu .......................................... 1659
Sample Code: Reservation Service ........................................................... 1660
Data Exchange using Standards in Windchill .................................................... 1661
Product Lifecycle Management Services, Version 2.0 ................................. 1662
STEP Data Exchange using EXPRESS ..................................................... 1699
Windchill Workgroup Manager Customization ................................................... 1881
Custom Windchill Workgroup Manager Requests ....................................... 1884
Creating the Windchill Server-side Customization....................................... 1890
Pre Operation Customization Hooks for PDM Actions ................................. 1895
Registering a Custom Event Listener......................................................... 1896
CAD Document Structure Publishing to Other Systems ..................................... 1897
CAD Document Structure Publishing to Other Systems............................... 1898
ThingWorx ..................................................................................................... 1905
Adding a ThingWorx Mashup to Windchill .................................................. 1906
Deploying Arbortext Customizations................................................................. 1921
Annonymous Arbortext Access ................................................................. 1922
Customizing Configuration Specifications ......................................................... 1931
Customizing Logic to Determine the Default Configuration
Specifications ....................................................................................... 1932

Identified Business Classes ................................................................................ 1934


Services and Infrastructure Customization........................................................ 1941
System Generation ......................................................................................... 1943
Modeling Business Objects....................................................................... 1944
Creating New Tablespaces ....................................................................... 1971
Enumerated Types.......................................................................................... 1973
The EnumeratedType Class...................................................................... 1974
Creating an EnumeratedType Subclass ..................................................... 1976
Editing the Resource Info for an Enumerated Type ..................................... 1977
Localizing an Enumerated Type ................................................................ 1979
Extending an Enumerated Type ................................................................ 1980

8 Customization Guide
The Enumerated Type Customization Utility ............................................... 1981
GUI Usage of an Enumerated Type ........................................................... 1983
External Enumerated Value Lists............................................................... 1984
Customizing LDAP Attributes ........................................................................... 1993
Customizing LDAP Mapped Attributes in a User Information Page ............... 1994
Customizing LDAP Mapped Attributes in a Group Information Page............. 1997
System Configuration Collector Plugin.............................................................. 2001
Creating a System Configuration Collector Plugin....................................... 2002
Customizing Modeled Elements....................................................................... 2051
Customizing Column Lengths ................................................................... 2052
Windchill Design Patterns................................................................................ 2055
The Object Reference Design Pattern........................................................ 2056
The Business Service Design Pattern ........................................................ 2058
The Master-iteration Design Pattern .......................................................... 2061
Internationalization and Localization................................................................. 2063
Background ............................................................................................. 2064
The Windchill Approach............................................................................ 2065
Localizing Text Visible to the User ............................................................. 2067
Resource Info (.rbInfo) Files...................................................................... 2071
The Enterprise Layer ...................................................................................... 2075
Enterprise Abstractions ............................................................................ 2076
Document Abstractions ............................................................................ 2083
Part Abstractions ..................................................................................... 2086
Change Abstractions ................................................................................ 2093
Persistence Management................................................................................ 2107
Persistence Datastore Sequence Customization ........................................ 2108
Advanced Query Capabilities........................................................................... 2113
QuerySpec .............................................................................................. 2114
SearchCondition ...................................................................................... 2122
Import Export Framework ................................................................................ 2129
How to Write an IX Application .................................................................. 2130
How to Write Exp/Imp Handlers................................................................. 2146
Navigating Through an Object’s Structure with ObjectSet
Application ........................................................................................... 2160
Product Design eXchange (PDX) Support for Export................................... 2181
Adding Export Functionality in the Project Plan Table .................................. 2188
Evolvable Classes .......................................................................................... 2192
Background Information ........................................................................... 2193
General Externalization Guidelines............................................................ 2193
Hand-coded Externalization Guidelines ..................................................... 2195
Migration Guidelines for Classes with Hand-coded Externalization............... 2196
Examples of Generated Externalization Code for Evolvable Classes............ 2197
Creating Large Objects (LOBs) ........................................................................ 2203

Contents 9
Modeling Large Objects............................................................................ 2204
Customizing Data Formats .............................................................................. 2209
Adding and Updating Data Formats for Content Holders ............................. 2210

10 Customization Guide
About This Guide
The Windchill Customization Guide describes how to customize the out-of-the-
box implementation of Windchill. It is intended for developers who are familiar
with Windchill Javadoc.
This guide can be used with all Windchill solutions.
Examples in this guide referencing third-party products are intended for
demonstration purposes only. For additional information about third-party
products, contact individual product vendors.

Note
Some code examples in this guide have been reformatted for presentation
purposes and, therefore, may contain line number, hidden editing characters
(such as tabs and end-of-line characters) and extraneous spaces. If you cut and
paste code from this manual, check for these characters and remove them
before attempting to use the example in your application.

Related Documentation
This guide contains a subset of the customization reference topics from the Basic
Customization and Advanced Customization sections of the Windchill Help
Center. Additional customization information is available in the following guides:
• Windchill Explorers Customization Guide
• Windchill Enterprise Systems Integration Customizer's Guide - Oracle
Applications
• Windchill Enterprise Systems Integration Customizer's Guide - SAP
• Info*Engine User's Guide
• Info*Engine Implementation Guide
• Windchill Adapter Guide
• Info*Engine Java Adapter Development Kit Programming Reference

Customization Source Code Examples


Customization source code examples are available for download from the
following location: http://www.ptc.com/view?im_dbkey=156765

11
Technical Support
The PTC eSupport portal provides the resources and tools to support your
Windchill implementation:
https://support.ptc.com/appserver/cs/portal/
If you encounter problems using this product, contact PTC Technical Support. For
complete details, see “Opening a Case” on the Processes tab of the PTC
Customer Support Guide:
http://support.ptc.com/appserver/support/csguide/csguide.jsp
You must have a Service Contract Number (SCN) before you can receive
technical support. If you do not know your SCN, see “Preparing to contact TS” on
the Processes tab of the PTC Customer Support Guide for information about how
to locate it.

Documentation for PTC Products


You can access PTC documentation using the following resources:
• Windchill Help Center—The Windchill Help Center includes all Windchill
documentation. You can browse the entire documentation set, or use the search
capability to perform a keyword search. To access the Windchill Help Center,
you can:
○ Click any help icon in Windchill
○ Select Help ▶ Windchill Help Center from the Quick Links menu at the top
right of any Windchill page
○ Use the following link to access all PTC help centers:
https://support.ptc.com/appserver/cs/help/help.jsp
• Reference Documents website—The Reference Documents website is a library
of all PTC guides:
http://support.ptc.com/appserver/cs/doc/refdoc.jsp
A Service Contract Number (SCN) is required to access the PTC
documentation from the Reference Documents website. If you do not know
your SCN, see “Preparing to contact TS” on the Processes tab of the PTC
Customer Support Guide for information about how to locate it:
http://support.ptc.com/appserver/support/csguide/csguide.jsp
When you enter a keyword in the Search Our Knowledge field on the PTC
eSupport portal, your search results will include information from knowledge base
articles, product documentation, and the PTC community.

12 Customization Guide
Comments
PTC welcomes your suggestions and comments on its documentation. To submit
your feedback, you can:
• Send an email to documentation@ptc.com. To help us more quickly address
your concern, include the name of the PTC product and its release number
with your comments. If your comments are about a specific help topic or
book, include the title.
• Click the feedback icon in the Windchill Help Center toolbar and complete
the feedback form. The title of the help topic you were viewing when you
clicked the icon is automatically included with your feedback.

13
Customization Documentation Change
Record
This table details the updates to the Windchill Customization Guide.

11.0 Release History


Release Date Document Version /
Description
11.0 F000 December 2015 11.0.01 – 11.0 F000
release
11.0 M010 June 2016 11.01.01 – 11.0 M010
release
11.0 M020 December 2016 11.02.01 – 11.0 M020
release

Planned Updates
The Windchill Customization Guide in updated on a periodic basis between
Windchill maintenance releases. Check the Reference Documents site on PTC.
com for updates.

Release 11.0 Changes

Windchill Customization Basics


Chapter Changes / Release
Managing Customizations on page 100 • Modeled To Subtype Conversion on
page 133 was updated in 11.0 F000.
• Monitoring a Customized Windchill
Environment on page 160 was
updated in 11.0 M020.

14 Customization Guide
User Interface Customization
Chapter Changes / Release
User Interface Technology Overview • Windchill Client Architecture
on page 231 Overview on page 232 was updated
in 11.0 F000.
• MVC Components Overview
on page 258 was updated in 11.0
M020.
Customizing HTML Clients Using the • Component Access Control on page
Windchill JSP Framework on page 289 330 was updated in 11.0 F000.
• Attribute Panels
on page 348 was updated in 11.0
F000.
Generic UI Customizations on page • Customizing Role-Based UI
481 Functions - Attribute Visibility on
page 482 was updated in 11.0 F000.
• “Relationship Explorer” section
was removed in 11.0 M020.
Adding Actions and Hooking Them Up • Customizing Role-based Visibility
in the UI on page 511 on page 549 was updated in 11.0
F000.
• Adding Custom Content to the
Home Page
on page 578 was added in 11.0
M020.
Presenting Information in the UI on • Attribute Customization on page
page 603 658 was updated in 11.0 F000 and
11.0 M010..
• Dynamically Resolved Attributes
for Customizations on page 604
was updated in 11.0 F000.
• URL Authorization on page 823
was added in 11.0 M010.
• Creating Custom Graphical
Representations
on page 749was added in 11.0
M020.

15
Chapter Changes / Release
Constructing Wizards on page 837 • Customizing Reusable Wizard
Steps
on page 928 was updated in 11.0
F000.
• Configuring a Type Picker on page
1043 was updated in 11.0 M010.
Incorporating Pickers in JSP Clients on • Configuring a Participant Picker in
page 1005 JCA on page 1068 was updated in
11.0 F000.
• Configuring a Participant Picker in
AngularJS on page 1083 was added
in 11.0 F000.
Configurable Links on page 1089 • Configurable Link Tables on page
1090 was updated in 11.0 F000.
Customizing Online Help on page 1105 • Removed the “Uninstalling the
Windchill LearningConnector”
section in 11.0 M010.
• Customizing Windchill Help Center
Content on page 1107 was updated
in 11.0 M020.
Windchill Search Customization on • Customizing Indexing Behavior on
page 1119 page 1120 was updated in 11.0
F000.
• Customizing Faceted Search
on page 1128 was added in 11.0
M010.
• The “Developing a Custom Search
Application” section was removed
in 11.0 M010.

16 Customization Guide
Business Logic Customization
Chapter Changes / Release
Customizing Business Logic on page • Context Builder Customization
1157 Example
on page 1163 was updated in 11.0
F000.
• Reservation Service on page 1651
was added in 11.0 M010.
Customizing Change Management on • Change Workflow Closure
page 1169 on page 1243 was added in 11.0
F000.
• Customizing Business Rules
on page 1264 was updated in 11.0
F000.
• Flexible Change Links for Query
Builder
on page 1253 was added in 11.0
F000.
• Evaluating Business Rules On
Demand
on page 1219 was updated in 11.0
F000.
Customizing Workflow Administration • Multiple Participant Selection
on page 1311 Wizard Customization
on page 1374 was updated in 11.0
F000.
• Locking Annotations In Change
Workflows
on page 1398 was added in 11.0
F000.
Customizing Life Cycle Administration • Defining Custom Life Cycle
on page 1401 Transitions on page 1404 was
updated in 11.0 M010.
Customizations in Type and Attribute • Using a BusinessAlgorithm in a
Management on page 1415 Calculated Attribute
on page 1416 was added in 11.0
F000.
Customizing Windchill Visualization • Interference Detection
Services on page 1453 on page 1479 was updated in 11.0
F000.

17
Chapter Changes / Release
Report Generation on page 1491 • Java Methods on page 1497 was
updated in 11.0 F000.
Packages Customization on page 1565 • Package Type-Based Properties
on page 1566 was updated in 11.0
M020.
DTI Customization Framework on page • Customize the DTI Document
1599 Search Window on page 1620 was
updated in 11.0 F000 and again in
11.0 M020.
• Using DTI with Form-Based
Authentication on page 1621 was
updated in 11.0 M020.
Customizing Action Item Attributes • Customizable Action Item
on page 1623 Attributes on page 1624 was
updated in 11.0 F000.

18 Customization Guide
Chapter Changes / Release
Data Exchange using Standards in • STEP Data Exchange using
Windchill EXPRESS
on page 1661 on page 1699 was updated in 11.0
F000.
• STEP Foundation
on page 1700 was updated in 11.0
M010 to add Configuring Metadata
Mapping on page 1762
• AP242 XPX Mapping Guide
on page 1806 was added in 11.0
M010.
ThingWorx • Adding a ThingWorx Mashup to
on page 1905 Windchill
on page 1906 was added in 11.0
M020.

Services and Infrastructure Customization


Chapter Changes / Release
Customizing LDAP Attributes on page • Customizing LDAP Mapped
1993 Attributes in a User Information
Page
on page 1994 was updated in 11.0
M020.
• Customizing LDAP Mapped
Attributes in a Group Information
Page
on page 1997 was updated in 11.0
M020.
• “Customizing LDAP Mapped
Attributes in Audit Reports” was
removed in 11.0 M020.
Customizing Modeled Elements on • Customizing Column Lengths on
page 2051 page 2052 was updated in 11.0
F000.

19
Changes in Release 10.1 M010 through Release 10.2
M030
The following updates were made in the Windchill customization documentation
in the 10.1 M010 through 10.2 M030 releases.

Windchill Customization Basics


Chapter Changes / Release
Getting Started With Windchill • Creating a UI
Customization on page 55 on page 68 was updated in 10.2
M030
Managing Customizations on page 100 • Updated Best Practices for Adding
New Packages and Files on page
129; added Compiling Custom
Classes on page 132 in 10.1 M010.
• Added Modeled To Subtype
Conversion on page 133 in 10.1
M010. Updated again in 10.1 M040
and 10.2 M030.
• Added Monitoring a Customized
Windchill Environment on page
160 in 10.1 M040.
• Customization with Windchill
Queues
on page 161 was added in 10.2
F000.

20 Customization Guide
User Interface Customization
Section Changes
User Interface Technology Overview • Windchill Client Architecture
on page 231 Overview on page 232 was updated
in 10.1 M030. It was removed in
10.2 M030.w
• Javascript Functions Overview on
page 248 was updated in 10.2
M030.
• Adding Custom Code to all
Windchill Client Architecture Pages
on page 255; added Color
Customizations in the Reference
Designator Differences Column on
page 256 in 10.1 M020.
Customizing HTML Clients Using the • “Customizing UI Branding” was
Windchill JSP Framework on page 289 updated in 10.1 M030.
• Customizing the UI with Ajax on
page 291
• Split Pane / Two Pane
on page 463 was updated in 10.1
M030.
• Updated Customizing the UI with
Ajax on page 291 in 10.1 M010.
• Component Access Control on page
330 was updated in 10.2 M030.
• Configuring the Drag and Drop
Zone
on page 478 was added in 10.2
M030
• Customization Tools Overview on
page 404 was updated in 10.1
M040.
Generic UI Customizations on page • System Banner Alert Message on
481 page 506 was updated in 10.1 M10
and again in 10.2 M030.
Adding Actions and Hooking Them Up • Action Framework for Windchill
in the UI on page 511 Client Architecture on page 512
was updated in 10.1 M010.

21
Section Changes
Presenting Information in the UI on • The “Generating the Name
page 603 Attribute Server” section was
removed in 10.2 F000.
• Attribute Customization on page
658 was updated in 10.2 M030.
• Constructing and Rendering a Table
Using the JSP Framework on page
606 was updated in 10.1 M030.
• Windchill Client Architecture Tree
on page 642 was updated in 10.1
M030.
• Attribute Customization on page
658 was updated in 10.2 M030.
• Generating the Name Attribute
Server was removed.
• Dynamically Resolved Attributes
for Customizations on page 604
was updated in 10.1 M040 to
remove rich text from list of
standard attribute supported data
types
Constructing Wizards on page 837 • Wizard Processing on page 866 was
updated in 10.1 M010.
• Building Wizards to Create a Single
Object on page 892 was updated in
10.1 M010.
• Building Wizards to Edit a Single
Object on page 914
• Client Generated Form Data
on page 964 was updated in 10.1
M010.
• Wizard Processing on page 866 was
updated in 10.1 M030.
• Client Generated Form Data
on page 964

22 Customization Guide
Section Changes
Customizing Online Help on page 1105 • Adding Topics to the Help Center
TOC
on page 1108 was added in 10.1
M020.
Windchill Search Customization on • Customizing Solr on page 1122 was
page 1119 updated in 10.2 M030.
○ Custom Solr Help Link on page
1122 was updated in 10.2
M010.
• Windchill Search Customization on
page 1119 was added in 10.1 M010.

Business Logic Customization


Section Change / Release
Customizing Business Logic on page • Customizing a Bill of Materials on
1157 page 1158 was updated in 10.2
M030. The “Customization” and
“Current Implementation of
Visitors” subsections were
removed.
• Mass Change Operations
on page 1185 was updated in 10.2
M030
• Replicated Objects as Change Task
Resulting Objects
on page 1213 was added in 10.2
F000.
• Evaluating Business Rules On
Demand
on page 1219 was added in 10.2
M010
• Editing Attributes on the Links of
Change Relationship Tables
on page 1228 was added in 10.2
M010 (Document Version 10.2.03).
Business Rules • Loading Business Rule Objects
on page 1263 on page 1291 was added in 10.2
M030.

23
Section Change / Release
Customizing Workflow Administration • Customizing Workflow Task Pages
on page 1311 on page 1335 was updated in 10.2
M030.
• Customizing Change Activity
Workflow Assignments
on page 1382 was added in 10.2
F000.
• Customizing Change Tables
Designed for Workflow
on page 1392 was added in 10.2
M030.
Customizing Security Labels on page • Customizing Security Labels on
1431 page 1432 was updated in 10.2
M030.
Customizing Windchill Visualization • Customizing Publishing Queues
Services on page 1453 on page 1473 was added in 10.2
M030
• Modifying the Default Behavior of
Dynamic Part Generation
on page 1487 was updated in 10.2
M010
Report Generation on page 1491 • Updated the Report Selection List
Customization on page 1554 topic
with information on customizing
the PSB ribbon toolbar in 10.2
M030
Packages Customization on page 1565 • Package Type-Based Properties
on page 1566 was updated in 10.2
F000.
• Identifying Users in Context
Replication and Activating
Replicated Users on page 1580 was
added in 10.2 F000.
• Select Files – Copy Forward
Exclusion Decisions
on page 1594 was added in 10.2
F000.
• Windchill Replication Package
Command Line Sample Scripts

24 Customization Guide
Section Change / Release
on page 1597 was added in 10.2
F000.
DTI Customization Framework on page • Add Custom Attributes to Microsoft
1599 Office on page 1600 was updated in
10.2 M030.
• Customize Windchill Actions in
Windows Explorer on page 1617
was updated in 10.2 M010 and
M030..
Data Exchange using Standards in • The “AP214 AIM Mapping”
Windchill section was removed in 10.2 M010.
on page 1661. This chapter was • STEP Data Exchange using
renamed from “STEP Support in EXPRESS
Windchill” in 10.2 M020. on page 1699 was added in 10.2
M010. It was further updated in
10.2 M030.
• PLCS Data Exchange
on page 1867
Windchill Workgroup Manager This chapter was added in 10.2 M030
Customization
on page 1881
Customizable Action Item Attributes on This chapter was updated in 10.2 F000.
page 1624

Services and Infrastructure Customization


Chapter Section
Form Based Authentication • Entire section was removed in 10.1
M010. Information can now be
found in the “Authentication”
section in the Windchill Advanced
Deployment Guide.
System Generation • Modeling Business Objects
on page 1943 on page 1944 was updated in 10.1
M010
• Creating New Tablespaces
on page 1971 was added in 10.2
F000

25
Chapter Section
Enumerated Types on page 1973 • External Enumerated Value Lists
on page 1984 was added in 10.2
F000
Customizing Modeled Elements on • Customizing Column Lengths on
page 2051 page 2052 was updated in 10.1
M030
• How to Write an IX Application on
page 2130 was updated in 10.2
F000
• How to Write Exp/Imp Handlers on
page 2146 was updated in 10.2
F000
• Adding Export Functionality in the
Project Plan Table
on page 2188 was added in 10.1
M020

26 Customization Guide
1
Windchill Customization Basics
Configuration Options ................................................................................................30
Customizations .........................................................................................................33
Windchill Customization Points...................................................................................36
Directory Structure ....................................................................................................40
Environment Variables ...............................................................................................46
Property Files............................................................................................................47
Properties and Property Files .....................................................................................51
Example Overview ....................................................................................................56
Windchill Development Environment...........................................................................57
Customization Setup .................................................................................................58
Creating the Class .....................................................................................................59
Creating a UI.............................................................................................................68
Customizations — Next Steps ....................................................................................90
Windchill Modeling Heuristics .....................................................................................92
Windchill Foundation Abstractions ..............................................................................95
Setting Up a Directory Structure for Managing Customized Files and Text
Tailoring .............................................................................................................. 101
Best Practices for Customizing Files Supplied by PTC ............................................... 109
Best Practices for Adding New Packages and Files.................................................... 129
Modeled To Subtype Conversion .............................................................................. 133
Monitoring a Customized Windchill Environment........................................................ 160
Customization with Windchill Queues........................................................................ 161
Using the xconfmanager Utility ................................................................................. 164
Formatting Property Value Guidelines ....................................................................... 176
Windchill Command................................................................................................. 177
Windchill Shell ........................................................................................................ 180
Tutorial Overview .................................................................................................... 182
Create Administrator and User ................................................................................. 184
Create a Library and Document ................................................................................ 194
Allocate Database Columns for Local Attributes......................................................... 200
Create a New Attribute Definition and Add it to the Document Type ............................. 202

27
As the End User, Create a Document with the new Attribute ....................................... 209
Create a Document Subtype .................................................................................... 212
Create an Instance of the New Document Subtype .................................................... 216
Model a New Document Subclass ............................................................................ 217
Create an Instance of the New Document Subclass ................................................... 224
Verify the Customizations......................................................................................... 227
Customization Tutorial Summary .............................................................................. 228

This section contains information related to the basics of Windchill customization.

28 Customization Guide
2
Customization Overview
Configuration Options ................................................................................................30
Customizations .........................................................................................................33
Windchill Customization Points...................................................................................36

The Windchill solutions are designed to fit the needs of customers in different
industries and of different sizes. The Windchill solutions are built to enable
product development business processes. Input for these solutions comes from the
many PTC customers who are leaders in their domains and from PTC industry
experts.
In order to reduce the cost of ownership, the Windchill solutions provide extensive
out-of-the-box capabilities and configuration options to make them easily
adaptable to these disparate customers and their different product development
processes and needs.
Where the configuration options do not provide sufficient flexibility and no
appropriate out-of-the-box capabilities are available to satisfy a particular business
need, Windchill provides an extensive set of customization features that customers
can leverage to satisfy such business needs.

29
Configuration Options
Properties and Preferences
Windchill provides an extensive set of options that control how the system
behaves, how the user interacts with the system, or how the system presents itself
to the user. These options are either properties or preferences.

Properties
Properties are created in text files in the Windchill codebase and control overall
system configuration. For example, the wt.home property contains the path to
the installation directory. Properties are stored in files with the .properties
extension. Changing most properties requires a restart of the Windchill method
server.
See Property Files on page 47 for some additional information on property files. A
complete set of properties and descriptions for the wt.properties,
tools.properties, and db.properties files can be found in the
properties.html file in the Windchill codebase directory.

Preferences
Preferences are set through the Windchill user interface and do not require a
server restart. They control application behavior (for legacy reasons, some
Properties also control application behavior). Preferences can be implemented on
different levels of detail. Preferences can be configured to control the whole
Windchill installation, or can be used more narrowly to control an organization’s
or an application container’s (e.g. Product, Library), or a specific user’s setup.
See Preference Framework on page 495 for some additional information on
preferences.
The table below provides just a few of the available preferences:
Preference Description
Change Notice without Change Request Allows creating a change notice
without a change request.
Enable Structure Propagation Enables propagation of effectivity
statements down a product structure.

30 Customization Guide
Preference Description
Digest Notification Schedule Set up a schedule for Digest
Notification. That is, instead of sending
individual notification of as events of
interest to a user happen, the system
will collect and send all notifications in
one email according to the
administrator-setup schedule.
Display Thumbnails Controls whether the thumbnail action
available in tables.

Object Initialization Rules


A business analyst can set up rules that tell the system how to initialize newly
created objects.
For example, the business analyst can set the system up to number parts according
to the company’s part numbering policies (e.g. auto-number). The business analyst
may also set the system up to require the user to enter a manual number, or
alternatively, set the system up so that if the user does not enter a number, the
system will assign one.
As another example, the business analyst can set the system up to automatically
assign objects of certain types to certain workflows; or, alternatively, the business
analyst can configure the system with appropriate workflows by object types and
it will be up to the end user to select the appropriate workflow to use. For more
sophisticated needs, the business analyst can set the system up to route an object
appropriately based on the values of meta-data attributes provided by the end user.
Object initialization rules provide significant flexibility in adapting a Windchill
system to a specific customer’s environment and business process needs. For
additional information, see the “Object Initialization Rules” topic in the Windchill
Help Center.

Workflow Templates
Windchill provides a very powerful workflow configuration and execution engine.
The workflow engine of Windchill can model virtually any business process
which can be modeled via an easy-to-use drag-and-drop tool.
The workflow engine has an embedded java virtual machine which allows a
business analyst to embed java expressions and process logic where appropriate.
For more information on workflow templates see the online help topic
“Customizing Workflow Administration” in the Windchill Help Center.

Customization Overview 31
Soft Typing
• Soft Typing is the name of the set of Windchill capabilities that allows a
customer to, at runtime, add additional types and attributes to the out-of-the-
box Windchill Schema. This is done without having adding additional tables
to the database, without restarting the database, and without restarting the
system.
• With the Soft Typing capabilities, customers can add data types and meta data
attributes that are meaningful to them and which are necessary for their
business processes. For all intents and purposes, these customer-defined types
are no different than any other out-of-the-box object in the system: Types can
assigned access control rules, can be assigned workflows and lifecycles, can
be assigned custom UIs, can have Object Initialization Rules assigned to them,
are accessible via APIs, etc.
No user interface modifications are necessary as the Windchill user interfaces
automatically accommodate (e.g. adapt to) these additional Types and Attributes.
The general guideline to be followed is this: If a need can be satisfied by soft
typing, then it should. That is, do not customize (i.e. create modeled extensions) to
the out-of-the-box schema. The reason for this rule is to minimize the total cost of
ownership of Windchill and minimize upgrade costs and burdens. This, in no way,
is a limitation on the customizability of Windchill; but, rather, the intent of the
rule is to reduce the cost of ownership.

Organization and Container Templates


Creating an organization or an application container (e.g. Product/Library/Project/
Program) requires that you provide a template to initialize the container with. A
template allows you to configure the business rules of the created container. For
example, you can specify what approval processes are to be followed, who has
access to create and/or view information, what roles are required and who the role
players are, what numbering and versioning rules should be followed, etc.

32 Customization Guide
Customizations
Windchill is an open system that is fully supports customizations at the schema,
server, and UI levels. An extensive set of APIs are published, documented, and
supported to enable these customizations. But as stated above, in order to reduce
the cost of ownership, if changing other mechanisms such as properties or
preferences satisfy the business need, then customizations should not be used.

Data Model Customizations


Windchill Information Modeler is one of the Windchill development components
that can be used to customize your Windchill environment. Information Modeler
contains the Windchill modeling files and source code that you will use to develop
your customizations. Custom Java Annotations are used to model business
objects. Windchill then uses this model to generate code that is used in server and
client development.
Information Modeler provides the most powerful capabilities for creating custom
business objects and relationships in Windchill systems, but requires greater
development skills and is less flexible than using subtypes. For example, subtypes
can be added and changed by an administrator while the system is running, but
model changes must be made by a skilled Java developer during strictly managed
checkpoints. On the other hand, modeled objects can be created by assembling
specific collections of Windchill plug-and-play interfaces to create unique server
behavior but subtypes can only be created as super types of existing modeled
classes with additional attributes.
For more information on Java Annotations see Modeling Business Objects on
page 1944 .

Service Customizations
Windchill supported server-side customizations to enable certain business
processes or enforce business constrained. Any kind of customization can be
performed. The most common types of customizations falls into one of the
following categories:
• Process form data submitted through the user interface
• Validate data - (e.g. Do not allow the user to enter a Need Date for a Change
Request that is more than 30 days into the future)
• Implement service listeners - (e.g. Create a listener that waits for any data to
be checked in and populate an MRP system with appropriate data)
• Get/Put data in an external systems - (e.g. when the user navigates to a part’s
details, get the cost of the part from the ERP system and display it in the same
UI)

Customization Overview 33
User Interface Customizations
The Windchill Client Architecture is a Windchill-aware JSP framework. It
provides very high-level building blocks known as common components which
make Windchill UI development a very efficient process done with ease.
Javadoc and learn-by-example documentation is available to reduce the learning
curve and increase developer productivity.
For more information on user interface customizations see Generic UI
Customizations on page 481.

Info*Engine
Info*Engine provides data access and integration capabilities to access Windchill
data, remote Windchill systems and non-Windchill data and services (through
adapters). Info*Engine components can be used in many different software and
hardware configurations to meet your business requirements for accessing,
managing, and presenting data from many different information systems.
All basicInfo*Engine solutions take advantage of five fundamental concepts: JSP
pages, tasks, webjects, groups, and the virtual database. Both JSP pages and tasks
are text-based documents that define howInfo*Engine either displays or retrieves
information. Webjects are the means by whichInfo*Engine JSP pages and tasks
gather, manipulate and display data. Groups are the chunks of information
generated and manipulated by JSP pages and tasks. The virtual database (VDB) is
the special holding area where groups are stored until they are manipulated or
passed along by JSP pages and tasks.
• For general information onInfo*Engine see the Info*Engine User's Guide.
• For information onInfo*Engine customizations see Managing Windchill
Info*EngineTasks on page 113.

Custom Reports
Windchill provides predefined, out-of-the-box reports in the areas of change
management, project item status, and parts/products. Your company-specific
custom reports can be created using Windchill Query Builder or the Windchill-
integrated third-party report authoring tool, Cognos.
Use Windchill Query Builder if you would like to create very simple tabular
reports and your site is not configured for third-party reporting tool, Windchill
Business Reporting.
Windchill Business Reporting (WBR) is a new reporting framework that embeds
Cognos Business Intelligence (BI) within Windchill to provide out-of-the-box
integration between Windchill and Cognos BI. It also includes pre-built reports on
change management, project items status, and parts/products.

34 Customization Guide
To create tabular reports, visual and graphical reports, dashboard reports, and
drill-down reports, use the optional third-party reporting authoring tool. This
optional authoring tool also allows you to modify out-of-the-box reports. Using
the authoring tool you can create new reports that include charts and graphs
(Crosstabs, bar/3D bar, pie, gauge, funnel, scatter and more). The report data
sources that are required for creating custom reports in report author tool can be
created using Info*Engine report tasks and Query Builder templates.
For more information on custom reports see Report Generation on page 1491.

Customization Overview 35
Windchill Customization Points
Windchill is composed of thousands of Java classes. To help you focus your
customization efforts, certain Windchill Java classes have been designated as
belonging to the Windchill Supported API. To customize Windchill, you should
interact only with the classes in the Windchill Supported API. The Javadoc
provided with Windchill defines the Supported API.

Windchill Supported API


The Windchill Supported API includes those classes that customizers are meant to
work with directly. A class might be in the Supported API because it is meant to
be extended by customizers or, more likely, because it has some methods for
customizers to call. Programming elements that are part of the Supported API will
not be changed without notification and a deprecation period, whenever possible.
The deprecation period for a particular supported API begins with release that the
Javadoc for that element first declares that it is deprecated. The deprecation period
ends when support for that release ends. For Windchill release maintenance
information, see the PTC product calendar at this URL:
http://www.ptc.com/cs/product_calendar/PTC_Product_Calendar.htm
Classes, methods, and other programming elements that are not part of the
Supported API should not be used directly by customizers. Those elements are
subject to change without notification or a deprecation period.
To determine if a class, or one of its methods, is part of the Supported API,
consult the Javadoc for that class. For each class, the Javadoc contains a
Supported flag, and an Extendable flag. Individual methods within a Supported
class may also be flagged as Supported.

36 Customization Guide
If a class (or method) is flagged as Supported: true, it indicates that the class
or method may be referenced by customized code. If a class is flagged as
Extendable: true, it indicates that the class may be extended. For example,
WTPart is both Supported and Extendable, as shown in the following illustration.

The fact that a class is part of the Supported API indicates that some part of it is
meant to be used, or at least understood by customizers. The Javadoc for some
classes is distributed for information purposes (and if that is the case, it should be
clear from the Javadoc). A class is meant to be extended only if its Javadoc
contains the line indicating “Extendable: true”. (Classes that can be extended are
listed in Appendix B, Extendable Classes in the Windchill Supported API.)
Methods and other programming elements may also have a “Supported API” line
in their Javadoc. If a class is not part of the Supported API, then neither are any of
its methods. If a class is part of the Supported API, that does not indicate that its
methods are, too. For a method to be part of the Supported API, its Javadoc must
also state “Supported API: true”.

Customization Overview 37
3
The Windchill Development
Environment
Directory Structure ....................................................................................................40
Environment Variables ...............................................................................................46
Property Files............................................................................................................47
Properties and Property Files .....................................................................................51

This chapter describes the Windchill development environment.

39
Directory Structure
The image below shows the Windchill directory structure after you install all
available components. If Windchill was installed as recommended to follow this
structure, go to the home directory where Windchill is installed and navigate
through this structure as it is described here.

Windchill Directory Structure


ant
Installation of supported version of Ant.
apacheConf
Contains configuration files forPTC HTTP Server (powered by Apache) and
Windchill
bin
Contains various batch scripts, such as ToolsSetup.bat.

40 Customization Guide
buildlogs
Default location for logs created by running Windchill Ant scripts.
cgi-bin
Contains the Windchill common gateway interface wrappers.
codebase
Contains the runtime environment files.
conf
Configuration files for PTC HTTP Server, Info*Engine and other applications.
db
Contains the database properties file and SQL scripts.
ieconnector
Contains the Info*Engine JCA (Java Connector Architecture) which is used for
J2EE integrations (EJB or App Server connectivity). It is also used by
Info*Engine JCA enabled standalone java SOAP clents.
installer
Contains files used by, or created by, the installation process, including
installation logs.
ldif
Files related to PTC's InterComm Viewer.
lib
Contains the wtbeans.jar file, which holds the Java bean components that have
been developed for use with Windchill clients.
loadFiles
Contains files used to load initial data.
loadXMLFiles
Contains new style xml files used to load initial data.
logs
Default location for trace logs when logging is turned on.
Module
Contains Windchill modules' model files, which are used for customization
development.
opt
Install folder for some optionally installed functionality.
prog_examples
Contains Info*Engine program examples

The Windchill Development Environment 41


src
Contains files for customizations, and rbInfo files for text.
srclib
Contains module jar files.
step
Contains STEP application related files.
taskeditor
Contains the Info*Engine task editor startup scripts, help files reside and is the
runtime directory for the task editor.
tasks
Contains Info*Engine tasks.
tomcat
Embedded Servlet Engine (based on Tomcat) installation.
temp
Temporary files used by Windchill.
Upgrade
Contains files to facilitate the upgrade process.
utilities
Contains various Windchill utilities.
vaults
Default file vault location.
WHC
Contains the Windchill Help Center which consists of the online help.
WinDU
Directory of xml files that declare the existence of tasks that are executable by the
Windchill Diagnostic Utility.
The codebase directory and src directory are described in more detail in the
following subsections.

42 Customization Guide
The codebase Directory
In general, the codebase directory contains executable class files, property files,
and other files that contain information needed by the runtime environment for
Java and Web processing. The codebase directory can be expanded to show the
following directories.

The codebase Directory

The Windchill Development Environment 43


Note
To allow presentation in manual format, many subdirectories in the wt
directory are not included in this figure.

Most of these directories contain third party product class files.


The html directory contains templates that are used to generate HTML
dynamically.
The wt and com\ptc directories contains the executable code for the packages
supplied by Windchill (only a subset of which are shown in this illustration) and
files required for localization, such as resource bundles and HTML files.
Within these packages are executable class files compiled from corresponding
Java files of the same name in the src\wt directory. This set of Java source or .java
files is for every business object.
Files in the form <object> .ClassInfo.ser are generated and contain
metadata needed by the runtime environment. They are all described in more
detail in System Generation.
Each package also contains resource bundles, that is, files that contain localizable
information and are in the form:
• <packageName>Resource.class
• <packageName>ModelRB.RB.ser
• <EnumeratedTypeClassName>RB.RB.ser

44 Customization Guide
The src Directory
In general, the src directory contains the source files needed for application
development. The src directory can be expanded to show the following
directories.

The src Directory


The wt and com\ptc directories contains the source files for the packages supplied
by Windchill (only a subset of which are shown in this illustration).
In the wt directory and its package subdirectories, you will see the following kinds
of files:
• Localizable ResourceBundles (.rbInfo and .java) files, which contain
customizable display text for EnumeratedTypes and business elements and UI
strings.

The Windchill Development Environment 45


Environment Variables
The environment variables required for running Windchill tools and utilities will
be defined by starting a Windchill shell. The Windchill shell is described in more
detail in Windchill Utilities on page 163.

46 Customization Guide
Property Files
Windchill uses standard Java property files to determine runtime configuration
properties.
The codebase directory contains:
• wt.properties
Contains properties used for general Java system configuration and Windchill
system configuration.
• service.properties
Contains properties used by the Windchill service delegate mechanism.
• user.properties
Contains user overrides used by resource bundle and sql script generation
tools.
• moduleRegistry.properties
Contains list of registered modules.
• moduleDir.properties
Contains home directory for each registered module.
The db directory contains:
• db.properties
Contains properties used by the Windchill database connection layer to access
the database.
The System Generation jars (SystemGeneration.jar,
WindchillUtil.jar & CommonCore.jar) contain:
• tools.properties
Contains properties used by resource bundle and sql script generation tools.
• debug.properties
Contains properties used by Windchill code to control debug info capturing.
• service.properties
Contains properties used by the Windchill service delegate mechanism, for the
System Generation tools.
• typedservices.properties
Contains properties used by the Windchill service delegate mechanism, for the
System Generation tools. You must use typedservices.properties when the
selector object type could be a subtype.
• wt.properties

The Windchill Development Environment 47


This is an abbreviated form of the file that is in codebase.
(Care must be taken when using a manually created classpath that includes
both codebase and System Generation jars, since properties files will be
loaded based on the order of the classpath components.)
The following sections discuss only a subset that you as a developer are most
likely to be interested in. A complete set of properties and descriptions for the wt.
properties, tools.properties, and db.properties files can be found in the properties.
html file in the codebase directory.

wt.properties file
To use Windchill, the following properties must be set in the wt.properties file
(this is usually done at installation). Note that you must use double back slashes to
specify path names in the wt.properties file. This is necessary because the string is
read by a Java program.
• wt.home, which specifies the top level of the class directory structure where
Windchill is installed. The default value is c:\\windchill.
• wt.server.codebase, which is used by client applications (not applets). It
specifies a URL from which client applications can download server resources
such as property files. Client applets use their own codebase URL as specified
in their APPLET tags. Server applications may use this property when writing
dynamically generated HTML to be returned to a client browser. It is used to
build URLs for static resources such as images or HTML files that reside
under the server’s codebase directory.
• java.rmi.server.hostname, which specifies a host name used to identify the
server host. It is used by the Java RMI runtime for clients to look up the IP
address of the server. It can be specified as a symbolic name, such as a fully-
qualified Internet domain name, or numerically in dot notation (for example,
127.0.0.1). If not specified, the RMI runtime will use the name returned by
InetAddress.getLocalHost() method, which may return a name that is not
known to remote clients. We recommend that this property be set to the fully-
qualified Internet domain name of the server host.
You may also want to set the following properties:
• wt.access.enforce
This property enforces access control. By default. it is true. However, if you
are debugging and want to bypass access control temporarily, you can set it to
false.
• wt.logs.enabled

48 Customization Guide
This property enables and disables logging in applications that support it, such
as the Windchill Server Manager and Method Server applications. By default,
it is false. To write debugging messages to a log file, you must set it to true.
• wt.method.verboseClient and wt.method.verboseServer
These properties cause trace messages to be printed from the client-side and
server-side, respectively, of the method server remote interfaces. By default, it
is false. Turning on these properties causes trace information to be written to
logs for debugging purposes.
Similar properties are available for the server manager: wt.manager.
verboseClient and wt.manager.verboseServer.
In looking through the properties, you will see many service names followed by
the word “verbose” (for example, wt.access.verboseExecution and wt.access.
verbosePolicy). In general, these properties allow you to turn on debug tracing.

service.properties file
The service.properties file contains properties used by the Windchill service
delegate mechanism. This mechanism is a general facility for adding delegate
classes to an existing service to implement new, customized behavior. In this
context, service can mean any sort of Java mechanism that provides functionality
to other classes.
For example, assume a copy service exists that can make copies of certain classes
of objects. The service knows how to make copies only for objects of certain
classes: the classes for which copy service delegates have been created. Each
delegate implements an interface, defined as part of the copy service, that contains
the methods needed by the service. Once the delegate is created and put in the
codebase, the copy service is notified of its existence by adding an entry to the
service.properties file.
Generally, each service is accessed using a factory. The factory either returns
instances of delegates to perform services on particular classes of objects, or it
performs the operations on the objects itself by instantiating the necessary
delegates internally.
If a Windchill service supports customization by adding delegates, the description
of how to do the customization is described elsewhere in the documentation.

tools.properties file
• wt.generation.sql.dir, which specifies where SQL scripts will be generated.
• wt.generation.sql.xxxTablesSize, which sets default sizes for tables.

The Windchill Development Environment 49


Note
Because tools.properties is contained within the SystemGeneration.jar, user
overrides to these properties are placed in codebase\user.properties.

user.properties file
The user.properties file contains user overrides that are used by the System
Generation tools.

Note
Configuration overrides for System Generation should be configured in user.
properties using the xconfmanager utility.

db.properties file
The db.properties file contains properties that are used by the Windchill
persistence layer to access the database. They can be set in the wt.properties file
but are usually kept in a separate file identified by the wt.pom.properties entry.
Because a password is contained in this file, you should maintain it in a secure
location. The values in the separate file override the values in the wt.properties
file.
In the db.properties file, you must set the following properties:
• wt.pom.dbUser, which specifies the Oracle user name you or your Oracle
administrator defined for you. This user is the owner of Windchill tables and
stored procedures. There is no default; it must be set.
• wt.pom.dbPassword, which specifies the Oracle password you or your Oracle
administrator defined for you. There is no default; it must be set.
• wt.pom.serviceName, which is the service name you or your Oracle
administrator created. There is no default; it must be set.

50 Customization Guide
Properties and Property Files
In general, properties for Windchill out-of-the-box clients are grouped as follows:
codebase/service.properties – properties specifying the
TemplateProcessor, ActionDelegate, URLActionDelegate, and
FormTaskDelegate to use for a given action/object type
codebase/htmltemplate.properties – properties specifying the
HTML template to use for a given action/object type
codebase/htmlcomponent.properties – properties specifying the
HTMLComponent to be used for a given element
codebase/wt.properties – miscellaneous template processing properties
such as colors of various page components (wt.html.color.*), the text
encoding used for various locales (wt.template.encoding.*), and the
default parameters used for various page tags
(wt.templateutil.component.*)
The first three of these files contain properties for what are typically known as
“application context services.” These require special loading at runtime and are
described in more detail in the following section.
The properties in wt.properties are simple name/value pairs that are loaded
into a Java Properties class instance at runtime. You should not add to or modify
this file directly because it will be hard to maintain your customizations if
Windchill is reinstalled or upgraded. Instead, modify this file using the
xconfmanager command line utility. These are respectively described in the
Administering Runtime Services section of the Windchill Specialized
Administration Guide and in Using the xconfmanager Utility on page 164.
See the section Properties and Property Files for more information on the property
files used in Windchill.

Application Context Service/Resource Properties


These are properties, generally used by a factory class, for locating a delegate,
service, or resource. They have one of the following formats:
wt.services/svc/default/<Service Type>/< Selector >|null/<Requestor>/<Service
Priority Number>=<Service Class Name>/<duplicate or singleton>
or
wt.services/rsc/default/<Resource Type>/<Selector>|null/<Requestor>/<Service
Priority Number>=<Resource Name>

The first format is used to locate a Java service or delegate class to perform a
function or provide a service. The second format is used to locate a resource file
— for example, a HTML template file or an icon image file

The Windchill Development Environment 51


Definitions
• Service Type = the type of service or delegate referenced by this property
• Resource Type = the type of resource referenced by this property
• Selector = an identifier used to specify the context in which this service or
resource is to be used (for example, an action name)
• Requestor = the object class for which the service, delegate, or resource is to
be used
• Service Priority Number = a priority rating used to choose between valid
delegates (see below)
• Service Class Name = name of delegate or service class for the given Service
Type, Selector, and Requestor
• Resource Name = name or resource for given Resource Type, Selector, and
Requestor
• Duplicate or singleton = a flag to indicate whether the server should instantiate
a shared instance of a delegate class or create a new one for each use. If
neither is specified, duplicate will be used.
This is an example property for a template processor:
wt.services/svc/default/wt.enterprise.TemplateProcessor/AddAlternates/
wt.part.WTPartMaster/0=wt.part.AlternatesLocalSearchProcessor/duplicate

where
Service Type = "wt.enterprise.TemplateProcessor"
Selector = the action name "AddAlternates"
Requestor = "wt.part.WTPartMaster"

Note
Any service class that incorporates an HTTPState object should be made
duplicate. This would include instances of BasicTemplateProcessor,
and FormTaskDelegate, NavBarActionDelegate.

If a factory receives a request for a service or resource class for a given requestor
object class but no property entry for that requestor class is found, the factory will
attempt to find an entry for the parent class or interface of the requestor class. If
no entry for the parent class or interface is found, a search will be made for an
entry for the parent of the parent or interface, and so on. It could happen that
entries for two or more parent classes or interfaces are found. If the entries have
different service priority numbers, the one with the lowest number will be
selected. If the entries have the same service priority number, the one selected is
arbitrary.

52 Customization Guide
To be loaded correctly at runtime, files containing application context service
properties must be listed for one of the following properties in
wt.properties:
wt.services.applicationcontext.WTServiceProviderFromProperties.
defaultPropertyFiles
wt.services.applicationcontext.WTServiceProviderFromProperties.
customPropertyFiles

Property files will be loaded in the order listed, and files listed for
defaultPropertyFiles will be loaded before those for
customPropertyFiles. If the same property is found in more than one file,
the value for the one loaded last will be used. Any custom properties should be
placed in the latter list.
Except for the need to separate application context service properties from
ordinary properties and the effect of load order, the grouping of properties into
various properties files is unimportant to the system and based primarily on ease
of maintenance. If a TemplateProcessor property is put in the
htmltemplate.properties file instead of service.properties the system
will still find it.
Many of the more heavily customized service property files are not created or
edited directly but instead are generated from xml files. XML files used to
generate property files have the same name as the associated property file but
have the additional extension “.xconf”. For example, the XML file used to
generate service.properties is called service.properties.xconf.
See Managing Customizations on page 100 for more information on xconf files.
If you need to add application context property entries for your custom HTML
clients, we recommend you put them in a new properties file or files used only for
your customizations. This file should be added to the list of files for
WTServiceProviderFromProperties.customPropertyFiles using
the xconfmanager utility. This procedure is described in Managing Customizations
on page 100 .

Application Context Service Properties for Subtypes


The application context service properties in service.properties and other files
listed for
WTServiceProviderFromProperties.defaultPropertyFiles and
WTServiceProviderFromProperties.customPropertyFiles
cannot reference requestor object types that are subtypes. Properties for client
features that allow you to specify different services or resources for different
subtypes must be put in a property file listed for one of the following properties in
<Windchill>/codebase/wt.properties:
• wt.services.applicationcontext.TypeBasedService

The Windchill Development Environment 53


ProviderFromProperties.defaultPropertyFiles
• wt.services.applicationtext.TypeBasedService
ProviderFromProperties.
CustomPropertyFiles
If you need to add typed service property entries for your custom HTML clients,
we recommend you put them in a new properties file or files used only for your
customizations. This file should be added to the list of files for
TypeBasedServiceProviderFromProperties.CustomProperty
Files using the xconfmanager utility. This procedure is described in Managing
Customizations on page 100.

54 Customization Guide
4
Getting Started With Windchill
Customization
Example Overview ....................................................................................................56
Windchill Development Environment...........................................................................57
Customization Setup .................................................................................................58
Creating the Class .....................................................................................................59
Creating a UI.............................................................................................................68
Customizations — Next Steps ....................................................................................90

The Windchill product is highly customizable and provides various mechanisms


and APIs to customize business logic, user interfaces, and services and
infrastructure. The chapters that follow document these mechanisms, making it
possible to do everything from minorly tailoring a user interface to creating brand
new business objects with supporting user interfaces and server-side logic.
This chapter provides a “Hello, World!” introduction to Windchill customization
by introducing a new, persistent class and backing user interface. The example
assumes familiarity with Java and the Eclipse IDE. While not obligatory, Eclipse
is known to work well and project setup tools are provided.

55
Example Overview
The customization will introduce a new class, Pet. Pet will represent an animal (a
pet) and will define the following properties:
• name the name of the pet
• kind an enumeration consisting of dog, cat, gerbil, etc.
• dateOfBirth a date represeting the pet’s birthday
• fixed a boolean indicating whether the pet has been spayed or neutered.
Additionally, the Pet will incorporate the following:
• ContentHolder (a domain interface) to store pictures of the pet
• Ownable (a domain interface) to support assigning the pet to an owner
• WTObject (a base class) to provide basic functionailty.
Pets can be stored in the Windchill database and support basic “CRUD”
operations (Create, Read (query), Update, Delete). Additionally, the Windchill
user interface will be augmented to support CRUD operations against pets in the
browser. Note that the Pet example is not intended to be “complete”, nor is it an
example of a practical customization; it merely demonstrates a simple Windchill
customization introducing a new, persisted, and very basic class.

56 Customization Guide
Windchill Development Environment
The Pet example requires a Windchill installation with Information Modeler
installed. The install location is referred to as the “load point”, and may be a path
similar to /opt/ptc/Windchill or C:\ptc\Windchill. The example
uses the Eclipse IDE to author and compile source.
Pet itself is a Java source file and will reside in the load point/src directory. The
Ant script, tools.xml, found in load point/bin provides the following targets
which will be used throughout the example:
• eclipse_project generates an Eclipse project
• class compiles Java source code
• bundle builds the resource bundles for enumerations
• sql_script generates SQL scripts for persistent classes.
Each of these targets provides help (simply append .help to the names above).
Basic knowledge of Java, Ant, Eclipse (if you are using it), and persistence is
assumed throughout the example.

Getting Started With Windchill Customization 57


Customization Setup
Setup consists of two steps:
1. Start a Windchill shell
2. Install & configure Eclipse.

Starting a Windchill Shell


The Windchill shell (included in load point/bin/windchill) establishes
an environment suitable for customization. It is invoked as follows:
1. cd load point
2. bin/windchill shell
The Windchill shell adds Ant and Java to the PATH, configures various Ant
environment variables, sets the CLASSPATH to that of the MethodServer, and
sets Windchill to the load point directory.

Installing and Configuring Eclipse


Eclipse should be installed and configured. Follow the instructions produced by
the following command to get started:
ant -f bin/tools.xml eclipse_project.help

58 Customization Guide
Creating the Class
1. Begin by launching Eclipse (see previous section). The cust_Windchill_
src project should be open in Eclipse, which should look similar to the
following:

2. Create the Pet class.


a. Navigate to File ▶ New ▶ Class.
b. Set Package to com.acme
c. Set Name to Pet
d. Click Finish.

Getting Started With Windchill Customization 59


The result will be an empty class, as follows:

3. Make the Pet persistent.


a. Annotate the class declaration with @GenAsPersistable (note,
Control + Space will complete and, as Eclipse supports camel-completion,
it is possible to complete this by typing “@GAP” followed by Control +
Space; using Eclipse completion has the advantage that, generally, an
inability to complete is an indicator that some larger syntax error exists
that needs to be corrected)
b. Save Pet (Control-s). Pet will immediately show two compile errors, as
follows:

This is expected.
c. Resolve them by:
i. Making Pet extend _Pet.
ii. Adding the required declaration to Pet’s body
d. Save Pet again. Pet now extends _Pet, which implements
wt.fc.Persistable, resulting in two new errors.

60 Customization Guide
Rather than implement these directly, make WTObject the super class of
_Pet by adding superClass=WTObject.class to the annotation
above (both superClass and WTObject will complete, and Eclipse
will automatically import WTObject as part of the completion).
e. Save Pet again. The result, which will compile cleanly, is as follows:

f. Create the no-argument factory method for Pet, which consists of the
following:
public static Pet newPet() throws WTException {
final Pet instance = new Pet();
instance.initialize();
return instance;
}

Windchill persisted objects require the use of factory methods similar to


the “newPet()” factory method over constructors. They are paired with
initialize methods accepting the same arguments so child classes can
inherit logic present in the parent class’s methods. In this case, an explicit
initialize method is unnecessary as Pet does not contribute functionality;
here, the implementation inherited from WTObject is sufficient.
4. Add ContentHolder and Ownable to Pet. Windchill utilizes Java
interfaces to provide domain functionality to persistent business classes.
ContentHolder gives the ability to store files (content) and Ownable the
ability to take ownership of a business object.
a. Add “, interfaces={ContentHolder.class,
Ownable.class}” after the superClass annotation member. Make
sure to use Eclipse “Control + Space” completion auto-import the
interfaces
b. Save Pet
5. Add name, dateOfBirth, and fixed as properties to Pet.
a. Declare the properties annotation member by adding a comma after the
closing “}” of interfaces, then adding a newline, and then inserting the

Getting Started With Windchill Customization 61


following (the annotation’s closing parethensis is shown): properties=
{ })
b. All properties will be included between the “{}”s for properties, each on
their own line. First, add name as follows:
@GeneratedProperty(name="name", type=String.class,
columnProperties=@ColumnProperties(index=true),
constraints=@PropertyConstraints(required=true, upperLimit=60))
This property declares name, of type String. The name is required,
must be 60 characters or less in length, and will be indexed in the database.
Most of this can be code-completed by the IDE, reducing significantly the
amount of effort needed to enter it
c. Next, add dateOfBirth immediately following name. It will be
necessary to add a comma to the previous line to separate the two
declarations:
@GeneratedProperty(name="dateOfBirth", type=Timestamp.class)
Here, dateOfBirth is a java.sql.Timestamp.
d. Finally, add fixed (a boolean): @GeneratedProperty(name=
"fixed", type=boolean.class)
6. Create PetKind, an enumerated type consisting of common pet kinds.
a. Navigate to File ▶ New ▶ Class.
b. Set Package to com.acme
c. Set Name to PetKind
d. Click Finish.
Add the GenAsEnumeratedType annotation to the class declaration and
make the class extend _PetKind (ignore the warning). The result will look as
follows:

7. Create PetKindRB.rbInfo, a resource bundle storing kinds of pets.


a. Select PetKind.java and Type Control-N.
b. Select General ▶ File and click Next.
c. Give PetKindRB.rbInfo as the File name.
d. Click Finish.

62 Customization Guide
e. Make the contents of PetKindRB.rbInfo as follows (and save it):
ResourceInfo.class=wt.tools.resource.EnumResourceInfo

dog.value=Dog
dog.order=10

cat.value=Cat
cat.order=20

gerbil.value=Gerbil
gerbil.order=30
8. Add kind to Pet.
a. Place kind between name and dateOfBirth:
@GeneratedProperty(name="kind", type=
PetKind.class, constraints=
@PropertyConstraints(upperLimit=40))
The stored value of an enumerated type is the key value (dog, cat, gerbil)
as opposed to the display value (Dog, Cat, Gerbil). An upper limit of 40
was specified as it’s a more than sufficient value to store the keys.
9. Verify the result. Note that, as a minor clean-up, all the separate annotations
imports have been reduced to a single “*” import:

10. Compile PetKindRB.rbInfo.

Getting Started With Windchill Customization 63


a. Find or start a Windchill shell (command assumes shell is in Windchill
directory).
b. run the following command: ant -f bin/tools.xml bundle
-Dbundle.input=com.acme.*
11. Ensure Pet, PetKind compile with Ant.
a. Reuse Windchill shell from previous command
b. ant -f bin/tools.xml class -Dclass.includes=com/
acme/** -Dclass.force=true
12. Generate SQL scripts.
a. Reuse, again, Windchill shell
b. ant -f bin/tools.xml sql_script -Dgen.input=
com.acme.*
13. Load schema for Pet.
a. Locate, under load point/db, Make_pkg_acme_Table.sql.
i. Oracle (single byte): db/sql/com/acme/Make_pkg_acme_
Table.sql
ii. Oracle (multi-byte): db/sql3/com/acme/Make_pkg_acme_
Table.sql
iii. SQLServer: db/sqlServer/com/acme/Make_pkg_acme_
Table.sql
b. cd to the db/<xxx> directory from above (db/sql, db/sql3, or db/
sqlServer)
c. Run the script
i. Oracle: sqlplus <database credentials> @com/acme/
Make_pkg_acme_Table.sql
ii. SQLServer: …
d. Repeat for @com/acme/Make_pkg_acme_Index.sql

Verifying the customization


The customization is incomplete: no user interface (UI) exists to manage Pet
objects. Nevertheless, the customization is complete enough to verify that CRUD
operations against Pet objects are possible, as the following Jython code
demonstrates. To invoke the example:
1. Download (and install) the latest version of Jython from http://www.jython.org
2. Start (or restart) the MethodServer

64 Customization Guide
3. Start a Windchill shell
4. Run jython, which – without arguments – will start the Jython interpreter.
Jython is a Java implementation of the Python programming language and, while
Jython uses Python’s syntax, it will be readily familiar to a Java programmer.
Jython brings two important advantages of a Java class with a main method:
• Jython is dynamic: methods can be typed in the interpreter, are immediately
invoked by the interpreter, and the result of the invocation is immediately
available. This, sometimes refered to as a “REPL”, offers a level of interaction
with code unparalleled by a static class file, even when debugged in a
debugger. Furthermore, Jython’s dynamic nature precludes typing variables,
casting, writing try/catch blocks (unless this is desired), and so on, resulting in
significantly shorter code than Java’s equivalent.
• Jython interacts seamlessly with Java: Jython brings Python to Java without
sacrificing Java. Jython is “pure Java” and can instantiate any Java class and
call any Java method or access any Java field (within the restrictions of the
Java security model). Beyond simply being able to interact with Java, Jython
is notable in that the “impedance mismatch” between it (as a Python
implementatiotn) and Java is very small, making interaction with Java simple,
predictable, and easy and making conversion to straight-Java trivial.
Jython is not the only language on top of the Java virtual machine. Notably,
there’s also Groovy, JRuby, BeanShell, and even JavaScript. All are worth
exploring and all have different approaches and philosophies worth discovering,
however, Jython excels in simplicity, interactivity, and in the quality of its
interpreter.
The following code snippets should be executed in the Jython interpreter. While
segmented, they should be invoked in the same interpreted session. The segments
can also be combined into a single script that is then executed by Jython; if done,
note that Jython won’t automatically print like it does in the interpreter.
1. Import the Java classes necessary to do CRUD against Pet objects:
from java.sql import Timestamp
from java.text import SimpleDateFormat

from com.acme import Pet, PetKind


from wt.fc import PersistenceHelper
from wt.ownership import OwnershipHelper
from wt.query import QuerySpec, SearchCondition
2. Create two pets:
dog = Pet.newPet()
dog.setName('Fergus')
dog.setKind(PetKind.toPetKind('dog'))
dog.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd').
parse('1999-02-11').getTime()))
dog.setFixed(False)
dog = PersistenceHelper.manager.store(dog)

Getting Started With Windchill Customization 65


cat = Pet.newPet()
cat.setName('Stimpy')
cat.setKind(PetKind.toPetKind('cat'))
cat.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd').
parse('1996-08-24').getTime()))
cat.setFixed(False)
cat = PersistenceHelper.manager.store(cat)
3. Update the cat (note that “#” starts a comment and is equivalent to Java’s “//”;
the comment string need not be entered and is intended to highlight that the
call will print the current principal):
cat.setFixed(True)
cat = PersistenceHelper.manager.modify(cat)
cat = OwnershipHelper.service.takeOwnership(cat)
OwnershipHelper.getOwner(cat) #Should print/return the current principal
4. Query (read) for the Pets named Fergus:
qs = QuerySpec(Pet)
qs.appendWhere(SearchCondition(Pet, Pet.NAME, SearchCondition.EQUAL,
'Fergus'))
qr = PersistenceHelper.manager.find(qs)
qr.size() #Should print/return 1
fergus = qr.nextElement()
fergus.getName() #Should print/return “Fergus”
5. Finally, delete the dog:
PersistenceHelper.manager.delete(dog)

Pet customization notes


As previously stated, this example serves more as a “Hello, World!” introduction
to Windchill persistence and modeling than an example of a actual Windchill
business object. As such, properties of various types (strings, enumerations,
timestamps, and primitives) were modeled to demonstrate possibilities, but Pet
was clearly insufficient as a class for storing information about pets.
Similarly, while Pet implemented Windchill interfaces, it was a particularly
lightweight object from a Windchill perspective. Firstly, it is not
AccessControlled (from wt.access), so anyone could create, read,
update, or delete pets without any permission beyond the minimal requirement of
authentication. Secondly, most Windchill business classes are WTContained
(from wt.inf.container) because containership is a primary organization
principle of Windchill.
A final, badly-needed correction to the customization is a helper/service along the
lines of those already utilized in the verification (PersistenceManager from
PersistenceHelper.manager and OwnershipService from
OwnershipHelper.service).

66 Customization Guide
The service makes it possible to provide APIs that encapsulate logical operations,
such as adoption. These APIs can utilize transactions, addressing the major flaw in
the combination of discrete APIs to accomplish adoption on the client: it is
possible to modify the pet and fail to takeOwnership, producing a state that
would likely be considered corrupt. A service API such as “public Pet
adopt(Pet pet, WTPrincipalReference owner) throws
WTException” could utilize a transaction to ensure the entire adoption proceeds
smoothly or not at all.
Subsequent chapters in this guide will cover these and many more aspects of
modeling and server-side customization.

Getting Started With Windchill Customization 67


Creating a UI
So far, Jython has stood in for a real client. Windchill, as a web application,
utilizes the browser to provide a user interface. The following user interface
components will be created for Pet:
• A table to display all pets, which will be linked to from the Site ▶ Utilities page
• A pop-up to create new pets (with support for uploading pictures (content))
• A similar pop-up to edit existing pets
• An “info” page to view pets, with an “Attachments” tab to download pictures
• Actions to create, edit, and delete pets

Pet Table
1. Create the PetTable class
a. File ▶ New ▶ Class
b. Set Package to com.acme.mvc.builders
c. Set Name to PetTable
d. Set Superclass to AbstractComponentBuilder (from com.ptc.mvc.
components)
e. Click Finish
2. AbstractComponentBuilder requires that two methods be
implemented (Eclipse will generate method stubs for each). The first,
buildComponentData, should return the objects (rows) to display in the
table. Replace the method’s body with the following code to simply query all
pets:
return PersistenceHelper.manager.find(new QuerySpec(Pet.class));

3. The second, buildComponentConfig, returns a table, complete with the


columns to display. First, create a convenience method to get individual
columns (ColumnConfig and ComponentConfigFactory are
imported from com.ptc.mvc.components):
ColumnConfig getColumn(final String id, final ComponentConfigFactory
factory) {
final ColumnConfig column = factory.newColumnConfig(id, true);
column.setSortable(false);
return column;
}

4. Next, create a new class, acmeManagerResource, to manage the localized


display name of the table. The complete listing follows:
package com.acme.jca;

68 Customization Guide
import wt.util.resource.*;

@RBUUID("com.acme.jca.acmeActionResource")
public final class acmeManagerResource extends WTListResourceBundle {
@RBEntry("Pets")
public static final String PET_TABLE_LABEL = "pet_table_label";
}

5. Next, replace buildComponentConfig’s generated body with ():


final ComponentConfigFactory factory = getComponentConfigFactory();

final TableConfig table; {


table = factory.newTableConfig();
table.setType(Pet.class.getName());
table.setLabel(WTMessage.getLocalizedMessage(RESOURCE,
acmeManagerResource.PET_TABLE_LABEL, null));
table.setSelectable(true);
table.setShowCount(true);
table.setShowCustomViewLink(false);

final ColumnConfig name; {


name = factory.newColumnConfig(Pet.NAME, true);
name.setInfoPageLink(true);
name.setSortable(true);
}
table.addComponent(name);
table.addComponent(getColumn(ColumnIdentifiers.INFO_ACTION, factory));
table.addComponent(getColumn(ColumnIdentifiers.NM_ACTIONS, factory));
table.addComponent(getColumn(ColumnIdentifiers.LAST_MODIFIED, factory));
table.addComponent(getColumn(Pet.KIND, factory));
table.addComponent(getColumn(Pet.DATE_OF_BIRTH, factory));
table.addComponent(getColumn(Pet.FIXED, factory));
}
return table;

Use Control-L to resolve classes as follows:


com.acme.jca.acmeManagerResource,
com.ptc.core.components.descriptor.DescriptorCon
stants.ColumnIdentifiers,
com.ptc.mvc.components.TableConfig, and
wt.util.WTMessage. Also, assign RESOURCE as a field:
static final String RESOURCE = acmeManagerResource.class.getName();

6. Register PetTable as a bean


a. Annotate the PetTable class declaration as follows:
@ComponentBuilder("acme.pet.table")
b. Alter the project’s exclusions:
i. Make the project’s .classpath (eclipse/cust_Windchill_src/
.classpath) writeable
ii. Project ▶ Properties

Getting Started With Windchill Customization 69


iii. Select Java Build Path and the Source tab.
iv. Select Excluded under cust_Windchil_src/src and select Edit.
v. Select config/** and select Edit.
vi. Replace config/** with config/logicrepository/** and
click OK
vii. Click Finish and OK
7. Create a new file named Pet-configs.xml.
a. File ... ▶ Other ▶ Other
b. Select XML ▶ XML File, then Next (if XML/XML File are not available,
install Eclipse XML Editors and Tools, which is available under the Web,
XML, and Java EE Development category when working with the Helios
software site -or- simply create a General -> File)
c. Assign parent folder to cust_Windchill_src/src/config/mvc
and file name to Pet-configs.xml and click Finish
d. Content is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.ptc.com/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.ptc.com/schema/mvc http://www.ptc.com/schema/mvc/mvc-10.0.xsd">
<!-- Define the builders -->
<bean class="com.acme.mvc.builders.PetTable"/>
</beans>

8. Validate that the table works by starting/restarting Windchill and appending to


the base Windchill URL /app/#ptc1/comp/acme.pet.table. The
following table should appear:

70 Customization Guide
Pet Information Page
Wiring the Pet table into Site ▶ Utilities
At this point, acme.pet.table is accessible, but requires the user to specify
the URL manually. Pet is not WTContained, so a logical place to wire in the
table is under Site ▶ Utilities.
1. The site utilities or managed by codebase/netmarkets/jsp/object/
commonUtilities.jspf, a Windchill-delivered and Windchill-managed
file. This file should not be updated in place; rather, it should be handled by
the “safe area” mechanism.
a. Create the following two directory structures under load point:
• wtSafeArea/ptcOrig/codebase/netmarkets/jsp/
object
• wtSafeArea/siteMod/codebase/netmarkets/jsp/
object
Copy commonUtilities.jspf to both directories just created above.
2. Edit wtSafeArea/siteMod/codebase/netmarkets/jsp/object
as follows to add the items in bold:
a. After <%@ page import=
"com.ptc.netmarkets.object.objectResource"%> add:
<%@ page import="com.acme.acmeResource"%>
<%@ page import="com.ptc.netmarkets.object.objectResource"%>
<%@ page import="com.acme.acmeResource"%>
b. After private static final String ENTERPRISE_RESOURCE =
"wt.enterprise.enterpriseResource"; add private
static final String ACME_RESOURCE =
"com.acme.acmeResource";
<%! private static final String OBJECT_CONFIG_RESOURCE =
"com.ptc.netmarkets.object.objectResource";
private static final String ENTERPRISE_RESOURCE =
"wt.enterprise.enterpriseResource";
private static final String ACME_RESOURCE = "com.acme.acmeResource";
c. After ResourceBundle enterpriseRb =
ResourceBundle.getBundle(ENTERPRISE_RESOURCE,
localeBean.getLocale()); add ResourceBundle acmeRb =
ResourceBundle.getBundle(ACME_RESOURCE,
localeBean.getLocale());
ResourceBundle objectRb = ResourceBundle.getBundle
(OBJECT_CONFIG_RESOURCE, localeBean.getLocale());
ResourceBundle enterpriseRb = ResourceBundle.getBundle
(ENTERPRISE_RESOURCE, localeBean.getLocale());
ResourceBundle acmeRb = ResourceBundle.getBundle(

Getting Started With Windchill Customization 71


ACME_RESOURCE, localeBean.getLocale());
d. After "PERSONAL_CABINETS” , add "PET_ADMINISTRATION" ,
String [] knownUtilities={"AUDITING_PURGE",
"AUDITING_LICENSE_USAGE",
"AUDITING_ORGANIZATION_USAGE",
"AUDITING_SECURITY_REPORT_QUERIES",
"AUDITING_SECURITY_REPORTS",
"CALENDAR_MANAGEMENT",
"CLASSIFICATION_ADMINISTRATOR",
"SCMI_ADAPTER_ADMINISTRATOR",
"SCMI_ADMINISTRATOR",
"CONFIGURATION_FILE_GENERATOR",
"ESI_TRANSACTION_ADMIN",
"REPLICATION_ADMINISTRATOR",
"CCS_MANAGER",
"IMPORT_EXPORT",
"INFO_ENGINE" ,
"NUMBERING_SCHEMES",
"VERSIONING_SCHEMES",
"LIFE_CYCLE_ADMIN",
"ESI_DISTRIBUTION_TARGET_ADMIN",
"OPTEGRA_GATEWAY",
"RULES_ADMINISTRATION",
"PACKAGES_MAPPING_MANAGER",
"PARTICIPANT_ADMINISTRATION",
"PERSONAL_CABINETS" ,
"PET_ADMINISTRATION",
e. After the if (wvs_enabled ) { block add linkDatum.put("PET_
ADMINISTRATION.isUtilityInstalled", "Yes");
if (wvs_enabled ) {
linkDatum.put("CAD_AGENT.isUtilityInstalled" , "Yes" );
linkDatum.put("PRODUCT_VIEW.isUtilityInstalled" , "Yes" );
linkDatum.put("PUBLISH_MONITOR.isUtilityInstalled" , "Yes" );
linkDatum.put("PUBLISH_SCHEDULER.isUtilityInstalled" , "Yes" );
linkDatum.put("PUBLISH_THB_CONTROL.isUtilityInstalled" , "Yes" );
}

linkDatum.put("PET_ADMINISTRATION.isUtilityInstalled", "Yes");
f. After linkDatum.put("AUDITING_SECURITY_
REPORTS.isAuditUtility" , "Yes" ); add // set ACME
utility flag. Define only if the utility is considered
an ACME utility linkDatum.put("PET_
ADMINISTRATION.isACMEUtility", "Yes");
// set audit utility flag. Define only if the utility is considered an
// auditing utility
linkDatum.put("AUDITING_PURGE.isAuditUtility" , "Yes" );
linkDatum.put("AUDITING_ORGANIZATION_USAGE.isAuditUtility" , "Yes" );
linkDatum.put("AUDITING_LICENSE_USAGE.isAuditUtility" , "Yes" );

72 Customization Guide
linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.isAuditUtility", "Yes" );
linkDatum.put("AUDITING_SECURITY_REPORTS.isAuditUtility" , "Yes" );

// set ACME utility flag. Define only if the utility is


considered an ACME utility
linkDatum.put("PET_ADMINISTRATION.isACMEUtility", "Yes");
g. After linkDatum.put("PERSONAL_CABINETS.idText" ,
linkBean.getLinkID(null,"textLink:deletedUsersCabi
nets") ); add linkDatum.put("PET_
ADMINISTRATION.idText" ,
linkBean.getLinkID(null,"textLink:petAdmin") );
// The value to use for id. An entry is required for all known utilities
linkDatum.put("AUDITING_PURGE.idText"
, linkBean.getLinkID(null,"textLink:auditingPurge") );
linkDatum.put("AUDITING_ORGANIZATION_USAGE.idText"
, linkBean.getLinkID(null,"textLink:auditingOrgUsage") );
linkDatum.put("AUDITING_LICENSE_USAGE.idText"
, linkBean.getLinkID(null,"textLink:auditingLicenseUsage") );
linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.idText"
, linkBean.getLinkID(null,"textLink:auditingReportQueries") );
linkDatum.put("AUDITING_SECURITY_REPORTS.idText"
, linkBean.getLinkID(null,"textLink:auditingReports") );
linkDatum.put("CAD_AGENT.idText"
, linkBean.getLinkID(null,"textLink:cadAgentAdmin") );
linkDatum.put("CALENDAR_MANAGEMENT.idText"
, linkBean.getLinkID(null,"textLink:calendarManagement") );
linkDatum.put("CLASSIFICATION_ADMINISTRATOR.idText"
, linkBean.getLinkID(null,"textLink:classificationAdministrator") );
linkDatum.put("CONFIGURATION_FILE_GENERATOR.idText"
, linkBean.getLinkID(null,"textLink:configurationFileGenerator") );
linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.idText"
, linkBean.getLinkID(null,"textLink:ESI_DISTRIBUTION_TARGET_ADMIN") );
linkDatum.put("ESI_TRANSACTION_ADMIN.idText"
, linkBean.getLinkID(null,"textLink:ESI") );
linkDatum.put("EXTERNAL_STORAGE.idText"
, linkBean.getLinkID(null,"textLink:externalStorageAdmin") );
linkDatum.put("IMPORT_EXPORT.idText"
, linkBean.getLinkID(null,"textLink:importExportAdmin") );
linkDatum.put("PACKAGES_MAPPING_MANAGER.idText"
, linkBean.getLinkID(null,"textLink:packageMappingManager") );
linkDatum.put("INFO_ENGINE.idText"
, linkBean.getLinkID(null,"textLink:infoEngineAdmin") );
linkDatum.put("LIFE_CYCLE_ADMIN.idText"
, linkBean.getLinkID(null,"textLink:lifeCycleTemplateAdmin") );
linkDatum.put("NUMBERING_SCHEMES.idText"
, linkBean.getLinkID(null,"textLink:numberingSchemesAdmin") );
linkDatum.put("POLICY_ADMINISTRATOR.idText"
, linkBean.getLinkID(null,"textLink:policyAdmin") );
linkDatum.put("PERSONAL_CABINETS.idText"

Getting Started With Windchill Customization 73


, linkBean.getLinkID(null,"textLink:deletedUsersCabinets") );
linkDatum.put("PET_ADMINISTRATION.idText"
, linkBean.getLinkID(null,"textLink:petAdmin") );
h. After linkDatum.put("VIEW_NETWORK.pageLoc" ,
viewAction.getActionUrl(actionBean, linkBean,
objectBean, localeBean, urlFactoryBean,nmcontext,
sessionBean,request)); add //ACME pageLocs
linkDatum.put("PET_ADMINISTRATION.pageLoc",
NetmarketURL.convertToShellURL("ptc1/comp/
acme.pet.table"));
//We need to get the locale specific link for the network admin .

NmAction viewAction = NmActionServiceHelper.service.getAction


("view","list");
linkDatum.put("VIEW_NETWORK.pageLoc"
, viewAction.getActionUrl(actionBean, linkBean,
objectBean, localeBean,
urlFactoryBean,nmcontext, sessionBean,request));

//ACME pageLocs
linkDatum.put("PET_ADMINISTRATION.pageLoc",
NetmarketURL.convertToShellURL
("ptc1/comp/acme.pet.table"));
i. After linkDatum.put("NUMBERING_SCHEMES.urlPrarms"
,"'NumberingSchemes','resizable=yes,scrollbars=
yes,menubar=yes,toolbar=yes,location=yes,status=
yes'"); add linkDatum.put("PET_
ADMINISTRATION.urlPrarms" ,"'PetAdmin','resizable=
yes,scrollbars=yes,menubar=yes,toolbar=
yes,location=yes,status=yes'" );
linkDatum.put("ESI_TRANSACTION_ADMIN.urlPrarms","'ESITransaction','
directories=no,location=no,menubar=no,scrollbars=yes,status=yes,
toolbar=no,resizable=yes,height=1000,width=1400'" );

linkDatum.put("EXTERNAL_STORAGE.urlPrarms"
,"'ExternalStorage','resizable=yes,scrollbars=yes,menubar=no,
toolbar=no,location=no,status=yes,height=455,width=640'" );
linkDatum.put("IMPORT_EXPORT.urlPrarms"
,"'_blank','resizable=yes,scrollbars=yes,menubar=no,
toolbar=no,location=no,
status=yes,height=455,width=640'");
linkDatum.put("PACKAGES_MAPPING_MANAGER.urlPrarms"
,"'_blank','resizable=yes,scrollbars=yes,menubar=no,
toolbar=no,location=no,
status=yes,height=500,width=880'");
linkDatum.put("INFO_ENGINE.urlPrarms"
,"'InfoEngine','resizable=yes,scrollbars=yes,menubar=yes,

74 Customization Guide
toolbar=yes,
location=yes,status=yes'" );
linkDatum.put("LIFE_CYCLE_ADMIN.urlPrarms"
,"'LifeCycleAdmin','resizable=yes,scrollbars=yes,menubar=yes,
toolbar=yes,
location=yes,status=yes'");
linkDatum.put("NUMBERING_SCHEMES.urlPrarms"
,"'NumberingSchemes','resizable=yes,scrollbars=yes,menubar=yes,
toolbar=yes,
location=yes,status=yes'");
linkDatum.put("PET_ADMINISTRATION.urlPrarms"
,"'PetAdmin','resizable=yes,scrollbars=yes,menubar=yes,
toolbar=yes,
location=yes,status=yes'" );
j. After linkDatum.put("PERSONAL_CABINETS.linkText"
,objectRb.getString(objectResource.PERSONAL_
CABINETS)); add linkDatum.put("PET_
ADMINISTRATION.linkText"
,acmeRb.getString(acmeResource.PET_
ADMINISTRATION));
linkDatum.put("EXTERNAL_STORAGE.linkText"
,objectRb.getString(objectResource.EXTERNAL_STORAGE));
linkDatum.put("IMPORT_EXPORT.linkText"
,objectRb.getString(objectResource.IMPORT_EXPORT));
linkDatum.put("PACKAGES_MAPPING_MANAGER.linkText"
,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER));
linkDatum.put("INFO_ENGINE.linkText"
,objectRb.getString(objectResource.INFO_ENGINE));
linkDatum.put("LIFE_CYCLE_ADMIN.linkText"
,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN));
linkDatum.put("NUMBERING_SCHEMES.linkText"
,objectRb.getString(objectResource.NUMBERING_SCHEMES));
linkDatum.put("PERSONAL_CABINETS.linkText"
,objectRb.getString(objectResource.PERSONAL_CABINETS));
linkDatum.put("PET_ADMINISTRATION.linkText"
,acmeRb.getString(acmeResource.PET_ADMINISTRATION));
k. After linkDatum.put("PERSONAL_CABINETS.linkDesc"
,objectRb.getString(objectResource.PERSONAL_
CABINETS_DESCRIPTION)); add linkDatum.put("PET_
ADMINISTRATION.linkDesc"
,acmeRb.getString(acmeResource.PET_ADMINISTRATION_
DESCRIPTION));
linkDatum.put("EXTERNAL_STORAGE.linkDesc"
,objectRb.getString(objectResource.EXTERNAL_STORAGE_DESCRIPTION));
linkDatum.put("IMPORT_EXPORT.linkDesc"
,objectRb.getString(objectResource.IMPORT_EXPORT_DESCRIPTION));
linkDatum.put("PACKAGES_MAPPING_MANAGER.linkDesc"
,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER_DESCRIPTION));

Getting Started With Windchill Customization 75


linkDatum.put("INFO_ENGINE.linkDesc"
,objectRb.getString(objectResource.INFO_ENGINE_DESCRIPTION));
linkDatum.put("LIFE_CYCLE_ADMIN.linkDesc"
,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN_DESCRIPTION));
linkDatum.put("NUMBERING_SCHEMES.linkDesc"
,objectRb.getString(objectResource.NUMBERING_SCHEMES_DESCRIPTION));
linkDatum.put("PERSONAL_CABINETS.linkDesc"
,objectRb.getString(objectResource.PERSONAL_CABINETS_DESCRIPTION));
linkDatum.put("PET_ADMINISTRATION.linkDesc"
,acmeRb.getString(acmeResource.PET_ADMINISTRATION_DESCRIPTION));
l. Replace
objectRb.getString(objectResource.AUDITING_ADMINISTRATION)};
boolean [] systemHeader={true,false,false};
boolean [] auditHeader={false,false,true};
with
objectRb.getString(objectResource.AUDITING_ADMINISTRATION),
acmeRb.getString(acmeResource.ACME_ADMINISTRATION)};
boolean [] systemHeader={true,false,false,false};
boolean [] auditHeader={false,false,true,false};
boolean [] acmeHeader={false,false,false,true};
m. After the //Match audit/nonaudit section add //Match acme/
noacme String isACME =
knownUtilities[i].concat(".isACMEUtility"); if
(linkDatum.containsKey(isACME)!=
acmeHeader[currentHeader]) { continue;
//Match audit/nonaudit
String isAudit = knownUtilities[i].concat(".isAuditUtility");
if (linkDatum.containsKey(isAudit)!=auditHeader[currentHeader]) {
continue;
}
//Match acme/noacme
String isACME = knownUtilities[i].concat(".isACMEUtility");
if (linkDatum.containsKey(isACME)!=acmeHeader[currentHeader]) {
continue;

n. After <% } else if ("RULES_


ADMINISTRATION".equals(knownUtilities[i])) { %>
href="<%=pageLoc%>" add <% } else if ("PET_
ADMINISTRATION".equals(knownUtilities[i])) { %>
href="<%=pageLoc%>"
<% } else if ("RULES_ADMINISTRATION".equals(knownUtilities[i])) { %>
href="<%=pageLoc%>"
<% } else if ("PET_ADMINISTRATION".equals(knownUtilities[i])) { %>
href="<%=pageLoc%>"
<% }
3. Enable PET_ADMINISTRATION

76 Customization Guide
a. Create the following two directory structures under load point:
wtSafeArea/ptcOrig/codebase/netmarkets/jsp/
sitewtSafeArea/siteMod/codebase/netmarkets/jsp/
site
b. Copy listUtilities.jspf to both directories just created above.
c. Edit wtSafeArea/siteMod/codebase/netmarkets/jsp/
site/listUtilities.jsp, appending (after line 67) the following
to the enabled:
showUtility.put("PET_ADMINISTRATION" , "Enable");

4. Deploy the site modifications: ant -f bin/swmaint.xml


installSiteChanges
5. Create the imported acmeResource as shown
package com.acme;

import wt.util.resource.*;

@RBUUID("com.acme.acmeResource")
public class acmeResource extends WTListResourceBundle {
@RBEntry("ACME Administration")
public static final String ACME_ADMINISTRATION = "acme_administration";

@RBEntry("Pet Administration")
public static final String PET_ADMINISTRATION = "pet_administration";

@RBEntry("CRUD opererations for pets")


public static final String PET_ADMINISTRATION_DESCRIPTION =
"pet_administration_description";
}
6. Start/restart Windchill.
7. Site ▶ Utilities should incorporate ACME Administration, as shown

Pet Information Page


The table currently shows an “i” for an info page (for Stimpy), but the information
page has not been created yet (clicking the “i” will result in an error).
1. Create the primary builder for the information page. Complete source follows:

Getting Started With Windchill Customization 77


package com.acme.mvc.builders;

import wt.util.WTException;

import com.ptc.jca.mvc.builders.DefaultInfoComponentBuilder;
import com.ptc.mvc.components.ComponentBuilder;
import com.ptc.mvc.components.ComponentId;
import com.ptc.mvc.components.ComponentParams;
import com.ptc.mvc.components.InfoConfig;
import com.ptc.mvc.components.TypeBased;

@ComponentBuilder(ComponentId.INFOPAGE_ID)
@TypeBased("com.acme.Pet")
public class PetInfoBuilder extends DefaultInfoComponentBuilder {
@Override
protected InfoConfig buildInfoConfig(final ComponentParams params)
throws WTException {
final InfoConfig info = getComponentConfigFactory().newInfoConfig();
info.setTabSet("petDetails");
return info;
}
}
2. Define the petDetails tab set by creating its action model (in config/
actions/Pet-actionmodels.xml).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE actionmodels SYSTEM 'actionmodels.dtd'>
<actionmodels>
<model name="petDetails">
<action name="primaryAttributes" type="object"/>
<action name="attachments" type="object"/>
</model>
</actionmodels>
3. Define the primaryAttributes.
package com.acme.mvc.builders;

import wt.util.WTException;

import com.acme.Pet;
import com.ptc.core.ui.resources.ComponentType;
import com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder;
import com.ptc.jca.mvc.components.JcaAttributeConfig;
import com.ptc.jca.mvc.components.JcaGroupConfig;
import com.ptc.mvc.components.AttributePanelConfig;
import com.ptc.mvc.components.ComponentBuilder;
import com.ptc.mvc.components.ComponentConfigFactory;
import com.ptc.mvc.components.ComponentId;
import com.ptc.mvc.components.ComponentParams;
import com.ptc.mvc.components.TypeBased;

78 Customization Guide
@ComponentBuilder("primaryAttributes")
@TypeBased("com.acme.Pet")
public class PetInfoAttributesBuilder extends
AbstractAttributesComponentBuilder {
@Override
protected AttributePanelConfig buildAttributesComponentConfig
(final ComponentParams params)
throws WTException {
final ComponentConfigFactory factory = getComponentConfigFactory();

final AttributePanelConfig panel; {


panel = factory.newAttributePanelConfig(ComponentId.ATTRIBUTE_PANEL_ID);
panel.setComponentType(ComponentType.WIZARD_ATTRIBUTES_TABLE);

final JcaGroupConfig group; {


group = (JcaGroupConfig) factory.newGroupConfig();
group.setId("attributes");
group.setLabel("Attributes");
group.setIsGridLayout(true);

group.addComponent(getAttribute(Pet.NAME, factory));
group.addComponent(getAttribute(Pet.KIND, factory));
group.addComponent(getAttribute(Pet.DATE_OF_BIRTH, factory));
group.addComponent(getAttribute(Pet.FIXED, factory));
}
panel.addComponent(group);
}
return panel;
}

JcaAttributeConfig getAttribute(final String id, final


ComponentConfigFactory factory) {
final JcaAttributeConfig attribute = (JcaAttributeConfig)
factory.newAttributeConfig();
attribute.setId(id);
return attribute;
}
}
4. Register the beans by updating Pet-configs.xml to include:
<bean class="com.acme.mvc.builders.PetInfoBuilder"/>
<bean class="com.acme.mvc.builders.PetInfoAttributesBuilder"/>
5. Add Pet-actionmodels.xml to site.xconf.
a. Just before the last line, </Configuration> add <AddToProperty
name=
"com.ptc.netmarkets.util.misc.defaultActionmodels"
value="config/actions/Petactionmodels.xml"/>.

Getting Started With Windchill Customization 79


b. Run bin/xconfmanager -pF to propagate the change.
6. Start/restart Windchill and verify (noting the Attachments tab for content).

80 Customization Guide
Creating a New Pet
Creating a new Pet involves building a dialog for it and making it visible on the
table.
1. Create create.jsp, a wizard for creating pets.
a. Navigate to File ▶ New ▶ Other... ▶ Select Other ▶ JSP File and then click
Next.

Note
If the option Other... ▶ Select Other ▶ JSP File is not available, install
Web Page Editor. This is available under the Web, XML, and Java EE
Development category when working with the Helios software site. As
an alternative you can also create a general file (Other... ▶ General ▶
File)

b. The folder is cust_Windchill_src/src/netmarkets/jsp/


acme/pet, file name is create.jsp.
c. Click Finish and replace content with the following:
<%@taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib
/components"%>
<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments"%>
<%@include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:initializeItem baseTypeName="com.acme.Pet" operation=


"${createBean.create}"
attributePopulatorClass="com.ptc.core.components.forms.
DefaultAttributePopulator"/>

<jca:wizard>
<jca:wizardStep action="petDefineItemAttributesWizStep"
type="pet"/>
<jca:wizardStep action="attachments_step" type="attachments"/>
</jca:wizard>

<attachments:fileSelectionAndUploadApplet/>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

2. Define the petDefineItemAttributesWizStep action.


a. Create Pet-actions.xml alongside Pet-actionmodels.xml in
config.actions.

Getting Started With Windchill Customization 81


b. Assign its content as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE listofactions SYSTEM 'actions.dtd'>
<listofactions>
<objecttype name="pet" class="com.acme.Pet"
resourceBundle="com.acme.jca.acmeActionResource">
<action name="petDefineItemAttributesWizStep"
afterVK="setAttributesWizStep"
preloadWizardPage="true" required="true">
<command url="netmarkets/jsp/acme/pet/
defineItemAttributesWizStep.jsp"
windowType="wizard_step"/>
</action>
</objecttype>
</listofactions>

c. Register Pet-actions.xml in site.xconf <AddToProperty


name="com.ptc.netmarkets.util.misc.defaultActions"
value="config/actions/Pet-actions.xml"/>
d. Run xconfmanager again to propagate the change
3. Create the defineItemAttributesWizStep.jsp JSP page alongside
create.jsp with the following content:
<%@taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%>
<%@include file="/netmarkets/jsp/util/begin_comp.jspf"%>
<jsp:include page="${mvc:getComponentURL('acme.pet.SetAttributesPanel')}"/>
<%@include file="/netmarkets/jsp/util/end_comp.jspf"%>

4. Define the component (acme.pet.SetAttributesPanel)


a. Create PetSetAttributesPanelBuilder with content.
package com.acme.mvc.builders;

import wt.util.WTException;

import com.acme.Pet;
import com.ptc.core.ui.resources.ComponentType;
import com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder;
import com.ptc.jca.mvc.components.JcaAttributeConfig;
import com.ptc.jca.mvc.components.JcaGroupConfig;
import com.ptc.mvc.components.AttributePanelConfig;
import com.ptc.mvc.components.ComponentBuilder;
import com.ptc.mvc.components.ComponentConfigFactory;
import com.ptc.mvc.components.ComponentId;
import com.ptc.mvc.components.ComponentParams;
import com.ptc.mvc.components.TypeBased;

@ComponentBuilder("acme.pet.SetAttributesPanel")
@TypeBased("com.acme.Pet")
public class PetSetAttributesPanelBuilder extends
AbstractAttributesComponentBuilder {
@Override
protected AttributePanelConfig buildAttributesComponentConfig
(final ComponentParams params) throws WTException {

82 Customization Guide
final ComponentConfigFactory factory = getComponentConfigFactory();

final AttributePanelConfig panel; {


panel = factory.newAttributePanelConfig
(ComponentId.ATTRIBUTE_PANEL_ID);
panel.setComponentType
(ComponentType.WIZARD_ATTRIBUTES_TABLE);

final JcaGroupConfig group; {


group = (JcaGroupConfig) factory.newGroupConfig();
group.setId("setAttributes");
group.setLabel("Set Attributes");
group.setIsGridLayout(true);
group.addComponent(getAttribute(Pet.NAME, factory));
group.addComponent(getAttribute(Pet.KIND, factory));
group.addComponent(getAttribute(Pet.DATE_OF_BIRTH, factory));
group.addComponent(getAttribute(Pet.FIXED, factory));
}
panel.addComponent(group);
}
return panel;
}
JcaAttributeConfig getAttribute
(final String id, final ComponentConfigFactory
factory) {
final JcaAttributeConfig attribute = (JcaAttributeConfig)
factory.newAttributeConfig();
attribute.setId(id);
return attribute;
} }

b. Add the following to Pet-configs.xml to register the builder <bean id=


"acme.pet.SetAttributesPanel" class="com.acme.mvc.builders.
PetSetAttributesPanelBuilder"/>
5. Create the resourceBundle referred to by
petDefineItemAttributesWizStep, with content as follows (note the
reuse of createPackage.gif as the icon for creating pets):
package com.acme.jca;

import wt.util.resource.*;

@RBUUID("com.acme.jca.acmeActionResource")
public final class acmeActionResource extends WTListResourceBundle {
@RBEntry("New Pet")
public static final String PET_CREATE_TITLE = "pet.create.title";

@RBEntry("New Pet")
public static final String PET_CREATE_TOOLTIP = "pet.create.tooltip";

@RBEntry("New Pet")
public static final String PET_CREATE_DESCRIPTION = "pet.create.description";

@RBEntry("createPackage.gif")
public static final String PET_CREATE_ICON = "pet.create.icon";}

Getting Started With Windchill Customization 83


6. Wire the create action into PetTable.
a. Add the following model to Pet-actionmodels.xml (just above the
petDetails model).
<model name="pets list">
<action name="create" type="pet" shortcut="true"/>
</model>

b. Add the create action to pet in Pet-actions.xml (just above


petDefineItemAttributesWizStep).
<action name="create">
<command class="com.ptc.core.components.forms.CreateObjectFormProcessor"
url="netmarkets/jsp/acme/pet/create.jsp" windowType="popup"/>
</action>

c. Incorporate the action model (pets list) into PetTable (add before
table.setSelectable(true);). Example:
table.setActionModel("pets list");
7. Start/restart Windchill.
a. Verify the New Pet icon is available on the table
b.

84 Customization Guide
c. Click New Pet and verify a pop-up consisting of a wizard with two steps.

d. Create a pet. Be sure to upload the content.


e. Go to the new pet’s “info” page and verify that the content shows and is
viewable/downloadable.

Getting Started With Windchill Customization 85


Editing Pet
The process of editing a pet is similar to the process of creating one.
1. Copy createPet.jsp
a. Select create.jsp.
b. Right-click -> Copy
c. Right-click -> Paste, set new name to editPet.jsp.
d. Open editPet.jsp and replace createBean.create with
createBean.edit.
2. Register editPet and make it available on the information page.
a. Add the action to Pet-actions.xml.
<action name="editPet">
<command class="com.ptc.core.components.forms.DefaultEditFormProcessor"
url="netmarkets/jsp/acme/pet/editPet.jsp" windowType="popup"/>
</action>

b. Add a menu to the “info” page.


<model name="pet actions" menufor="com.acme.Pet">
<action name="editPet" type="pet"/>
</model>

3. Add the following to acmeActionResource.java :


@RBEntry("Edit Pet")
public static final String PET_EDIT_PET_TITLE = "pet.editPet.title";

@RBEntry("Edit")
public static final String PET_EDIT_PET_TOOLTIP = "pet.editPet.tooltip";

@RBEntry("Edit")
public static final String PET_EDIT_PET_DESCRIPTION = "pet.editPet.description";

@RBEntry("edit.gif")
public static final String PET_EDIT_PET_ICON = "pet.editPet.icon";

4. Implement a wt.verification.Verifier (non-AccesControlled


objects are shielded from inadvertent (or malicious) updates and deletes by a
Verifier in lieu of access control)
a. Create PetVerifier with content as follows:
package com.acme;

import wt.fc.Persistable;
import wt.fc.collections.WTCollection;
import wt.util.WTException;import wt.verification.Verifier;

public class PetVerifier implements Verifier {


@Override public boolean verify(Persistable a_object) throws WTException {
return true;
}

86 Customization Guide
@Override
public boolean verify(WTCollection a_objects) throws WTException {
return true;
}}

b. Register PetVerifier as a verifier for Pet by adding the following to


site.xconf and propagating with xconfmanager.
<Service context="default" name="wt.verification.Verifier"
targetFile="codebase/service.properties">
<Option cardinality="duplicate" order="1" requestor="com.acme.Pet"
serviceClass="com.acme.PetVerifier" selector="DEFAULT"/>
</Service>

5. Start/restart Windchill
a. Verify that “edit” is available as an action of an “info” page.

b. Verify the edit pop-up.

c. Edit the pet.

Getting Started With Windchill Customization 87


Deleting a Pet
1. Under the create action of the pets list model (in Pet-
actionmodels.xml), add
<action name="delete" type="object" shortcut="true"/>

2. Start/restart Windchill.
3. Verify that “delete” has been added as an action to the pet table

4. Delete a pet.

88 Customization Guide
Customization Notes
The user interface customization incorporates pets into the Windchill UI. All basic
“CRUD” operations are supported. However, more could be done. For example,
while content was not demonstrated in Jython (and is demonstrated in the UI),
ownership has been ignored and left out of the UI. How to incorporate concepts
like ownership will be covered elsewhere in the guide.
Additionally, both PetInfoAttributesBuilder and
PetSetAttributesBuilder set the group’s label to a hard-coded,
unlocalizable string. To correct that, take a look at setLabel in PetTable, which
does this correctly.
The choice to incorporate the table into Site ▶ Utilities was based on Pet being
neither AccessControlled nor WTContained, making it more like
Windchill’s administrative objects in practice than like the many Windchill
business objects. The manner in which a modeled customization is incorporated
into the Windchill UI is largely dictated by the behavior (as determined by the
domain interfaces it implements and the parent class it extends).

Getting Started With Windchill Customization 89


Customizations — Next Steps
The Pet example illustrates a simple “from scratch” modeled customization with
very little (unique/interesting) logic and no (new) associations. There are, not
surprisingly, many different kinds of customizations. Some customizations simply
extend and existing business class to add properties (a customization largely
superseded by Windchill’s soft typing capabilities), some exist to add new
associations to existing business objects, some exist to add validation and other
logic to existing Windchill classes, and so on. The remaining sections will cover
all of the various kinds of customizations, as well as providing greater insight into
this customization.

90 Customization Guide
5
Modeling Business Objects
Windchill Modeling Heuristics .....................................................................................92
Windchill Foundation Abstractions ..............................................................................95

This chapter explains how to model business objects.

91
Windchill Modeling Heuristics
This section is intended to give you some background on the design of the
Windchill class architecture and the approach we have used in modeling. The
Windchill class architecture was designed with the following objectives in mind:
• To promote the development of business objects that reflect the characteristics
of a three-tier architecture; that is, presentation for the client layer, business
logic for the server layer, and persistence for the database layer.
• To ensure a model from which optimized code can be generated. The code that
is generated should provide for managing the state of objects, transporting
objects between the client and the server, and manipulating objects in the
database.
• To provide an environment that enables value-added development. You must
be able to extend the model and put new capabilities in existing objects.
One approach to achieving these objectives is to inherit functionality.

Functionality through Inheritance


As you add subclasses to a parent class, in this case extending class WTObject
with Item and then DomainItem, the attributes and methods of each preceding
class are inherited by the subclasses. This approach works in many circumstances.
But sometimes you need only a small percentage of the functionality that is being
inherited. In that case, either you have much more than you actually need in your
object, or you copy just the code you want and add it to your own object, creating
redundancy and potential maintenance problems.

92 Customization Guide
Another approach, which we have implemented in Windchill , is to partition
functionality, as in the figure below, into objects that are responsible primarily for
maintaining business information (also called knowers) versus objects responsible
primarily for performing business operations (also called doers).

Functionality through Partitioning


Using this approach, business models have two major kinds of classes: business
information classes and business manager classes.
Business information classes represent the business information and associations
you want to manage and maintain in a database. These classes extend the
foundation classes provided in Windchill. They may implement one or more
business manager interfaces. These classes go back and forth between the client
and the server with data.
Business manager classes represent the business rules that are applied to the
business information objects. These classes extend the Windchill
StandardManager class. Business managers implement an interface class that
provides a client-side API to the business manager methods. The code for
business manager classes is located in the server.
The following is an example of one of the managers Windchill provides, the
LockService. (In naming classes, managers are sometimes also called services.)

Modeling Business Objects 93


LockService Example
In this example, Lockable is a “knower” that is implemented by MyItem (which
also extends the abstract class Item). Lockable objects, including MyItem, are
managed by the StandardLockService (a “doer”), with APIs exposed by the
implememnted remote interface LockService.
Besides the attributes and methods it inherited from Item, MyItem also has the
functionality defined in the Lockable interface.
The left side of the figure shows how to model the interface for a server-side
service on a client. The doer is StandardLockService and it runs on the server. It
inherits from the Windchill StandardManager, which provides standard, basic
operations for a typical manager, such as starting and shutting down. (When you
write your own managers, they also can inherit from StandardManager.).
The LockService interface describes the lock services that are available on the
client, lock and unlock. These services are invoked remotely from the client to the
server. StandardLockService on the server actually contains all the code to support
the lock and unlock methods.
LockService’s APIs expect a Lockable object. They can accept MyItem because
MyItem implemented the Lockable interface. Likewise, they can accept any other
business information class that implements the Lockable interface. To get access
to the lock service functionality, a class must implement the Lockable interface.

94 Customization Guide
Windchill Foundation Abstractions
At an infrastructure layer of Windchill’s architecture are foundational abstractions
to be used by services and applications. These abstractions, shown in the
following figure, represent the fundamental types that are commonly used by
others as a part of a Windchill system.

Foundation Hierarchy

Modeling Business Objects 95


Windchill Foundation Interfaces
At the root of the hierarchy is the NetFactor interface. If an abstraction asserts
itself as being an object of type NetFactor, it is classified as belonging to a
Windchill system. One side effect of being a NetFactor type is that static factory
(“new<Class>”) methods, along with supporting “initialize” methods replace
constructors.
Classes that are asserted as being ObjectMappable can be written into and read
from the database. All remaining abstractions in the foundation hierarchy are a
kind of ObjectMappable abstraction. All subtypes of ObjectMappable are
Externalizable, which gives an object the ability to use RMI for travel between the
client and server. ObjectMappable adds readExternal and writeExternal APIs
(similar to those of Externalizable) to support reading from and writing to the
database. Windchill annotation processors generate the appropriate
implementations for these APIs.
The PersistInfo interface contains information for each object that is stored in the
database. PersistInfo does not implement Persistable; it is a structured attribute. It
does, however, implement ObjectMappable. This means createStamp,
modifyStamp, updateStamp, and updateCount will all be included in readExternal
and writeExternal operations.
Links, object references, and query keys are generalized as interfaces as shown in
the following figure.

Binary Links

The QueryKey interface specifies a qualification for a persistable object in the


database, represented as a combination of a class(name) and identifier. The
WTReference interface aggregates a single QueryKey and provides a

96 Customization Guide
corresponding “object” representing the (inflated) Persistable corresponding to the
key. An attempt to inflate a key that results zero or multiple Persistent objects will
result in an exception.
The Link interface specifies the concept of a container of roles and, in particular,
the BinaryLink interface, a kind of Link, is an abstraction of an attributed member
of an association between two persistable objects. The actual containment of the
objects is done by aggregation of references for each role.
The Persistable interface gives an object a primary key (that is, the object
identifier) as shown in the following figure, and a table in the database. It is this
primary key that is the identifier for an ObjectReference, a WTReference
implementation referring to a Persistable via its primary key.

Persistable Objects

First class objects implement the Persistable interface. As a result, a database table
is generated for each class in which their objects will be stored. The structured
attributes are stored in the database table of their associated first class object. All
persistable objects, plus any structured attributes that must be written into or read
from the database, must implement the ObjectMappable interface.

Modeling Business Objects 97


Windchill Foundation Classes
Windchill provides three base classes with some basic functionality for business
information objects: WTObject, Item, and ObjectToObjectLink. Many business
information objects provided by Windchill, and probably many that you create
yourself, extend these foundation classes and, therefore, inherit attributes and
methods from these classes.
It is recommended that if you extend Windchill-supplied classes, you use those
described in The Enterprise Layer on page 2075, which were designed to be used
for customization.
• WTObject : Represents the base class for all Windchill business information
classes. Item and ObjectToObjectLink are subclasses of WTObject.
• Item : Represents a discrete business item.
• ObjectToObjectLink : Represents a concrete binary association between two
Persistable objects; that is, you can define a link between two items, between
an item and a link, and between two links. Each link has a roleA side and a
roleB side therefore, if you have a link, you can use it to navigate to all other
objects associated with it. The ObjectToObjectLink class can be extended and
therefore can have additional attributes and methods. As shown in the
following figure, the ObjectToObjectLink aggregates ObjectReference for
both role A and B. The ObjectReference in turn aggregates the primary key
ObjectIdentifier as an overridden key to reference its object for both roles. The
ObjectIdentifier extends QueryKey and adds the id as an additional attribute.

Object to Object Link

WTObject contains a few general-purpose methods that are inherited by every


business object and provide a low level of functionality. For example, the
checkAttributes method is called when the object is saved to perform elementary
validity checking. If you have not supplied information for required attributes, an
exception is thrown and the object is not made persistent.

98 Customization Guide
99
6
Managing Customizations
Setting Up a Directory Structure for Managing Customized Files and Text
Tailoring .............................................................................................................. 101
Best Practices for Customizing Files Supplied by PTC ............................................... 109
Best Practices for Adding New Packages and Files.................................................... 129
Modeled To Subtype Conversion .............................................................................. 133
Monitoring a Customized Windchill Environment........................................................ 160
Customization with Windchill Queues........................................................................ 161

This chapter describes the best practices that should be used when you are
customizing files that are supplied by PTC or changing configuration settings that
interact with the way PTC delivers software maintenance releases. The chapter
contains information that can help you understand how to structure and maintain
the files you modify or add to your Windchill environment. It also describes the
tools and Windchill Service Pack options that can be used to set up and update
customized files for Windchill maintenance releases.

Note
These recommendations apply to managing the <Windchill> installation
directory (where <Windchill> is the Windchill Services installation
directory). Best practices for products installed into other directories are not
described here.
If the implementation of Windchill at your site involves modifying files
supplied by PTC, it is important to understand that the maintenance
installation process could overwrite any file that is delivered by PTC (except
for the site.xconf file). This includes files that you may have modified
during customization activities.

100 Customization Guide


Setting Up a Directory Structure for
Managing Customized Files and Text
Tailoring
To customize a Windchill system it is often necessary to modify files released by
PTC. Because these files can subsequently be updated by PTC in a maintenance
release, you should use a strategy for managing your files so that your
customizations are not lost when the maintenance updates are installed.
As a general rule, the Windchill Service Pack installer can overwrite any files that
are in established PTC directories under the installation directory where the
Windchill product is installed, regardless of their modification status. It is your
responsibility to manage your customized files to avoid loss of your changes and,
when updates are applied, to be able to easily identify PTC changes that affect the
files you have modified.
PTC recommends that you manage customized files by creating a directory
structure known as the safe area. The actual directory name is <Windchill>/
wtSafeArea, where <Windchill> is the directory where Windchill Services is
installed. By using the wtSafeArea directory, you can store copies of the
customized versions of PTC files where they will not be overwritten by the
Windchill Service Pack installer, as well as keep versions of the original PTC
files. Additionally, the Windchill Service Pack installer uses this safe area to store
updated files that correspond to your customized files. You can then compare the
original files to those updated by PTC to identify where changes have been made.
Doing the comparison can assist you in incorporating PTC updates into your
customized files. PTC provides a script to assist with managing and installing
customized files into your system runtime locations within the <Windchill>
installation directory.
Additionally, if you make changes to resource bundle information files (RBINFO
files), then you must use the <Windchill>/wtCustom directory structure to store
those changes.

Managing Customizations 101


Directory Structure Diagram for Customized Files
and Text Tailoring
The following diagram gives an example directory structure that includes the
wtCustom directory for text tailoring and the wtSafeArea directory for other
customizations. The wtSafeArea directory contains subdirectories for storing site-
modified (i.e., customized) files and corresponding current versions and original
versions of the files that PTC has delivered. Following the diagram are the details
about how these directories are used.

Safe Area Directory Structure


Under the wtSafeArea directory shown in the previous diagram, notice that a
similar directory structure is shown for the siteMod, ptcCurrent, and ptcOrig
subdirectories. For example if the installed file <Windchill>/codebase/
templates/abcx.html has been modified, then the following set of related
files is located under the wtSafeArea directory:
wtSafeArea/siteMod/codebase/templates/abcx.html
wtSafeArea/ptcCurrent/codebase/templates/abcx.html
wtSafeArea/ptcOrig/codebase/templates/abcx.html
The following summary describes the purpose of each subdirectory:
siteMod – contains the site version of each PTC file that you have modified and
want to run in production.
ptcCurrent – contains the current PTC version of the file. This is a version
newer than the version in the ptcOrig directory and is copied to the directory by
the Windchill Service Pack when the installer finds a corresponding file in the
siteMod directory.

102 Customization Guide


ptcOrig – contains the original file from PTC. Put the version of the file in this
directory before you modify it for the first time and place the customized version
in the siteMod directory.
The following items describe the purpose and processing of the files under each of
the subdirectories in more detail:
• siteMod
○ Under this directory structure, store the site version of PTC files that you
modify and want to run in production
○ When running the Windchill Service Pack installer, selecting the Complete
installation type option directs the installer to copy files from the siteMod
directories to the selected installation directory. The files that are copied
overwrite existing files in the installation directory. The actual file copying
is done by the execution of the installSiteChanges target of the
<Windchill>/bin/swmaint.xml Ant script. For more information
on this target, see PTC Script for Working with Customized Files on page
105.
As described in PTC Script for Working with Customized Files on page
105 there are a few files that you should not put under the siteMod
directory.
○ You must place and update files in this directory yourself; the Windchill
Service Pack installer does not modify the files in the directory.
○ Although the previous diagram only shows a codebase subdirectory of
siteMod, modified versions of files from other directories can also be
deployed from the siteMod directory. For example, you can add a tasks
directory under the siteMod directory and in that directory, store
customized Windchill Info*Engine tasks.
• ptcCurrent
○ This directory structure holds the most current PTC versions of files you
have modified (as identified by the presence of those files under the
siteMod directory).
○ Windchill Service Pack installer automatically places files in this directory
when the following things are true:
◆ The siteMod directory exists.
◆ There are files in the siteMod directory that are being updated by the
service pack installer.
The files copied to the ptcCurrent directory are the files in the service pack
that have the same name as files found in the siteMod directory. Instead of
copying these files to your installation directory, the files are put in the
ptcCurrent directory. This means that your customized files are not
overwritten by the updated PTC files.

Managing Customizations 103


After running the service pack installer (using any of the installation
types), this directory contains updated PTC versions of the set of files that
have been modified at your site.
○ A file appears in the ptcCurrent directory when PTC delivers an updated
version in a maintenance release, but only after you initially create your
customized version in the siteMod directory.
• ptcOrig
○ Before making first-time modifications to a file, put a copy of the original
PTC file in this directory. The original PTC file is the last version of the
file that PTC delivered prior to making modifications. This file could be
the file supplied in a major release or in one of the maintenance releases.
○ You must place files in this directory yourself; the Windchill Service Pack
installer does not modify the files in the directory.
○ ptcOrig is a suggested directory name; there are no PTC tools that actually
look for this name.
After setting up this directory structure and installing updated files, you can
compare the most recent version of a file from PTC (located in the ptcCurrent
directory) with the currently deployed file (located in the siteMod directory) and
the original version of the file (located in the ptcOrig directory). From the
comparisons, you can determine how the version in the siteMod directory should
be updated to incorporate the latest changes from PTC. For additional
information, see Using the Safe Area Directory Structure When Installing the
Windchill Service Pack on page 108.

Text Tailoring Directory Structure


Store your updates to PTC-supplied RBINFO files in the wtCustom directory
shown in Directory Structure Diagram for Customized Files and Text Tailoring on
page 102. The details on which files can be updated and how to do the updates are
in Best Practices for Customizing Files Supplied by PTC on page 109.

104 Customization Guide


PTC Script for Working with Customized Files
PTC provides the swmaint.xml Ant script to help you manage the files in the
<Windchill>/wtSafeArea/siteMod directory. The swmaint.xml script is
installed in the <Windchill>/bin directory during Windchill Services
installation.
To obtain a list of all swmaint.xml script target options, enter the following ant
command from a Windchill shell:
ant -f bin/swmaint.xml -projecthelp

Following is a list of the most common target options:


• createSafeArea – creates the <Windchill>/wtSafeArea/siteMod,
<Windchill>/wtSafeArea/ptcCurrent, and <Windchill>/
wtSafeArea/ptcOrig directories.
• listSiteChanges – lists the files in the siteMod directory.
• installSiteChanges – copies the files under the <Windchill>/
wtSafeArea/siteMod directories to their corresponding <Windchill>
installation directories. The timestamps on files from the siteMod directory
are preserved when the copying is done.
There are a few files and directories that could be present under
wtSafeArea/siteMod but are not copied. For example, the files under the
following wtSafeArea/siteMod directory structures are not copied to
installation directories:
.xconf-backup
installer
logs
codebase/instreg
tasks/codebase
temp
vaults
wtCustom
wtSafeArea

Note
Most of these directories contain files that you should never modify;
therefore, the directories should not be in the wtSafeArea/siteMod
directory. If you happen to have files in any of these directories, the target
reports that the files were not copied.

Managing Customizations 105


The following files in the wtSafeArea/siteMod directory structure are also not
copied to installation directories:
bin/swmaint.xml
codebase/.xconf-target-file-hints
declarations.xconf
site.xconf
For an up-to-date list of files and directory structures excluded when the
installSiteChanges target option is processed, see the output from the
listSiteModExclusions target option (described next).
• listSiteModExclusions – lists the files and directory tree structure
patterns of those files and directories that are excluded when the
installSiteChanges target option is processed.
• listSiteChangesIgnored – lists the files under the <Windchill>/
wtSafeArea/siteMod directory that are not copied to corresponding
<Windchill> installation directories when you run installSiteChanges. This
target option is also run when you run the swmaint.xml script with the
listSiteModExclusions target option.
• MakeJar.xml – a script to build JAR files and maintain a network of definition
files for building jar files. For more information see Managing Client JAR
Files on page 115.
Executing the swmaint.xml script is always done from an ant command. For
example, from a Windchill shell, execute the following ant command to copy the
siteMod files to their executable location:
ant -f bin/swmaint.xml installSiteChanges

106 Customization Guide


Using the Safe Area Directory Structure When Customizing
Files

Note
The following descriptions assume that you have set up your safe area
directory structure, as described in Directory Structure Diagram for
Customized Files and Text Tailoring on page 102.

Use the following procedure to modify a PTC file for the first time:
1. Copy the original version of the PTC file into the proper subdirectory under
the ptcOrig directory. For example, copy:
<Windchill>/codebase/templates
/adcx.html
to:
<Windchill>/wtSafeArea/ptcOrig/codebase/templates/
abcx.html.
2. Also copy the file to the siteMod directory and then make your modifications
to the file that is in the siteMod directory. For example, copy the abcx.html file
as follows and then modify the copied file:
<Windchill>/wtSafeArea/siteMod/codebase/templates/
abcx.html.
3. When you are ready to use the customized files in your <Windchill>
installation directory, copy the customized files into the installation directory.
Run the following swmaint.xml script from a Windchill shell to complete this
step:
ant -f bin/swmaint.xml installSiteChanges

The script is described in PTC Script for Working with Customized Files on
page 105.

Managing Customizations 107


Using the Safe Area Directory Structure When Installing the
Windchill Service Pack
Use the following procedure to incorporate updates at a maintenance release:
1. Run the Windchill Service Pack installer using the Updates for Site-Modified
Files to Safe Area installation type. Using this option puts the updated PTC
versions of customized files in the ptcCurrent directory. (A file is copied into
the ptcCurrent directory only if the file exists in the siteMod directory.)
2. Using the three versions of the file found in the siteMod, ptcOrig, and
ptcCurrent directories, determine what changes PTC has made in this
maintenance release to each of your customized files.

Note
If there is no corresponding file in the ptcCurrent directory, then there are
no updates for the file in the current maintenance release.
You can run the following swmaint.xml script from a Windchill shell to
list the site changes contained in files that are under the wtSafeArea/
siteMod directory:
ant -f bin/swmaint.xml listSiteChanges

Additionally, other target options described in PTC Script for Working


with Customized Files on page 105.

3. Update each filed that is in the siteMod directory appropriately.


4. After all files in the siteMod directory have been updated, run the following
swmaint.xml script from a Windchill shell to copy the files into place for
testing.
ant -f bin/swmaint.xml installSiteChanges

Running this target also lists all files that are not copied. Normally, there
should be no files listed. Inspect any files listed to determine why they were
not copied. If they were in the wrong directory, put them in the correct
directory and rerun the script.

Note
The Windchill Service Pack installer executes this script and target
automatically whenever there is a siteMod directory and you select the
Complete installation type.

108 Customization Guide


Best Practices for Customizing Files
Supplied by PTC
The following sections call out specific file types and directories where sites
typically modify PTC files. The text recommends procedures to follow that work
in concert with the maintenance installation process to avoid unexpected file
overwrites.
If you are modifying files that are not specifically identified in the following
sections, consult Setting Up a Directory Structure for Managing Customized Files
and Text Tailoring on page 101 to determine if the procedures outlined there can
assist with managing your changes.
Often, sites make changes to the following types of files:
• RBINFO files
• *.properties files
• HTML templates
• XML files
• Windchill Info*Engine tasks
• INI files
• Client JAR files
Additionally, your site may modify other files in the codebase directory.
Use the information in the following sections to help you manage your
customizations.

Changing Displayed Text Found in RBINFO Files


To ensure that site changes to displayed text that resides in RBINFO files is
properly handled, note the following points:
• Site changes to PTC text values should be stored in RBINFO files that are in
the <Windchill>/wtCustom directory structure. Never edit the RBINFO
files in the <Windchill>/src directory. When the enumCustomize tool
is used, it creates the required wtCustom directory structure.
• Changes to displayed text may have an effect on resources that are
incorporated in client JAR files. Make sure to consult Managing Client JAR
Files on page 115.
• The Windchill Service Pack and patch installers automatically re-compile
these resources so maintenance updates and your site changes are re-
combined.
The following sections provide additional details on text tailoring and updating
client JAR files. For general information about the enumCustomize tool, see
Enumerated Types on page 1973.

Managing Customizations 109


For recommendations on where and how to create new localized resources (for
example, new RBINFO files), see Best Practices for Adding New Packages and
Files on page 129.

Details on Tailoring Text


The text that is displayed in most of the user interface, be it HTML or Java-based
UIs and regardless of the locale, is produced from text stored in RBINFO files.
The files installed to the directory <Windchill>/src contain PTC text, site
changes to the displayed text are to be done to corresponding files in the
<Windchill>/wtCustom directory. There is a clear structure relationship
between RBINFO files in the <Windchill>/wtCustom directory, the
<Windchill>/src and the <Windchill>/codebase directory. For example, the
list of valid life cycle states are stored as compiled resources in <Windchill>/
codebase/wt/lifecycle/StateRB*, original PTC sources are in
<Windchill>/src/wt/lifecycle/StateRB*.rbInfo, and any site
modifications must be stored at <Windchill>/wtCustom/wt/
lifecycle/StateRB*.rbInfo.
The files under <Windchill>/src should never be edited. This is because these files
can be overwritten during a maintenance installation, thus losing site
modifications.
There are three kinds of text stored in RBINFO files. For all of these, site changes
should only be done in files under the <Windchill>/wtCustom directory.
• Text for enumerations (EnumResourceInfo – lists of values) is changed using
the enumCustomize tool that is launched from <Windchill>/bin/
enumCustomize. Using the enumCustomize tool creates the required files in
the wtCustom directory and stores the values you replace.
• Text for many string messages, user interface (UI) buttons, and labels are
declared in WTListResourceBundle classes, but they are changed by placing
site-specific values in the wtCustom/wt/util/resource/
resourceCustomize.rbInfo file.
For more information on customizing these values, see the documentation in
this file: <Windchill>/src/wt/util/resource/
resourceCustomize.rbInfo

• Displayable text for modeled business information such as classes, attributes,


relationships, and so on (MetadataResourceInfo) is changed by placing site
specific values in RBINFO files in the wtCustom directory. By using a text
editor, enter only the values you want to override in the files; values that you
are not changing should not be included.
For your text changes to be used by the running product, they must be compiled
into the codebase. Running the enumCustomize tool does this automatically, but
only for EnumResourceInfo resources. However, all three kinds of resources can

110 Customization Guide


be compiled by using the ant script <Windchill>/bin/tools.xml and the
bundle_custom target. To use this script, start a Windchill shell and execute
the following command:
ant -f bin/tools.xml bundle_custom -Dbundle.input=registry

Both the Windchill Service Pack installer and patch installer automatically
execute this command to ensure that any updates delivered by PTC are merged
with your site changes in the <Windchill>/wtCustom directory.
For text changes that are to be used by any applets, you must additionally execute
the MakeJar command as follows:
ant -f <Windchill>/codebase/MakeJar.xml custUpdate

See Managing Client JAR Files on page 115 for more information. For example, if
you add a life cycle state to StateRB.rbInfo, you must run the above command to
see the new state in an applet such as the Lifecycle Administrator.

Managing codebase Property Files


In most cases, the property files (*.properties) in the codebase directories should
only be modified by using PTC tools, and never manually edited. This is a major
change from previous Windchill releases, where editing property files was very
common. There are two key points regarding property files:
• Use either the xconfmanager utility to make property file changes. Additional
information on these topics is covered in the next two sections.
• When you cause a property file to be changed, you may need to update
downloadable client JAR files. Make sure to consult Managing Client JAR
Files on page 115.

Manipulating Property Files


Most property files should be manipulated using the xconfmanager utility. The
reason to use either of these tools is that they store the property values you set in
the <Windchill>/site.xconf file. They then propagate those values to the
proper *.properties files. (Comment blocks are placed at the top and bottom of *.
properties files that the xconfmanager has updated.) If a PTC maintenance update
delivers changes to properties that you have changed, the xconfmanager
automatically propagates the property changes stored in your site.xconf file on top
of the PTC updates.
In many cases, there is a one-to-one correspondence between an *.xconf file and
its *.properties file; for example codebase/wt.properties.xconf and codebase/wt.
properties. In other cases, there is not a matching XCONF file. Even without an
associated XCONF file, a properties file can still be manipulated with the
xconfmanager Utility.

Managing Customizations 111


The following codebase properties should not be manipulated with the
xconfmanager Utility:
• associationRegistry.properties
• descendentRegistry.properties
• modelRegistry.properties
• moduleRegistry.properties
• moduleDir.properties
• debug.properties
This is because these properties contain properties not suitable for the
xconfmanager Utility.
If there are a lot of new properties that you need to add to a file such as wt.
properties, rather than using xconfmanager Utility to set each property, consider
creating your own declarative XCONF file. In this file, you declare the properties
with a targetFile of wt.properties. Then use xconfmanager Utility to install this file
into the declarations.xconf file. For an example of creating a service provider
property file, see Adding a Custom Service Provider Property File on page 130.

Using XCONF Files


The XCONF files supplied by PTC are not intended for direct editing. All *.xconf
files, except <Windchill>/declarations.xconf and <Windchill>/
site.xconf should be considered read-only. The declarations.xconf and site.
xconf files are both manipulated by the xconfmanager Utility. See Using the
xconfmanager Utility on page 164 for details on using the xconfmanager Utility.

Managing HTML Templates in the <Windchill>/


codebase/templates/ Directory
The HTML template files are located in the <Windchill>/codebase/
templates directory. These files must be in this directory at runtime. If you
want to modify any of the files in this directory, be sure to put a copy of the
corresponding PTC files (before you make any changes) in the <Windchill>/
wtSafeArea/ptcOrig/codebase/templates directory. Then modify
the files and put a copy of your customized files in the <Windchill>/
wtSafeArea/siteMod/codebase/templates directory. For details on
using the <Windchill>/wtSafeArea directory, see Setting Up a Directory
Structure for Managing Customized Files and Text Tailoring on page 101.

112 Customization Guide


Managing the LogicalAttributes.xml File
The LogicalAttributes.xml file is used to assign logical names to the
attributes of business objects. These logical names are used to identify the
attributes when configuring certain clients. For details on the format and content
of the file, see the file itself and the corresponding Javadoc.
The file is located in the <Windchill>/codebase directory. To prevent
overwriting, use the safe area procedures as described in Setting Up a Directory
Structure for Managing Customized Files and Text Tailoring on page 101.

Managing codebase/{wtcore,netmarkets,pdmlink}
Files
If you have a requirement to modify any of the files, such as JSP files, under the
<Windchill>/codebase/wtcore, <Windchill>/codebase/
netmarkets, or <Windchill>/codebase/pdmlink directories, be aware
that during a maintenance installation the PTC updates to the same files could
overwrite your changes.
To prevent overwriting, you should utilize the safe area procedures as described in
Setting Up a Directory Structure for Managing Customized Files and Text
Tailoring on page 101.

Managing Windchill Info*EngineTasks


Windchill Info*Engine tasks are stored in the <Windchill>/tasks directory.
If you customize any of the task files, they could be overwritten during a
maintenance installation if PTC must update the same task files.
To prevent overwriting modified tasks, you should utilize the safe area procedures
that are described in Setting Up a Directory Structure for Managing Customized
Files and Text Tailoring on page 101. For example, if you needed to modify a task
in the tasks/com/ptc/windchill/enterprise directory, first put the
original PTC version in the wtSafeArea/ptcOrig/tasks/com/ptc/
windchill/enterprise directory and your modified version would go into
the wtSafeArea/siteMod/tasks/com/ptc/windchill/
enterprise directory.

INI Files for Workgroup Manager


If you modify any INI files for the workgroup managers, then you should copy the
originals to the ptcOrig directory and put your modified versions in the siteMod
directory.

Managing Customizations 113


The Workgroup Manager for Pro/ENGINEER 2001 has the following INI files:
• proefileadapter.ini
• newdocument.ini
• proeworkspaceconfig.ini
• registryclient.ini
The Workgroup Manager for CATIA V4 has the following INI files:
• catiafileadapter.ini
• newcatiadocument.ini
• catiaworkspaceconfig.ini
• registryserver.ini
• registryclient.ini
The Workgroup Manager for CADDS has the following INI files:
• cadds5workspaceconfig.ini
• registryclient.ini
• newdocument.ini

114 Customization Guide


Managing Client JAR Files
Clients need to have the same versions of client JAR files as those located on the
Windchill server in <Windchill>/codebase. Customizations to displayed text and
properties can require that JAR files downloaded to clients are updated.

Note
When the client JAR files are updated, clients download them from the
Windchill server as the applications detect the previously downloaded JAR
files are out-of-date.

There are two times when you need to ensure that the client JAR files have been
updated by rebuilding the files. Rebuild client JAR files:
• As part of installing a maintenance release.
• When customizations have been made that affect the client JAR files

Note
When updating for a maintenance release, running Windchill Service Pack
installer with the Complete installation type rebuilds all client JAR files as
needed. If you make new customizations or re-install existing customizations
after running this installer, you must manually rebuild the client JAR files.

Most client JARs are maintained through the use of an Ant script, MakeJar.xml,
provided with Windchill. To ensure that the JAR files maintained through the
MakeJar.xml script are updated correctly, you should add the following to the
<Windchill>/codebase/jarContents/Cust.bom:
• Paths for the compiled resources (*.ser and/or *.class files) of the files you
change
• Paths of customized property files
To verify that all customized property files are listed in Cust.bom, you can
compare targetFile entries in site.xconf with the files listed in Cust.bom. Any files
listed in targetFile entries that are not in Cust.bom should be added to Cust.bom.
For example, if the site.xconf file has an entry for the following:
targetFile="codebase/wt/change2/change2.properties"

Then, ensure that codebase/jarContents/Cust.bom contains the following entry:


wt/change2/change2.properties

Managing Customizations 115


To rebuild the client JAR files that are managed by jarContents and jarManifest
specifications, execute the following command from a Windchill shell:
ant -f codebase/MakeJar.xml custUpdate

See Rebuilding Client JARs on page 120 for more information.

Overview of Client JAR Deployment Approach


To effectively manage your client JAR customizations, you need to understand the
Windchill approach to client JAR deployment.

Logical JARs
The concept of a “logical” JAR was introduced to Windchill in R7.0. Each logical
JAR is actually composed of four JARs, in addition to any external dependencies
it might have, e.g. to 3rd-party jars. The components of a logical JAR are shown
in the figure below.

In this figure, the bolded labels denote role names for each component JAR
whereas the italicized name denotes the actual name of the JAR. Thus for a logical
JAR named “MyApplet”, for instance, the components would be MyApplet.jar,
MyAppletCust.jar, MyAppletDSU.jar, and MyAppletFCS.jar.

Note
The classloading precendence is from left to right in the figure, so that
customization JARs override DSU JARs, which in turn override original
distribution JARs.

Head JARs only include manifests declaring the component and other JARs upon
which they depend, as well as a JAR index in cases where the head JAR is the top-
level JAR for an applet. PTC distributions leave customization JARs empty, as
these are for customer additions and overrides (e.g. to resource bundles). DSU
JARs are left empty until a maintenance release provides additional files to target
client(s) and/or newer versions of files already present in the corresponding FCS
JAR. The FCS JAR contains all the original files required by a module at FCS
(first customer shipment). The head JAR may list additional JARs upon which it is
dependent after its own components.

116 Customization Guide


Note
The usage of “DSU” comes from the fact that, pre-R7.0, maintenance releases
to Windchill were delivered in Downloadable Software Updates.

Modular Client JARs


In addition to breaking logical JARs into different components for customization,
maintenance releases, and original distribution, an effort has been made to break
client JARs into appropriate modular components so that resources required by
one applet are not automatically downloaded by all applets.
This effort has been balanced with a desire to prevent any resource from being
downloaded more than once, that is, included in more than one FCS JAR. DSU
and Customization JARs will indeed duplicate resources contained by
corresponding FCS JARs to override them without requiring an FCS JAR rebuild.
Indeed only in small, targeted cases is a resource downloaded in more than one
FCS JAR.
In general, these efforts have led to the use of a dependency tree (more precisely, a
unidirected graph) of logical JARs as described in the following section.

Current Foundation JAR Tree Definition


A representative view of the dependency graph of the client JARs is shown below.

Note
The figure and the table following it constitute merely a representative view,
not necessarily the complete dependency graph.

Each label refers to a logical JAR (composed of head, customization, DSU, and
FCS components) unless otherwise noted. Bolded labels are “root” JARs intended
as top-level JARs to directly support applets, whereas the non-bolded labels are
intended solely for re-use from other JARs. Each arrow implies a dependency
(and essentially inclusion by reference) in the direction of the arrow. It should thus
be clear that all JARs currently defined depend on wtApplet and 3rdPartyApplet
with the notable exception of wtBootInst. Thus all duplicates are consolidated
down the tree except from wtBootInst which is completely independent. The
graph shown supports almost all of the Windchill Foundation applets and will
certainly grow over time.

Managing Customizations 117


These logical JARs are further described in the following table.
Logical JAR Description
3rdPartyApplet A head JAR which collects all the commonly
required 3rd-party libraries into a single point of
reference. As such it does not include any separate
resources and thus has no customization, DSU, or
FCS components. Rather it is purely an ordered list
of references to 3rd-party libraries. This list is
similar to that found in 3rdparty.jar but has had all
library references which do not make sense for
applets (e.g. JSSE) removed.
wtApplet Common base (non-3rd-party) resources shared
amongst most Windchill applets. Like all other
shared logical JARs, this JAR serves to collect all
resources which would otherwise have been
duplicated in JARs above it. Please note that the
intermediate JARs wtPolicy, wtQB, and wtWork
also serve to consolidate duplicates between
themselves and JARs above them.
wtBootInst The JAR for the Bootstrap loader installation
applet. This is currently the only root applet JAR
which is not based on wtApplet. This JAR does
duplicate a few resources from wtApplet, but this
JAR was kept separate as it had so little overlap
with wtApplet and without this dependency could
be kept extraordinarily small and lightweight.
wtPolicy The JAR for the Policy Administration and domain
browser/selector applets.
wtQB The JAR for the QueryBuilder and Report
Management applets.
wtWork The JAR for the Workflow, Life Cycle, and Team-

118 Customization Guide


Logical JAR Description
related Applets (Workflow Administration, Team
Administration, Lifecycle Administration, Initiate
Process, Process Manager, and Setup Participants).
wtFVault The JAR for the External and Remote File Vault
Administrator applets.
wtExp The JAR for the Windchill Explorer applet. Note
that this JAR references / depends-on wtPolicy,
wtQB, and wtWork as many of the clients
supported by these JARs can be launched from
within Windchill Explorer.
Note
This JAR is obsolete as of Windchill release
9.0.
wtCal The Calendar applet JAR.
wtESig The electronic signature/identity applet JAR.
wtIXB The JAR to support import/export and bulk-
loading applets.
wtSearch The JAR to support Applet.jsp, AppletQuery.jsp,
and ChooserTask.html customization samples.
This JAR essentially only contains the top-level
applet class and exists primarily to keep wtApplet
from containing any applet-specific resources and
to provide a simple top-level JAR sample.
wtTypeAdm The JAR for the Attribute Administrator, Type
Manager, CSM, and Re-Use Manager applets
wtLogin The JAR for the login/reauthentication applet (i.e.
that accessed via Login.jsp).
ptcAnnotator, ptcCore (not The JARs for the Product Structure Explorer (PSE)
shown) applet. There are no customizable or inheritable
classes in these JARs.
Note that wt.jar and 3rdparty.jar, the JARs used in Windchill applet deployments
prior to R7.0 are not used at all by the new applet deployments. Both of these
JARs are now the sole province of any applications which use them to maintain
and use as they see fit. The new JARs are dramatically smaller than wt.jar.

Using the Client JAR Architecture


The following sections discuss how you should use the client applet JARs.

Managing Customizations 119


Rebuilding Client JARs
The client JARs are built via the Java SDK's jar command and an Ant script
(MakeJar.xml) that coordinates the builds of the client JARs and other related
activities (e.g. consolidation of duplicate entries, removal of known inappropriate
resources, and updating JPI cache versions.
To rebuild all of the new client JARs, one can simply type:
ant -f MakeJar.xml

from a command prompt in the <Windchill>/codebase directory.

Caution
As a general rule, customizers should not use this command pattern, as it will
rebuild the FCS jars and cause unnecessary downloads by clients that have
already downloaded the FCS jars by this point. Instead, 'custUpdate' and
'dsuUpdate' targets, as described in the following sections, should be used.

If you are using Java 2 v1.4.x, then any resources listed in a .includes file which
are not present in your codebase will result in an error. To remove any such
resources from your .includes files, add the following to your MakeJar.xml
command line:
-DremoveStaleEntries=true

Although it takes only a couple minutes or so to rebuild all client JARs, in most
cases you are only testing an applet or two at a time. In this case you will wish to
the faster Ant targets for individual applets. For instance, to rebuild all JARs
loaded by a workflow applet, one would use (all on one line):
ant -f MakeJar.xml buildFullClientJars -DlogicalJarNames=wtWork

Omitting the '-DdoDeepBuild=true' argument would limit the rebuild to the


wtWork JARs, i.e. it would not rebuild the wtApplet JARs and so forth.
To determine what actions a command would perform, without actually
performing them, the following argument can be added to the command line for
any of the MakeJar.xml targets:
-DtraceOnly=true

The MakeJar.xml script contains targets allowing a wide variety of JAR building
and maintenance operations to be performed for one or more JARs or sets thereof.
To obtain more information on these targets, execute the following command:
ant -f MakeJar.xml -projecthelp

120 Customization Guide


Managing Client JAR Contents
For optimal performance, all resources (.class files, .properties files, etc.) needed
by a Windchill applet should be contained within one of the client JARs it uses.
Each resource not found within one of an applet's client JARs that is needed by
the applet will require a separate round-trip network request and the resource will
not be compressed as it would be if it was part of a client JAR. This leads to
especially poor performance on slow or wide-area networks. Providing the correct
content in a client JAR file helps ensure optimal performance of the applet. If you
have any customized applets, their JARs may not contain all the custom resources
they require. If you suspect that the client JAR file used by an applet does not
have the correct contents, you can determine which missing resources should be
added.
After customizing applets or JARs, you can identify what resources are used by an
applet but are not contained in the corresponding client JAR files as they should
be. If you are using the PTC HTTP Server (powered by Apache), PTC provides
the HTTP Request Log utility that can be used to identify resources that are
missing from a client JAR file and can then be added to the client JAR file.
Use the following steps to determine which resources are missing from a set of
client JAR files.
1. Open the HTTP Request Log utility. This marks the location of the current end
of the PTC HTTP Server (powered by Apache) log file so that all entries
added to the file can be examined to see if they identify resources that have
been downloaded to the client.
2. In a browser window, open the applet associated with the client JAR files and
test the applet functionalities you wish to ensure/troubleshoot the performance
of.
Any resource downloaded for use in the client is recorded in the Web server
access log. The HTTP Request Log utility searches the log file for the resource
requests made of types peculiar to applets (for example, .class and .properties
files) since you opened the utility in step 1. These resources were not found in
the client JARs and thus were being pulled from the Web server.
3. Use the results from the utility to update the appropriate client JAR files.
The following section provides details about using the HTTP Request Log utility.

Using the HTTP Request Log Utility


You can use the HTTP Request Log utility to determine which resources are
missing from the client JAR files used by Windchill applets. It searches the PTC
HTTP Server (powered by Apache) log file, either by a specific user or all users,
for specified file extensions and displays them in sorted order.

Managing Customizations 121


Note
To use the utility, you must be using the Apach Web server.

1. Log in as a user named in the wt.sysadm.administrators property in the wt.


properties file. For example, if the property value is:
$(wt.admin.defaultAdministratorName),demo
You can log in as the demo user or the user stored in the wt.admin.
defaultAdministratorName property.
2. In the browser window, access the following page:
<local_host_name>/<Web_app_name>/wtcore/jsp/wt/sysadm/HttpRequestLogUtil
Start.jsp.

The HTTP Request Log Utility Start Page opens:

3. In a separate browser window, start to the applets you want to test and
complete your testing.
4. Return to the browser window where you started the HTTP Request Log
Utility Start Page. Click View single client results to view the results from your
testing session. Click View all client’s results to view the results from all
sessions recorded.

122 Customization Guide


The results are a sorted list of all of the resources that were accessed during
the testing that are not contained in a client JAR file. Use this input to update
the appropriate JAR files. For example, if the list is as follows:

5. Copy the resources from the resulting list and paste them into the following
file:

Managing Customizations 123


<Windchill>/codebase/jarContents/
<topJarName>Cust.includes
<topJarName> is the leafname of the top-level JAR used by the applet. For
example, the QueryBuilder top-level JAR in the applet tag is wtQB.jar.
Therefore, paste the resources into the file named:
<Windchill>/codebase/jarContents/wtQBCust.includes
6. From a Windchill shell, run the following script from the codebase directory:
ant -f MakeJar.xml custUpdate

Tip
• The search results are only as accurate and complete as the testing you do.
• If the HTTP Request Log Utility Start Page was not accessed before the testing,
the entire log file is searched. Otherwise, the search begins from the point in
the log that immediately follows your most recent access.
• The types of resource files that are searched for can be configured. By default,
the defined extensions are .class, .ser, and .properties. To change from the
default, edit the fileExtensions variable in wtcore/jsp/wt/sysadm/
HttpRequestLogUtilStop.jsp file.

Note
Depending on the servlet engine configuration you may have to restart the
servlet engine for these changes to take effect.

• To find all resources needed for an applet, remove the client JARs used by the
applet and use the previous steps to log all resources that are used. This type of
testing creates a lot of network traffic since every resource is downloaded
from the server. You would typically only do this type of testing if you
believed the client JARs contained significantly more resources than were
required for your use cases. This generally should not be done with PTC
supplied *FCS.jar and *DSU.jar files.

124 Customization Guide


Note
If, using the above methods, you discover that there are resources missing
from Windchill client JARs that you have not modified, file a problem report
with technical support. Include the following in the report:
• The list of missing resources.
• The applet or root JAR against which the testing was being performed.
• A brief description of the functionalities exercised.
• The exact build against which the testing was performed.
• The version of the Java Plug-In used in the testing.
• The client OS.

Adding New Applets

Re-using an Existing Root JAR


If you have decided to directly re-use an existing root JAR for the applet(s) in
question, then all you have to do is list this JAR in the plug-in tag.

Using a New Logical Root JAR


In the case where a new JAR is to be added, however, the necessary steps are as
follows.
1. Create content and manifest description files for your logical JAR's
components. You can use a target within MakeJar.xml to do this for you by
executing the following in codebase:
ant -f MakeJar.xml makeNewJarDescr -DlogicalJarName=
logicalJarName

For example, for a new logical JAR, foo, one would execute:
ant -f MakeJar.xml makeNewJarDescr -DlogicalJarName=foo

• This creates an empty FCS .includes files for the specified logical JAR in
codebase/jarContents, e.g. for a logical JAR, foo, this file would be
fooFCS.includes.
• This also creates head, Customization, DSU, and FCS .manifest files in
codebase/jarManifests for the specified logical JAR, e.g. for a logical JAR,
foo, these files would be foo.manifest, fooCust.manifest, fooDSU.
manifest, and fooFCS.manifest. All of these files except the head manifest
(e.g. foo.manifest) are initially empty. The head manifest defaults to have a

Managing Customizations 125


Class-Path entry listing the Customization, DSU, and FCS JAR
components of the logical JAR followed by wtApplet.jar, e.g. for a logical
JAR, foo, the entry would be:
Class-Path: fooCust.jar fooDSU.jar fooFCS.jar wtApplet.jar

This entry should be amended if your logical JAR does not depend on
wtApplet.jar or has additional dependencies - in either case these should be
listed after the FCS JAR entry.
2. Create a .set file in <Windchill>/codebase/jarManifests that includes the
logical name of your new JAR.
3. Build your JAR by executing an appropriate target on the MakeJar.xml script
(from the codebase directory), e.g.:
ant -f MakeJar.xml buildFullClientJars -DlogicalJarNames=foo

where “foo” should be replaced by the name of your logical JAR.


4. Test your new JAR by using it in your applets' plug-in tags, recording missing
resources via the HTTP Request Logging utility as described in Using the
HTTP Request Log Utility on page 121.
5. Update your new JAR's contents as described in Using the HTTP Request Log
Utility on page 121.
6. Re-test your applet.

Updating Client JARs At Maintenance Releases


Because of the inclusion of DSU JARs in the logical JARs, clients only have to
download resources that were added or changed as part of the maintenance release
(plus new root head jars), not the entire set of client JARs.
The process of rebuilding the client JARs at a maintenance release has been
automated via the following command (note that this command rebuilds
Customization JARs when necessitated by new or updated DSU JARs):
ant -f MakeJar.xml dsuUpdate

This command executes the following targets:


• createCodebaseDsuBOM: Takes entries in codebase/../*_bom.txt BOM files
which are in codebase and places them in jarContents/DSU.bom, but written
relative to codebase (i.e. it removes "codebase/" from each entry).
• updateDSUIncludes: Intersects each FCS .includes file with jarContents/DSU.
bom and adds the intersection to the corresponding DSU .includes file.
• updateCustIncludes: Intersects each FCS .includes and DSU .includes file pair
with jarContents/Cust.bom and adds the intersection to the corresponding
Customization .includes file

126 Customization Guide


• expandJarLocales: For resource bundles represented by _en localization in
DSU and FCS .includes, places other localizations requested in jarContents/
clientJarLocales into Customization .includes
• removeNonexistantDsuAndCustEntries: Removes any entries from the
Customization and DSU .includes files which are not found in codebase.
• buildDSUClientJars: Rebuilds all DSU and Customization jar components.
Also builds all indexed head jars which are parents (directly or indirectly) of
these jars.
The only steps omitted by dsuUpdate for the Foundation resources and jars are:
• The addition of any new DSU jar entries required for reasons other than being
in the intersection of the DSU BOM and FCS jar contents (e.g. previously
missed entries, new classes, etc).
• The inclusion of a codebase/../*_bom.txt file containing the files changed by
the DSU.
These should both be provided (e.g. as updated DSU .includes files and a foo_
bom.txt file) as part of the maintenance release itself.

Updating Client JARs for Customizations


The Customization JAR components exist to allow customization additions and
overrides to the out-of-the-box JAR sets as these components take load
precedence over the corresponding DSU and FCS components.
A customer or customizer can add entries to any Customization .includes files
they want and rebuild the corresponding JAR via:
ant -f MakeJar.xml buildCustClientJars
-DlogicalJarNames=jar1,jar2,…

where “jar1,jar2,…” should be replaced by the list of logical JARs whose


Customization components should be rebuilt.
More often, however, the customer is likely to have a number of files they have
overridden and simply wish to have the client JARs updated to account for this.
This can be done by listing the overridden/customized files in codebase/
jarContents/Cust.bom and then executing the command:
ant -f MakeJar.xml custUpdate

Managing Customizations 127


This command executes the following targets:
• updateCustIncludes: Intersects each FCS .includes and DSU .includes file pair
with jarContents/Cust.bom and adds the intersection to the corresponding
Customization .includes file. Note that Cust.bom contains a few of the most
volatile entries (e.g. properties files regenerated during code generation)
initially out-of-the-box.
• expandJarLocales: For resource bundles represented by _en localization in
DSU and FCS .includes, places other localizations requested in jarContents/
clientJarLocales into Customization .includes
• buildCustClientJars: Re-builds all Customization JAR components. Also,
builds all indexed head JARs which are parents (directly or indirectly) of these
JARs.
Additionally more extensive client customizations can be supported by proceeding
to build new client JAR sets in much the same way as was described for the
previous sections.

Handling Localized Resources


The MakeJar.xml script contains reusable targets which wrap custom Ant tasks
which handle localized resource entries in client JARs.
• standardizeJarLocales: removes all except one locale-specific resource entries
for each resource bundle encountered in the FCS and DSU .includes of the
logical JARs listed by the input property logicalJarNames. Note that the null/
default locale entry is also not removed. This target is used by various targets
including sanitizeAndBuildJarSets to eliminate most of the overhead of
undesired localization in client JARs.
• expandJarLocales: for each resource bundle in the FCS and DSU .includes of
the logical JARs listed by the input property logicalJarName, places the
corresponding entries specific to the locales desired by the site (as specified in
jarContents/clientJarLocales) in the corresponding Customization .includes
files. Conversely, entries from bundles represented in a DSU.includes or FCS.
includes but from locales not requested by the site are removed from the
corresponding Customization.includes. This target is used by dsuUpdate and
custUpdate to ensure that the client JARs support the locales requested by the
site.
As a whole the MakeJar.xml script ensures reasonable handling of site-specific
locale sets. It does not handle user-specific locale sets (i.e., delivery of different
JAR sets to each user depending on their locale settings).

128 Customization Guide


Best Practices for Adding New Packages
and Files
To create custom applications, your site may need to create new packages and
files. You can store new packages and files under the <Windchill>/src/directory
structure; however, the packages and files that are defined should not be stored
under the <Windchill>/src/wt or <Windchill>/src/com/ptc directory.
Typically, newly developed packages and files are stored under the domain name
of your company. For example if your company domain name is mycompany.com,
store them under <Windchill>/src/com/mycompany.

Caution
When you create a new package, you need to add it to the
includeClassStartsWith property in wt.properties. This property lists the
package hierarchies that are included when resolving inherited descriptor
information. For example, if you add the package com.mycompany, use
xconfmanager to add “com.mycompany.” to the property, with the following
command from a windchill shell:
xconfmanager --add com.ptc.core.meta.descriptor.server.impl.
includeClassStartsWith=com. mycompany. -p
Make sure the package name ends with the period (".") character.

The types of files that you should store under <Windchill>/src/com/mycompany


include new Java source files, property files, HTML templates, RBINFO files, and
XCONF files.
In addition to keeping your new packages and files in a <Windchill>/src/com/
mycompany directory structure, you must include corresponding packages and
files in your runtime system. For example, the following list explains where your
files should be placed:
• Java files are typically compiled to a comparable directory under <Windchill>/
codebase. For example, if you create a class under <Windchill>/src/com/
mycompany/part, you could compile it to <Windchill>/codebase/com/
mycompany/part.
• Resource bundle files must be compiled into a directory under <Windchill>/
codebase at runtime. This can be done using the ResourceBuild command. For
example, if you have new RBINFO files in the directory <Windchill>/src/com/

Managing Customizations 129


mycompany/part, you could compile them to the <Windchill>/codebase/com/
mycompany/part directory by executing the following command from a
windchill shell:
ResourceBuild com.mycompany.part
• Property files maintained in a custom directory like <Windchill>/src/com/
mycompany must be copied to a directory in <Windchill>/codebase at runtime.
Often when you integrate new packages and files into your existing environment,
you must change files that were supplied by PTC. Be sure to manage these
customized files as directed in earlier sections.

Note
When you are updating files for a maintenance release, remember to copy any
updated new packages and files that are used in your runtime system from
your test system to your production system.

Modeling Recommendations
Sites that use custom modeled classes using Windchill InformationModeler and
Java Annotations, may store their new packages and classes under the
<Windchill>/src directory structure; however, the packages that are defined should
not be stored under the <Windchill>/src/wt or <Windchill>/src/com/ptc directory.
Typically, newly developed packages and classes are stored under the domain
name of your company, as described previously.
Some customizations can also be stored under the <Windchill>/src/com/
myCompany directory.

Adding a Custom Service Provider Property File


Some site customizations involve creating a new service provider property file.
Service provider property files must be declared in one of the following
<Windchill>/codebase/wt.properties entries:
wt.services.applicationcontext.WTServiceProviderFromProperties.
customPropertyFiles
wt.services.applicationcontext.WTServiceProviderFromProperties.
defaultPropertyFiles
wt.services.applicationcontext.TypeBasedServiceProviderFromProperties.
defaultPropertyFiles
wt.services.applicationcontext.TypeBasedServiceProviderFromProperties.
customPropertyFiles

130 Customization Guide


See service.properties file on page 49 for information on these properties.
These properties are handled in a special fashion with xconfmanager Utility.
Rather than directly specifying a new property value for any of these properties,
you should instead establish a new declarative XCONF file that causes your new
service provider file to be used. A key benefit to doing this is that it will avoid
conflicts with these property values if you later install other PTC products that
require their own service provider property values. This is illustrated with the
following example.
Suppose your new service provider file name is named codebase/ext/sitepart/
sitepart.properties. It contains the entries that define your new services. In order to
get this property listed as one of the files in the following wt.properties entry:
wt.services.applicationcontext.WTServiceProviderFromProperties.customProp
ertyFiles

You should create a new declarative XCONF file, for example, codebase/ext/
sitepart/sitepart.xconf. It would look like the following:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">
<Configuration targetFile="codebase/wt.properties">
<!-- Ensure that the file ext/sitepart/sitepart.properties is
appended to the list of custom property files.
-->
<Property default="ext/sitepart/sitepart.properties" name="wt.services
applicationcontext.WTServiceProviderFromProperties.customPropertyFiles"/>
</Configuration>

The Property statement (formatted on two lines for this guide) is one line in the
file that declares that the file ext/sitepart/sitepart.properties (a path relative to the
codebase directory) should be added as a value for the property:
wt.services.applicationcontext.WTServiceProviderFromProperties.customProp
ertyFiles

This property is in the codebase/wt.properties file.


Store a copy of new XCONF files in your source directories as described in Best
Practices for Customizing Files Supplied by PTC on page 109.
To install the codebase/ext/sitepart/sitepart.xconf file and generate the sitepart.
properties file, execute the xconfmanager Utility from a windchill shell, as
follows:
xconfmanager -i codebase/ext/sitepart/sitepart.xconf -p

After running the above command, the wt.properties file is updated to reference
your service provider file, codebase/ext/sitepart/sitepart.properties.

Managing Customizations 131


Compiling Custom Classes
The syntax to compile custom java classes to the Windchill codebase is: ant -f
bin/tools.xml class -Dclass.includes=*.java
-Dclass.source=<Windchill>/wtCustom/<custom-
subdirectories>

132 Customization Guide


Modeled To Subtype Conversion
The ModeledToSoftType tool was released with Windchill 9.1 to help
eliminate custom modeled types from your system. The tools does this by
converting the hard type instances into to subtype instances of PTC-supplied
modeled classes. For instance, if you have extended WTDocument to create your
own AcmeDocument that adds a few simple attributes, it may be simpler for
you, in the long run to eliminate the need to maintain a model and generate source
code by converting your AcmeDocument to a subtype based on WTDocument.

Note
Rational Rose was retired as of the Windchill 10.0 release. Modeling
previously done with Rational Rose is now done via Java Annotations that
define the data model. However, this does not change the value of retiring
customization in favor of OOTB solutions.
For more information on Java Annotations see the “Modeling Business
Objects” section of the Windchill Customization Guide.

Note
Some code examples in this document have been reformatted for presentation
purposes and, therefore, may contain line numbers, hidden editing characters
(such as tabs and end-of-line characters) and extraneous spaces. If you cut and
paste code from this document, check for these characters and remove them
before attempting to use the example in your application.

Note
The term “soft type” has been replaced in the product documentation by the
term “subtype.”

Assumptions
• Windchill Servers should be down when running the tool.
• Verify that there are no recyclebin tables ( Oracle 10g and above). To do
this:
○ Log on to your Sqlplus session as schema owner.

Managing Customizations 133


○ From Sqlplus, run: select count(*) from recyclebin;
○ If the count is greater than zero, run the following command: purge
recyclebin;
• When converting a modeled class to a subtype, it must extend a class that
implements the Typed interface, the class implementing Typed has to still be
in the model after all classes have been converted.
• If a modeled class is converted, all of the subclasses must also be converted.
• You have created the reusable attribute definitions and type definitions to
which you want to convert your modeled class instances, and have added
global attributes referencing the reusable attribute definitions on those types
using the Type and Attribute Management utility. You have updated any custom
UI and other customizations to know how to work with the type via subtype
APIs. The tool will not create the reusable attribute definitions, type
definitions, or create global attributes referencing the reusable attribute
definitions on the types, nor will it do anything to help eliminate
customizations.
• No policies and rules of the following types for the new target subtype can be
present in the system prior to running the tool. The tool will update the type
selector columns to change the references from the modeled class to the new
target subtype.
○ AccessPolicyRule
○ FvPolicyItem
○ FvPolicyRule
○ IndexPolicyRule
○ NotificationRule
• The tool deletes records from the following tables that have selectors
referencing the modeled class that's being converted to a subtype:
○ IndexPolicyList
○ NotificationList
○ PolicyAcl

134 Customization Guide


Restrictions

Note
• Currently the tool is only supported for Oracle. If the tool needs to be
supported for SQL Server, an enhancement request must be created with
PTC.
• Currently the tool can only convert modeled attributes to global attributes.
It cannot convert modeled attributes to standard attributes. To support
standard attributes an enhancement request must be created with PTC.

The tool preserves the following attribute data types that have been modeled on
the classes being converted to modeled subtypes. Any other attribute data type
cannot be converted; therefore, you must decide if they are to be either discarded
or changed in the way it is represented prior to converting to a subtype.
• Boolean
• Double
• Integer
• String
• Date and Time
The tool does not attempt to preserve ObjectMappables in any way.
Typically, an ObjectMappable class defines several attributes that should
remain together (for example, a WTReference is a class name and a numeric
ID).
If you are converting a class that used an ObjectMappable property to add
multiple columns, you are responsible for specifying what to do with each distinct
column.

Managing Customizations 135


Converting a Class
When a modeled class is converted to a subtype the tool does the following things:
1. Copies fields that the class has in common with its parent, from columns on
the modeled subclass table to the parent class table
2. When table data for the converted hard type classes is copied into the table of
the subtype's parent Typed class, the typedefintitionreference is set
to this latest WTTypeDefinition iteration.
3. For fields that were modeled on the subclass, creates global attribute values
for each instance, associates them with the type instance in the parent class
table and the reusable attribute definition:
• You are expected to specify the mapping for each modeled field to each
reusable attribute definition.
• You can opt to discard fields that are not used or which have no correlating
representation in the subtype model.
4. All "surface level" references (columns for WTReference
ObjectMappables which have a String classname column) in the
database are updated to replace references to the modeled classname that is
being removed with the concrete classname of the subtype it is being
converted to
5. All type definition based Selector columns containing external type definition
references in the database are updated to replace the modeled classname
with the external type definition string of the subtype it is being converted
to (this updates objects, such as access policies and notification rules).
6. A regular expression mapping is installed in the site.xconf file that tells
the Java code-based object reference factories to convert occurrences of the
classname that is being removed into the concrete classname of the
subtype it is being converted to when handling object references found in
BLOBs or outside the system (for example, in browser bookmarks).
7. The classname being removed is removed from the various registry
properties files in the <Windchill>/codebase directory (for example,
classRegistry.properties, modelRegistry.properties,

136 Customization Guide


associationRegistry.properties,
descendantRegistry.properties, and so on).

Note
If you encounter issues after you start the method server (ie:
ClassNotFoundException) please see the “Perform the Necessary
Cleaning” section in the examples below.

8. The .class file for the modeled class and its inner classes, as well as the
.ClassInfo.ser file, are removed from codebase along with any JAR
files in <Windchill>/srclib, <Windchill/lib, <Windchill>/
codebase/WEB-INF/lib.
9. The client JARs downloaded by client applets are rebuilt
10. The Background Blob Rewriter process is scheduled to be restarted to find and
fix references to the removed classname that may be inside BLOBed
objects
11. The classes being removed by the tool must also be manually removed from
the model and the model must be regenerated.

Note
Semantic Keys including the modeled class are not presently rebuilt.

Managing Customizations 137


Using the Tool
The tool is run by executing ModeledToSoftType (.sh or .bat) which can be
found in the <Windchill>/bin directory.

Usage
ModeledToSoftType [-help] [-debug|-trace] [ [-skipdb]
[-skipdm] [-skipfs] | -checkonly ] <MappingFile.xml>
• -debug : Describes in more detail each action being performed.
• -trace : Includes more detail, such as the SQL statements being executed.
• -skipdb : Do not perform any of the work that modifies the database. This
includes:
○ Migrating the data from the custom hard type tables into the type
definition tables associated to the subtype
○ Modifying the necessary tables to replace all references to the custom hard
type class with the corresponding subtype.
• -skipdm : Do not perform any of the work that migrates the data from the
custom hard type tables into the type definition tables associated to the
subtype. Essentially this will not migrate the data from the custom hard type
tables into the type definition tables associated to the subtype. (same as the
first -skipdb option).
• -skipfs : Do not delete any of the custom modeled type artifacts from
Windchill codebase.
• -checkonly : Equivalent to -skipdb and -skipfs. Performs validation
of the mapping file.
The tool outputs to STDOUT. It also appends its output with more details,
including timestamps to a timestamped log file named
ModeledToSoftType.log in the $(wt.logs.dir) directory.

Optional Properties
The following optional properties should be defined in the wt.properties file
in order for it to be used by the ModeledToSoftType tool. The delimiter for
the property values is a comma. For properties whose values are specific columns
of a table, the format is <table_name>.<column name>.
• com.ptc.windchill.modeledtosofttype.nonClassNameTa
bles
If there are some tables that the tool should not be considering while replacing

138 Customization Guide


all references of the hard type class name with the classname of the subtype,
such table names should be added to this property.
• com.ptc.windchill.modeledtosofttype.classNameTable
Columns
The tool by default retrieves all the columns starting with "CLASSNAME"
from all tables of type "TABLE". If there are some custom tables whose
columns need to be updated by this tool, but the column names do not start
with "CLASSNAME" OR if there are other types of tables whose columns need
to be considered, such tables and its corresponding columns need to be added
to this property.
• com.ptc.windchill.modeledtosofttype.nonClassNameTa
bleColumns
If there are some columns in a specific table that should not be considering by
the tool even though the column name starts with "CLASSNAME", then such
columns should be added to this property.
• com.ptc.windchill.modeledtosofttype.nonTypeIdTables
When the tool is replacing the references to the hard type class name with the
type references of the subtype, by default it only updates the type selector
columns of the five tables listed in the Assumptions section above. If there are
some tables that the tool should not be considering while performing this
replacement, such table names should be added to this property
• com.ptc.windchill.modeledtosofttype.typeIdTableCol
umns
When the tool is replacing the references to the hard type class name with the
type references of the subtype, by default it only updates the type selector
columns of the five tables listed in the Assumptions section. If such columns
exist in custom tables that is not automatically identified by the tool, then
these columns should be added to this property.
To identify such column for a specific concrete class, one can run an
inforeport against the fully qualified class name and look for column
names whose property descriptor is
wt.access.AccessSelector.typeId. For example below is the
relevant information from the inforeport for the AccessPolicyRule
class.
getName() : selector.typeId
getColumnName() : classNameA5
getJavaType() : java.lang.String
getSQLType() : java.sql.Types.VARCHAR
getLength() : 220

Managing Customizations 139


getTableSpaceName() : null
getTableSize() : SMALL
isRequired() : false
isIndexed() : false
isUnique() : false
isUpdatable() : true
getPropertyDescriptor(): wt.access.AccessSelector.typeId.

• com.ptc.windchill.modeledtosofttype.nonTypeIdTable
Columns
If there are some type selector columns in a specific table that should not be
considering by the tool while replacing references to the hard type class name
with the type references of the subtype, then such columns should be added to
this property.

140 Customization Guide


Mapping File
The mapping file is an XML file that looks like the following:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1" attributeDefinitionName=
"com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2" attributeDefinitionName=
"com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3" attributeDefinitionName=
"com.acme.Attr3"/> <!-- long -->
<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[] blobbed up -->
</Convert>
</Mappings>

Note
This is the mapping file for Case 1 as documented below.

Important Mapping File Attributes


• Target Subtype (softTypeLogicalIdentifier attribute from the
Convert XML element)
For each class being converted, a subtype definition must be specified using
the attribute softTypeLogicalIdentifier on the element Convert.

Managing Customizations 141


The value assigned to the softTypeLogicalIdentifier attribute
should be the internal name of the subtype as shown below.

Note
As is mentioned earlier in the “Assumptions” section, the subtype
definition must have already been created by you. The
ModeledToSoftType tool does not create type definitions or attribute
definitions.

• Target Subtype Attributes (attributeDefinitionName attribute from


the MapColumnToSoftAttribute XML element)
The attributeDefinitionName attribute in the mapping file for each
attribute, corresponds to the name of the reusable attribute definition you
created in the Manage Reusable Attributes window of the Type and Attribute
Management utility. Based on the screen shot below, the

142 Customization Guide


attributeDefinitionName would be
com.ptc.ptcnet.MySoftAttribute.

This attribute value is used to locate the latest iteration of


WTTypeDefinition appropriate attribute definitions (that is not deleted
and) in the various AttributeDefinition tables listed below.
○ BooleanDefinition
○ FloatDefinition
○ IntegerDefinition
○ StringDefinition
○ TimestampDefinition
While creating a new reusable attribute definition, although the Logical
Identifier field is not mandatory, it is recommended to enter a value in this
field. It is also recommended that the value assigned to the Logical Identifier
field matches the Internal Name field of the attribute unless there is a good
reason to keep them separate in which case its OK for the names to be
separate.
• Column Query Names (columnQueryName attribute from the
MapColumnToSoftAttribute XML element)

Managing Customizations 143


A column query name is a logical ID that uniquely identifies the column but
might not actually match the generated column name. This can happen for a
variety of reasons. To figure out the query name for a column, run
InfoReport on your class. For example: InfoReport
wt.doc.WTDocument
This generates a text file in $(wt.temp) named something like
doc.WTDocument.out.
Open it, then scroll down to the section that starts with
getBaseTableInfo().getColumnDescriptors() :
Under that, you will see information about column descriptors similar to these:
getName() : checkoutInfo.derivedFrom.key.id
getColumnName() : idA3A2checkoutInfo
getJavaType() : long
getSQLType() : java.sql.Types.BIGINT
getLength() : 0
getTableSpaceName() : null
getTableSize() : SMALL

The text to the right of getName() is the query name. The actual column
name in the database is on the line right below.

144 Customization Guide


Example Mapping Files
The following are example mapping files corresponding to different use cases for
which this tool can be employed.

Case 1 - Converting a Modeled TestDoc to SoftType

In this example, you have a TestDoc class that you want to make subtypes of
WTDocument.
package ext.cust.doc;
class TestDoc extends wt.doc.WTDocument {
String attr1;
boolean attr2;
long attr3;
Object signatureImage; // treated as an Image
}

The mapping file for converting TestDoc to the subtype


com.acme.MySoftDoc looks like:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=

Managing Customizations 145


"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1" attributeDefinitionName=
"com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2" attributeDefinitionName=
"com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3" attributeDefinitionName=
"com.acme.Attr3"/> <!-- long -->
<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[] blobbed up -->
</Convert>
</Mappings>

For the TestDoc class, use the Type and Attribute Management utility before
running the tool to define a reusable attribute, and add a global attribute
referencing the reusable attribute definition for the first three columns that were
modeled on the class. For each reusable attribute, specify the column query name
and the name of the reusable attribute definition in the mapping file. For the fourth
attribute in the TestDoc class, signatureImage, there is no corresponding
reusable attribute data type that the mapping tool supports, so the column is
simply discarded.

146 Customization Guide


Case 2 - Converting a Class that has a Persisted Link to Some Other
Class

The Modeled TestDoc is associated to SomeData via the persisted DocData


link. In order to collapse data from SomeData onto WTDocument when
TestDoc is converted, add the following to your mapping file:
<MapColumnToSoftAttribute columnQueryName="some.link.Class|id_of_convert_role
|data.from.Class|id_of_from_role|data" attributeDefinitionName="soft.Attribute"/>

Where:
• some.link.Class is wt.doc.testdoc.DocData
• id_of_convert_role is IDA3A5 (id portion of the role A reference
from ext.cust.doc.DocData)
• data.from.Class is wt.doc.testdoc.SomeData
• id_of_from_role is IDA3B5 (id portion of the role B reference from
ext.cust.doc.DocData)
• data is data1, data2, data3, etc.

Managing Customizations 147


Note
To get the id roles, you can execute the InfoReport command on
DocData. Search for roleAObjectRef.key.id and
roleBObjectRef.key.id. The column names specified under those IDs
are your id roles.

The mapping file for this example should be similar to the following example:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1"
attributeDefinitionName="com.acme.Attr1"/>
<!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2"
attributeDefinitionName="com.acme.Attr2"/>
<!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3"
attributeDefinitionName="com.acme.Attr3"/>
<!-- long -->
<DiscardColumn columnQueryName="signatureImage"/>
<!-- byte[] blobbed up -->
<MapColumnToSoftAttribute
columnQueryName="ext.cust.doc.DocData|IDA3A5|
ext.cust.doc.testdoc.SomeData|IDA3B5|
data1" attributeDefinitionName="com.acme.D1"/>
<!-- String -->
<MapColumnToSoftAttribute
columnQueryName="ext.cust.doc.DocData|IDA3A5|
ext.cust.doc.testdoc.SomeData|IDA3B5|
data2" attributeDefinitionName="com.acme.D2"/>
<!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="ext.cust.doc.DocData|IDA3A5|
ext.cust.doc.testdoc.SomeData|
IDA3B5|data3" attributeDefinitionName="com.acme.D3"/>
<!-- int -->
</Convert>
</Mappings>
Perform the Necessary Cleaning
After converting the TestDoc class, the persisted ObjectToObjectLink
DocData becomes obsolete because one of the classes it references no longer
exists. In this case, ensure that it is removed from the model and from the
codebase and JAR files, as well.

148 Customization Guide


1. First DocData must be removed from the *Registry.properties files
in <Windchill>/codebase. You can find these using grep (if available)
or a similar search mechanism.
grep -w DocData *Registry.properties associationRegistry.properties:
ext.cust.doc.SomeData=ext.cust.doc.DocData associationRegistry.properties:
ext.cust.doc.TestDoc=ext.cust.doc.DocData classRegistry.properties:
DocData=ext.cust.doc descendentRegistry.properties:
wt.fc.ObjectToObjectLink=ext.cust.doc.DocData
modelRegistry.properties:ext.cust.doc=DocData

2. Remove DocData.class and DocData.ClassInfo.ser from


<Windchill>/codebase/ext/cust/doc.
3. If DocData.class is in <Windchill>/codebase/ext/cust/doc
within wnc.jar, or any other jars, you need to remove it from those as well.

Note
The Method Server will not function if you do not follow the above steps.

Managing Customizations 149


Case 3 - Converting a Class that has a ForeignKey Association to
Some Other Class

In this case, TestDoc is also associated to MoreData via a ForeignKey


association. In order to collapse data from MoreData onto WTDocument when
TestDoc is converted, add the following to your mapping file:
<MapColumnToSoftAttribute columnQueryName="ForeignKey|null|
foreign.key.Class|id_of_foreign_key_data|data"
attributeDefinitionName="soft.Attribute"/>

Where:
• ForeignKey is a constant representing that you are collapsing via a
ForeignKey association.
• id_of_convert_role : null is always null for ForeignKey
associations
• foreign.key.Class is wt.doc.testdoc.MoreData*

150 Customization Guide


• id_of_foreign_key_data is moreDataReference.key.id. The
id portion of the ForeignKey reference from
wt.doc.testdoc.TestDoc
• data is md1, md2, md3, etc.
The mapping file should be similar to the following example:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1" attributeDefinitionName=
"com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2" attributeDefinitionName=
"com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3" attributeDefinitionName=
"com.acme.Attr3"/> <!-- long -->
<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[] blobbed up -->

<DiscardColumn columnQueryName="moreDataReference.key.classname"/>
<DiscardColumn columnQueryName="moreDataReference.key.id"/>

<MapColumnToSoftAttribute columnQueryName="ForeignKey|null|ext.cust.doc.MoreData|
moreDataReference.key.id|md1" attributeDefinitionName=
"com.acme.M1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="ForeignKey|null|ext.cust.doc.MoreData|
moreDataReference.key.id|md2" attributeDefinitionName=
"com.acme.M2"/> <!-- int -->
<MapColumnToSoftAttribute columnQueryName="ForeignKey|null|ext.cust.doc.MoreData|
moreDataReference.key.id|md3" attributeDefinitionName=
"com.acme.M3"/> <!-- boolean -->

</Convert>
</Mappings>

(moreDataReference.key.classname,
moreDataReference.key.id) is a objectMappable created under
TestDoc to represent ForeignKey Association to MoreData.
In this example, these fields are discarded because you are collapsing MoreData
information into WTDocument, so you do not need reference information. If you
decide to preserve the reference, you need to map the classname and id
columns to global attributes as explained in Case 1.
Perform the Necessary Cleaning
Once you have converted the TestDoc class, the non-persisted DocMoreData
link class is obsolete (this one represents the ForeignKey relationship between
TestDoc and MoreData) and must be completely removed.

Managing Customizations 151


1. First DocMoreData must be removed from the
*Registry.properties files in <Windchill>/codebase. You can
find these using grep (if available) or a similar search mechanism.
grep -w DocMoreData *Registry.properties
associationRegistry.properties:
ext.cust.doc.MoreData=ext.cust.doc.DocMoreData
associationRegistry.properties:
ext.cust.doc.TestDoc=ext.cust.doc.DocMoreData
classRegistry.properties:
DocMoreData=ext.cust.doc
descendentRegistry.properties:wt.fc.ForeignKeyLink
=ext.cust.doc.DocMoreData
modelRegistry.properties:ext.cust.doc=DocMoreData
2. Remove DocMoreData.class and DocMoreData.ClassInfo.ser
from <Windchill>/codebase/ext/cust/doc.
3. If DocMoreData.class is in <Windchill>/codebase/ext/cust/
doc within wnc.jar, remove that as well.

Note
The Method Server will not function if you do not follow the above steps.

152 Customization Guide


Case 4 - Converting a Class that has a Reverse ForeignKey
Association to Some Other Class

This UML shows what appears to be a correctly modeled ForeignKey


association from TestDoc to RetentionData, but it is actually reversed. The
ForeignKey is on RetentionData instead of on TestDoc where you
would expect it to be based on the UML.
Here are the RoleA/RoleB details:

Managing Customizations 153


Note
This is the incorrect way of modeling a foreign key association but this case is
handled in the ModeledToSoftType tool using ReverseForeignKey
attribute in the mapping file.

To collapse attributes from RetentionData onto TestDoc as it is converted


you need to add the following to your mapping file:
<MapColumnToSoftAttribute columnQueryName="ReverseForeignKey|null|
other_side_class|this_side_reference|attribute_to_convert"
attributeDefinitionName="soft_attribute"/>

Where:
• other_side_class is the class the data is coming from when conversion
happens, in our case ext.cust.doc.RetentionData
• this_side_reference is the identifier of the column from the other_
side_class that points back at the instance of the class being converted.
Here it is the TestDocReference.key.id
• attribute_to_convert is the attribute from the other_side_class
you are collapsing during conversion, in this case, rd1 and rd2
• soft_attribute is the name of the reusable attribute which a global
attribute on the subtype references, that the data is copied into during

154 Customization Guide


conversion. For example
localdomain.localhost.RetentionData1 and
localdomain.localhost.RetentionData2
The mapping file for this example should be similar to the following example:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1" attributeDefinitionName=
"com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2" attributeDefinitionName=
"com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3" attributeDefinitionName=
"com.acme.Attr3"/> <!-- long -->

<MapColumnToSoftAttribute columnQueryName="ReverseForeignKey|null|
ext.cust.doc.RetentionData|theTestDocReference.key.id|
rd1"attributeDefinitionName="com.acme.RetentionData1"/>
<MapColumnToSoftAttribute columnQueryName="ReverseForeignKey|null|
ext.cust.doc.RetentionData|theTestDocReference.key.id|
rd2"attributeDefinitionName="com.acme.RetentionData2"/>
</Convert>
</Mappings>

Perform the Necessary Cleaning


Once you have converted the TestDoc class, the non-persisted
TheTestDocRetentionData link class is obsolete (this one represents the
ForeignKey relationship between RetentionData.java and TestDoc).
This one also needs to be removed completely.
1. First TestDocRetentionData must be removed from the
*Registry.properties files in <Windchill>/codebase. You can
find these using grep (if available) or a similar search mechanism.
grep -w TestDocRetentionData *Registry.properties
associationRegistry.properties:ext.cust.doc.RetentionData=
ext.cust.doc.TheTestDocRetentionData
associationRegistry.properties:ext.cust.doc.testdoc.TestDoc=
ext.cust.doc.TheTestDocRetentionData classRegistry.properties:
TheTestDocRetentionData=ext.cust.doc descendentRegistry.properties:
wt.fc.ForeignKeyLink=ext.cust.doc.TheTestDocRetentionData
modelRegistry.properties:ext.cust.doc=TheTestDocRetentionData
2. Remove TheTestDocRetentionData.class and
TheTestDocRetentionData.ClassInfo.ser from
<Windchill>/codebase/ext/cust/doc.
3. If TheTestDocRetentionData.class is in <Windchill>/
codebase/ext/cust/doc within wnc.jar, remove that as well.

Managing Customizations 155


Note
The Method Server will not function if you do not follow the above steps.

156 Customization Guide


Case 5 - Converting a Class with EnumeratedType Attribute

You need to add the following element to the mapping file:


<MapColumnToSoftAttribute columnQueryName="EnumeratedType|ext.cust.doc.TDEnum|tdEnum"
attributeDefinitionName="com.acme.TestET1"/>

Where:
• EnumeratedType is a constant representing the type of mapping.
• ext.cust.doc.TDEnum is the name of the EnumeratedType class for
the attribute being converted.
• tdEnum is the attribute name from the class being converted of the
EnumeratedType.
• com.acme.TestET1 is the global attribute into which the
EnumeratedType value is being mapped.
When an EnumeratedType value is mapped like this, the
ModeledToSoftType tool will use the key value stored in the database to look
up the actual value from the rbInfo, and then will store the value from the
rbInfo in the specified global attribute.

Managing Customizations 157


If you decide to just store the EnumeratedType key from the database to the
specified global attribute , you can consider that to be normal attribute and add the
following to the mapping file:
<MapColumnToSoftAttribute columnQueryName="tdEnum"
attributeDefinitionName="com.acme.TestET1"/> <br>

The mapping file used to store values will look like this example:
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1" attributeDefinitionName=
"com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2" attributeDefinitionName=
"com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3" attributeDefinitionName=
"com.acme.Attr3"/> <!-- long -->

<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[] blobbed up -->


<MapColumnToSoftAttribute columnQueryName="EnumeratedType|ext.cust.doc.TDEnum|
tdEnum" attributeDefinitionName="com.acme.TestET1"/>
</Convert>
</Mappings>

The mapping file used to store keys will look like this example::
<Mappings>
<Convert class="ext.cust.doc.TestDoc" softTypeLogicalIdentifier=
"com.acme.MySoftDoc">
<MapColumnToSoftAttribute columnQueryName="attr1"
attributeDefinitionName="com.acme.Attr1"/> <!-- String -->
<MapColumnToSoftAttribute columnQueryName="attr2"
attributeDefinitionName="com.acme.Attr2"/> <!-- boolean -->
<MapColumnToSoftAttribute columnQueryName="attr3"
attributeDefinitionName="com.acme.Attr3"/> <!-- long -->

<DiscardColumn columnQueryName="signatureImage"/> <!-- byte[] blobbed up -->


<MapColumnToSoftAttribute columnQueryName="tdEnum"
attributeDefinitionName="com.acme.TestET1"/>

</Convert>
</Mappings>

158 Customization Guide


Case 6 - Converting a Customized Model Class to PTC Supplied
Model Class (Hard Type to Hard Type conversion)

The mapping file for this example should be similar to the following example:
<Mappings>
<Convert class="ext.com.hardtype.TestActivityData" convertToHardType="true">
<DiscardColumn columnQueryName="testAtr1"/>
</Mappings>
</Convert>

Note
Unlike other the cases documented above this is not applicable for classes that
implement Typed interface. If you try, the tool will fail with the following
error message: The class 'ext.com.hardtype.TestHardType' is
configured to be converted to IBAs on wt.doc.WTDocument
but wt.doc.WTDocument implements wt.type.Typed. This
will not work.

Managing Customizations 159


Monitoring a Customized Windchill
Environment
You can use the System Monitor to monitor and troubleshoot your customized
Windchill environment. Depending on where the custom code is, you may be able
to use the System Monitor without any modifications to collect information from
your custom code. If the out-of-the-box configuration does not collect all of the
information you would like to see, you can add sensors to key custom classes to
collect the data.

Note
Be careful when adding sensors as they can have an impact on performance.
Consequently, you should ensure that you have performance measures that
you can reliably use to verify performance before and after adding sensors.
Additionally, validate all changes made to the System Monitor System Profile
against your development environment before deploying the changes into your
production environment.

For more information about the System Monitor, see the videos and
documentation available from http://www.ptc.com/go/psm.

160 Customization Guide


Customization with Windchill Queues
Windchill queues provide a means of scheduling lower priority work which can be
run in the background. Many of the OOTB Windchill services create and use
queues for lower priority work activities. These capabilities are available to user
customizations also.
As part of ongoing efforts to make Windchill more secure and robust access
control checks have been added to all public queue APIs. What this means for all
future customizations (that use queues) is that all calls to the Queue Service must
first either set Administrator, or bypass access control. Failure to do so will result
in a not authorized exception being thrown.

Sample Code
The following code pattern should be followed when setting Administrator:
SessionContext previous = SessionContext.newSessionContext();
try {
SessionHelper.manager.setAdministrator();
// make calls to Queue Service
}
finally {
SessionContext.setContext(previous);
}
The following code pattern should be followed when bypassing access control:
boolean previous = SessionServerHelper.manager.setAccessEnforce(false);
try {
// make calls to Queue Service
}
finally {
SessionServerHelper.manager.setAccessEnforce(previous);
}

Managing Customizations 161


7
Windchill Utilities
Using the xconfmanager Utility ................................................................................. 164
Formatting Property Value Guidelines ....................................................................... 176
Windchill Command................................................................................................. 177
Windchill Shell ........................................................................................................ 180

This section contains information on various Windchill utilities.

163
Using the xconfmanager Utility
The xconfmanager is a command line utility that you can run to add, remove, or
modify properties in Windchill property files that are used for your defining your
system.
Windchill uses some property files to manage internal system activities that you
should never modify, including the following:
• associationRegistry.properties
• descendentRegistry.properties
• modelRegistry.properties
• moduleRegistry.properties
• moduleDir.properties
• debug.properties
The xconfmanager utility saves your changes in the site.xconf file and provides an
option to generate updated property files using the updates in the site.xconf file.
The site.xconf file contains the changes made to Windchill property files starting
with the installation and continuing with each use of the xconfmanager utility. The
site.xconf file is located in the directory where Windchill is installed.
Anyone with write access to the XCONF and property files under the Windchill
installation directory can successfully run the xconfmanager utility.
The following sections describe how to enter the xconfmanager command and
how to set property values and list property information using the command. The
last section describes the other xconfmanager options that may be useful when
running your Windchill solution.
The xconfmanager utility is located in the bin directory where your Windchill
solution is installed. For example, if Windchill solution is installed in the C:\
ptc\Windchill directory, then the utility is in the C:\ptc\Windchill\
bin directory.
Before executing the xconfmanager command, set up your environment by
using the windchill shell. To use the shell, either execute the shortcut (on a
Windows system) or enter the following on the command line:
windchill shell

Then from the new window that opens, you can enter the xconfmanager
command, as described in the next section.

164 Customization Guide


xconfmanager Command Syntax
The syntax of xconfmanager command that administrators should use is as
follows:
xconfmanager {-fFhuwvV} {-r <product_root>} {-d <property_names>} {-s
<property_pair>} {-t <property_file>} {--add <property_pair>} {--remove
<property_pair>} {--reset <property_names>} {--setfromfile <property_file>}
{--undefine <property_names>} {-i <declarative_xconf>} {--validateassite
<site_xconf>} {--validateasdecl <declarative_xconf>} {--validatefilesassite
<site_list_file>} {--validatefilesasdecl <declar_list_file>} {-p}

The brackets ({}) in the syntax indicate optional parameters and indicate
parameters that you specify together. The syntax includes only the short version of
each parameter name. Parameter names are case-sensitive; enter the names using
the case shown in the syntax and the following table.
The following variables are used in the syntax of multiple parameters:
• <property_pair> is a command-line escaped name=value pair that is
compatible with the specification for java.util.Properties. For an example, see
Setting Property Values and Propagating Your Changes on page 170.
• <property_names> is a comma-separated list of property names.
• <property_file> is the relative or full path name of the property file.
• <declarative_xconf> is either a full URL or relative file path to the declarative
XCONF file.
In the following table, all parameter names are listed in alphabetical order with
corresponding parameter descriptions:
Parameter Name Description
--add Add the specified value at the end of the set of ordered
values already defined in the property. Use this
parameter only when the property is declared as a
multi-valued property.
To determine if property is multi-valued, you can
display the current set of values using the -d parameter.
The output from this parameter lists the multivalue
separator when the property is multi-valued.
-d Lists the values that are currently set and the
corresponding XCONF file where each value is set for
or
the specified properties.
--describe
This parameter executes after all parameter setting
options and the -p option have executed.
-F Forces the propagator to ignore its cache of XCONF-
to-properties file dependencies and ignore the

Windchill Utilities 165


Parameter Name Description
or timestamp comparison it usually does to determine
which property files need to be updated. Using this
--force
option propagates all site-specific changes to property
files.
Use this parameter in place of -p if you suspect that
there are problems with file timestamps or you want to
switch between the -w and -u options.
-f Forces the propagator to ignore its cache of XCONF-
to-properties file dependencies. This parameter is
or
ignored if you specify -F.
--forcescan
Use this option in place of -p if you suspect that the
cache is out of date.
-h Displays the help for the xconfmanager command.
or
--help

-i Installs a declarative XCONF file that you have


created. New declarative XCONF files are used when
or
creating additional property files. When you are adding
--install code in which new properties can be set, you can
choose to create a separate property file where the
properties are stored. For details on what to put in the
declarative XCONF file, see Using XCONF Files on
page 112.
-p Propagates all changes that have been made to XCONF
files into the property files that are being used. This
or
option always executes after any options that set
--propagate properties. This execution order ensures that the newly
set properties are included in the propagation.
Updated property files are accessed when the Windchill
solution is restarted.
-r The root directory from which all relative paths are
based for XCONF references specified in the
or
declarations.xconf file and target file paths
--productroot specified in the -t parameter.
The default root directory is the bin directory where the
Windchill solution is installed.
--remove Removes the specified value that is in the set of
ordered values defined in the property. Use this option
only when the property is declared as a multi-valued

166 Customization Guide


Parameter Name Description
property.
To determine if a property is multi-valued, you can
display the current set of values using the -d parameter.
The output from this parameter lists the multivalue
separator when the property is multi-valued.
--reset Resets the site specific value of a property or set of
properties to the declared default values.
-s Sets the named property to a specific value in the site.
xconf file.
or
To set multiple properties in the same target property
--set
file, use multiple occurrences of this parameter or use
the following parameter:
--setfromfile

To set multiple properties that are in different target


property files, enter multiple xconfmanager commands,
one for each target file.
Use this parameter in conjunction with the -t parameter.
--setfromfile Adds the name=value pairs that are in the specified file
to the end of the site.xconf file, thus setting each
property named to the specified value. There is no
checking done to determine if the value set is the
default.
<property_file> is the file that contains a set of name=
value pairs (one pair per line) that indicate the
properties and values you want set in one target
property file. Each pair sets a value for one property.
With this parameter, you can set multiple properties in
the same target property file using one
xconfmanager command. To set properties that are
in different target property files, enter multiple
xconfmanager commands, one for each target file.
Use this parameter in conjunction with the -t parameter.
-t Identifies the property file in which the property value
specified in the -s parameter is set or the property
or
values specified in the following parameter are set:
--targetfile --setfromfile

Windchill Utilities 167


Parameter Name Description
Use this parameter in conjunction with either the -s or
the following parameter:
--setfromfile

This parameter is optional when setting common


properties where the default property file to update has
been declared and is available to the xconfmanager
utility. For example, properties stored in wt.properties
and db.properties do not require this parameter.
For other properties, you may need to specify the file
path of the property file in this parameter. For example,
updating properties in the federation.properties file
requires that you enter this parameter using the
codebase/federation.properties file path.
-u|w Indicates the platform for which the property files are
to be generated. Normally, the current platform settings
or
determine the format of the property files.
--unix|win
Include this parameter when you want to generate
property files for a specific platform that is not the
current platform.
For UNIX platforms, specify -u or the following:
--unix

For Windows platforms, specify -w or the following:


--win
--undefine Resets the specified properties such that their values
will be null (instead of an empty string) when read
through a java.util.Properties instance.
-v Turns on verbose console output, which shows full
exception stack traces.
-V Turns on debug verbose console output. This option
shows full exception stack traces and additional
information.
--validateasdecl Validates a specific file as a declarative XCONF file.
Returns a non-zero result if file cannot be validated.
--validatefilesasdecl Validates a list of files as declarative XCONF files. The
list is contained in the specified file, where each line in
the file is either a full URL or relative file path to a
declarative XCONF file.

168 Customization Guide


Parameter Name Description
Returns a non-zero result if any of the files cannot be
validated.
<declar_list_file> is either a full URL or relative file
path to the file containing the list of declarative
XCONF files you want to validate.
--validatefilesassite Validates a list of files as site-specific XCONF files.
The list is contained in the specified file, where each
line in the file is either a full URL or relative file path
to a site-specific XCONF file.
Returns a non-zero result if any of the files cannot be
validated.
<site_list_file> is either a full URL or relative file path
to the file containing the list of site-specific XCONF
files you want to validate.
--validateassite Validates a specific file as a site-specific XCONF file.
Returns a non-zero result if file cannot be validated.
<site_xconf> is either a full URL or relative file path
to the site-specific XCONF file you want to validate.

Note
The xconfmanager executes the following parameters in the order that they are
specified in the command:
-s, --reset, --add, --remove, --undefine

This means that if the same property is set in multiple parameters, the last
setting is used.

The xconfmanager always executes the -p parameter after executing the


previously listed parameters for setting, resetting, adding, removing, and
undefining values. This is done so that all parameter settings are included in the
propagation.
Additionally, the xconfmanager always executes the -d parameter after executing
the previously listed parameters. This is done so that the descriptions returned
include all of the parameter settings made on the command.

Windchill Utilities 169


Viewing xconfmanager Help
On the xconfmanager command, use -h or the following parameter:
--help

to list the xconfmanager command syntax and provide a description of each


parameter.

Setting Property Values and Propagating Your


Changes
The xconfmanager utility provides options that allow you to manage the
properties in a Windchill property file as follows. You can:
• Set a property value to specific value by using the -s and -t parameters.
• Set a property value to the declared default value by using the following
parameter:
--reset
• Set a property value to null (instead of an empty string) using the following
parameter:
--undefine
• Add and remove property values from properties that are multi-valued using
the following parameters:
--add
--remove
• Propagate the site changes stored in the site.xconf file to all affected property
files using the -p parameter.
Since property values are cached, propagated values are not used until you
restart Windchill and your servlet engine.

Setting Specific Property Values


On the xconfmanager command, use the -s parameter to set a specific property
value and the -t parameter to set the target property file for the property setting. In
a given xconfmanager command, you can specify multiple -s parameters.
However, all properties specified must reside in the same target property file;
there can only be one -t parameter.

170 Customization Guide


The property values you set must conform with the specification for java.util.
Properties. The following guidelines will help ensure that you set properties
correctly:
• Use forward slashes (/) in file paths so that the platform designation is not an
issue.
• To specify a property whose value contains characters that might be
interpreted by your shell, escape them using the appropriate technique for the
shell you are using.
• When setting passwords, specify the password in plain text and the
xconfmanager utility encrypts the password as described in the Windchill
Administration - Configuring Your Windchill Environment guide.
For example, on a Windows system you can include spaces in a value by
enclosing the argument with doubles quotes. For example, use the following:
-s wt.inf.container.SiteOrganization.name="ACME Corporation"

On a UNIX system, you can use doubles quotes or you can escape the space
character with a backslash. For example, use the following:
-s wt.inf.container.SiteOrganization.name="ACME\ Corporation"

On UNIX, dollar signs are usually interpreted by shells as variable prefixes. To set
a property value that has a dollar symbol in it, use single quotes around the
argument so that it is not interpreted by the shell or use backslash to escape the
dollar symbols. For example, use either of the following:
-s 'wt.homepage.jsp=$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp'

or
-s wt.homepage.jsp=\$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp

Other than escaping arguments so that the command line shell does not
misinterpret them, the values should not need to be escaped any further to be
compatible with XML or property file syntaxes. The xconfmanager escapes
property names and values automatically if necessary.
The following xconfmanager command used on a Windows system sets the wt.
properties property file wt.temp property to the WCtemp directory that is under
the Windchill installation directory [as defined by $(wt.home)]:
xconfmanager -s wt.temp=$(wt.home)/WCtemp -t wt.properties -p
Assuming that the command was executed from the Windows C:\ptc\
Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\..

java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar"


-r "C:\ptc\Windchill\bin\.." -s wt.temp=$(wt.home)/WCtemp
-t wt.properties -p

Propagating xconf data to target files...

Windchill Utilities 171


The xconfmanager creates a backup of the current site.xconf file, adds the
property element for wt.temp to the site.xconf file (replacing any existing property
setting that had been in the site.xconf file), and then propagates the change to wt.
properties. Since property values are cached, the propagated values are not used
until you restart Windchill and your servlet engine.

Restoring a Property Value to Its Default Value


Use the –reset parameter on the xconfmanager command to restore one or more
properties to their default values. To specify multiple properties in the parameter,
separate the properties using a comma.
The following xconfmanager command resets the wt.temp property:
xconfmanager --reset wt.temp -p
Assuming that the command was executed from the Windows C:\ptc\
Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\..

java -jar
"C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar"
-r "C:\ptc\Windchill\bin\.." --reset wt.temp -p

Propagating xconf data to target files...


The xconfmanager creates a backup of the current site.xconf file, removes any
existing property settings for the specified properties that had been in the site.
xconf file, adds a ResetProperty element for each property that was specified
(in this case, only wt.temp), and then propagates the change to property files that
have the specified properties (in this case, only wt.properties).

Setting a Property Value to the Null Value


Use the following parameter on the xconfmanager command to set one or
more properties to null values:
--undefine

To specify multiple properties in the parameter, separate the properties using a


comma.
The following xconfmanager command sets the wt.services.service.1160
property to null (which disables the service):
xconfmanager --undefine wt.services.service.1160 -p

Assuming that the command was executed from the Windows C:\ptc\
Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\..

java -jar
"C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar"

172 Customization Guide


-r "C:\ptc\Windchill\bin\.." --undefine
wt.services.service.1160 -p

Propagating xconf data to target files...


The xconfmanager creates a backup of the current site.xconf file, removes any
existing property settings for the specified properties that had been in the site.
xconf file, adds an UndefineProperty element for each property that was
specified (in this case, only wt.services.service.1160), and then propagates the
change to property files that have the specified properties (in this case, only wt.
properties).

Adding and Removing a Property Value to a Multi-valued


Property
To add a new classpath entry (d:\MyLibaries\somelibrary.jar) to the
Windchill end of the classpath specified in the wt.java.classpath property, execute
the following command from the windchill shell:
xconfmanager --add wt.java.classpath=d:\MyLibaries\somelibrary.jar -p

The value d:\MyLibaries\somelibrary.jar is added to the end of the


ordered set. You do not have to specify the delimiter $(path.sep) as this will be
added to the property value automatically by the xconfmanager.
To remove the classpath entry added in the previous example from the wt.java.
classpath property, execute the following command from the windchill shell:
xconfmanager --remove wt.java.classpath=d:\MyLibaries\somelibrary.jar -p
The value d:\MyLibaries\somelibrary.jar is removed.

Tip
The previous example commands do not include the target file (in the -t
parameter). The target file is not needed when the property is known to be in
only one existing property file.

Listing Property Information


Use the -d parameter on the xconfmanager command to list information about one
or more properties. To specify multiple properties in the parameter, separate the
properties using a comma. The resulting output includes the current value of each
property and the location of the files where each property is set.
The following xconfmanager command lists the information for the wt.home
property:
xconfmanager -d wt.home

Windchill Utilities 173


Assuming that the command was executed from the Windows C:\ptc\
Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\..

java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar"


-r "C:\ptc\Windchill\bin\.." -d wt.home

WARNING: Propagation of xconfs to properties was not requested.


To ensure your properties are up to date, re-run with the -p option.

Property information for 'wt.home':


Values:
- C:\Windchill
Locations:
- file:/C:/Windchill/site.xconf, line 9
- file:/C:/Windchill/codebase/wt.properties.xconf, line 17

Validating XCONF Files


You can use the following options to validate XCONF files:
• To validate a site-specific XCONF file, Use:
--validateassite
or to validate a list of site-specific XCONF files, use:
--validatefilesassite
• To validate a declarative XCONF file, use:
--validateasdecl
or to validate a list of declarative XCONF files, use:
--validatefilesasdecl
The following section provides examples.

Validating XCONF Files Examples


To validate a single file as a site-specific XCONF file, run the command:
xconfmanager --validateassite=<site_xconf>
If the file is valid, then the xconfmanager will issue no output and exit with a
return code of zero.
To validate that several files are valid site XCONF files in one invocation, there
are two options. You can use the
--validateassite
parameter multiple times. For example:
xconfmanager --validateassite=<site_xconf>
--validateassite=<site_xconf>

174 Customization Guide


The other option is to create a text file, add a line for each path to a file to be
validated, then run the command:
xconfmanager --validatefilesassite=<site_list_file>
If all the files are considered valid site XCONF files, xconfmanager issues no
output and exits with a return code of zero.
You can validate declarative XCONF files in the same manner using the following
parameters:
--validateasdecl
or
--validatefilesasdecl

Other xconfmanager Options


The xconfmanager utility provides additional options that can be useful when
setting up a Windchill cluster, performing customizations, or analyzing system
problems:
• To specify the root directory that is not the default root directory, use -r. The
default root directory is the bin directory under the Windchill installation
directory.
The xconfmanager utility uses the root directory when relative paths for
XCONF references and target file paths are used.
• To force propagation of all property values listed in the site.xconf, use -F
instead of using -p. The -F option forces the propagation regardless of the
analysis that is done to determine which files are already up-to-date.
• To generate properties in a format different from the current platform setting,
use one of the following:
○ For the UNIX platform format, use -u.
○ For the Windows platform format, use -w.
• To turn on additional console output, use either -v (verbose) or -V (debug
verbose).

Windchill Utilities 175


Formatting Property Value Guidelines
The following guidelines will help ensure that you set properties correctly on the
command line when using xconfmanager:
• To specify a property whose value contains characters that might be
interpreted by your shell (such as spaces and special characters), escape them
using the appropriate technique for the shell you are using.
On a Windows system, you can include spaces in a value by enclosing the
argument with doubles quotes or you can escape the space character with ^.
For example, use either of the following:
-s "wt.inf.container.SiteOrganization.name=ACME Corporation"
-s wt.inf.container.SiteOrganization.name=ACME^ Corporation

On a UNIX system, you can use doubles quotes or you can escape the space
character with \. For example, use either of the the following:
-s "wt.inf.container.SiteOrganization.name=ACME Corporation"
-s wt.inf.container.SiteOrganization.name=ACME\ Corporation
• In many UNIX shells, the use of a backward slash (\) escapes the following
character as a literal. In most cases, using forward slashes (/) in file paths is a
simple way to specify a path without having to know the intricacies of your
shell’s command line escaping rules.
• On UNIX, dollar signs are usually interpreted by shells as variable prefixes.
To set a property value that has a dollar symbol in it, use single quotes around
the argument so that the shell does not interpreted it or use backslash to escape
the dollar symbols. For example, use either of the following:
-s 'wt.homepage.jsp=$(wt.server.codebase)/wtcore/jsp/wt/portal/
index.jsp'

or
-s wt.homepage.jsp=
‘\$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp

Other than escaping arguments so that the command-line shell does not
misinterpret them, you should not need to escape other values to be
compatible with XML or property file syntaxes. The xconfmanager escapes
property names and values automatically if necessary.

176 Customization Guide


Windchill Command
About the windchill Command
PTC has provided a command, windchill, to invoke Windchill actions. For
example, the command can be used to stop and start Windchill, check the status of
the Windchill server, and create a new shell and set the environment variables. It
can also be used as a Java wrapper. In that regard, it can accept a Class file as an
argument, just like Java, and execute it without a predefined environment
(Windchill classes in CLASSPATH, Java in PATH, and so on).
The windchill command should be used to execute any server-side Windchill Java
code. This will ensure that the environment that the command is executed in is
properly setup. The environment that actions are executed within, including the
windchill shell action, is defined by the wt.env properties in the
wt.properties file. For example, the wt.env.CLASSPATH property will set
the CLASSPATH environment variable for the action that is being invoked.
The windchill command is a Perl script that has also been compiled into a
Windows binary executable. For UNIX systems, Perl 5.0 or greater must be
installed. The windchill script assumes that Perl is installed in the standard install
location of /usr/bin/perl. If Perl is not installed at this location, you can
either create a symbolic link (recommended method) to the Perl install location or
edit the windchill script to reference the Perl install location. To modify the
windchill script, edit the <Windchill>/bin/windchill file. Locate the #!
entry (for example, #!/usr/bin/perl -w) and change the Perl directory to the
location where Perl is installed.
The windchill command is located in the <Windchill>/bin directory. If you
receive a command not found message when you execute the windchill command,
add the <Windchill>/bin directory to your PATH environment variable. The
syntax of the windchill command is:
windchill [args] action

You can display the help for the windchill command by executing windchill with
the -h argument or with no argument.
The following tables list some of the arguments and actions applicable to the
windchill command. To see a complete list of the arguments, use the report
generated from the help (argument).

windchill Arguments
Arguments Description
(optional)
-h, –help Displays help and exits.
-v, –[no]verbose Explains what is being done when a command is

Windchill Utilities 177


Arguments Description
(optional)
executed. Default is:
-- noverbose
-w, –wthome=DIR Sets the Windchill home directory. Default is the
parent directory containing the windchill script.
Note
On UNIX systems where you have multiple
instances of Windchill installed under the same
user account, settings made to WT_HOME and
SQLPATH environment variables by using this -w
option are overridden by any settings to these same
variables in the user's .cshrc, .login, and .profile
shell initialization files.
–java=JAVA_EXE The Java executable. Default is the wt.java.cmd
variable value specified in the $WT_HOME/
codebase/wt.properties file.
-cp, Java classpath. Default is the wt.java.classpath variable
–classpath=PATH value specified in the $WT_HOME/codebase/
wt.properties file.
–javaargs= Java command line arguments.
JAVAARGS

windchill Actions
Action Description
shell Sets up a Windchill environment in a new instance of
the currently running shell.
start Starts the Windchill server.
stop Stops the Windchill server.
status Retrieves the status of the Windchill server.
version Displays the Windchill installation version.

178 Customization Guide


Action Description
properties <resource> Displays the properties as seen by Windchill for the
[,...][?key[&key2]...] given resource with substitution and other actions
executed. It can be limited to a given set of keys.
For example:
windchill properties wt.properties –
lists all wt.properties
windchill properties
wt.properties?wt.server.codebase – lists
server codebase
windchill properties
wt.properties?wt.env.* – lists all the
environment variables use by windchill shell
windchill properties – generates the help
report with no arguments
CLASS [CLASS_ Run a Windchill class with optional class arguments.
ARGS] For example:
windchill wt.load.Developer -UAOps

Windchill Utilities 179


Windchill Shell
About the windchill shell
The windchill shell brings up a new command shell, from the parent shell that is
setup for the Windchill environment. This includes setting all environment
variables defined in wt.env property in the wt.properties file.
To execute the windchill shell, at the command prompt enter the following
command:
windchill shell

When you are finished using the windchill shell, you can exit the shell and return
to the parent shell.
PTC recommends running all server-side Windchill applications, tools, and
utilities from the windchill shell. Also, you can use the windchill shell to set up
your development environment to use javac or Java directly.

180 Customization Guide


8
Customization Tutorial
Tutorial Overview .................................................................................................... 182
Create Administrator and User ................................................................................. 184
Create a Library and Document ................................................................................ 194
Allocate Database Columns for Local Attributes......................................................... 200
Create a New Attribute Definition and Add it to the Document Type ............................. 202
As the End User, Create a Document with the new Attribute ....................................... 209
Create a Document Subtype .................................................................................... 212
Create an Instance of the New Document Subtype .................................................... 216
Model a New Document Subclass ............................................................................ 217
Create an Instance of the New Document Subclass ................................................... 224
Verify the Customizations......................................................................................... 227
Customization Tutorial Summary .............................................................................. 228

This tutorial is intended for programmers who are not that familiar with
Windchill.

181
Tutorial Overview
This tutorial illustrates a minimal configuration to create an environment in which
you can create administrative objects (users) and business objects (attribute
definitions, types and subclasses) and test them as an end user (by creating a
container and document instances). This will give you some idea how to work in
Windchill products, and help you ensure that your customization environment is
configured correctly.

Note
This tutorial is intended for programmers that are not familiar with Windchill.

Goals
In this tutorial you will:
• set up and navigate a Windchill test system
• define soft and modeled types
• create instances of those types
Performing these tasks will:
• confirm that their development environment is properly configured
• shows that Windchill UIs adapt to new type and attribute definitions

Assumptions
• PDMLink standalone or Integral PDMLink and Windchill ProjectLink.
• You are using Oracle for your database storage (SQLServer will be similar).
• The system is installed, configured and runs. You know how to start and stop
the system.
• You have the ability to compile Java code into the system codebase.
• You have access to the system database instance and permission to create new
schema.
• You can login as the Windchill System Administrator.

Outline
1. As the System Administrator, create Organization Administrator and End
User.
2. As the end user, create a Library and a document instance.

182 Customization Guide


3. Allocate database columns for Local attributes.
4. As the Organization Administrator create a reusable attribute definition and
add it to the local document type.
5. As the end user, create a document instance which will include the new
attribute.
6. As the Organization Administrator create a document type and add a new local
attribute to it.
7. As the end user, create an instance of the new document subtype.
8. Model a new document subclass and deploy it. As the Organization
Administrator add an attribute to it and update the layouts.
9. As the end user, create an instance of the new document subclass.
10. Verify what you have done, by searching for instances of your documents.

Customization Tutorial 183


Create Administrator and User
1. Open Windchill in your browser and login as the System Administrator.

2. Open the Navigator.


3. Select the Browse tab.
4. Select the Site context.
5. Select Utilities.

6. Under Business Administration, select Participant Administration.

184 Customization Guide


7. Select Create new user .

8. Create an Organization Administrator with the following values:


• Name: orgadmin
• First: Orville
• Last: Adams
• E-mail Address: orgadmin@acme.com
• Organization
Click Search to select for the organization. Choose the default
Organization created for your system (this was specified when the system
was installed).
• Password and Password Confirmation: orgadmin

Customization Tutorial 185


9. Select Next.
10. Select the green ‘+’ icon to add groups to the table.
11. In the Find Participant dialog select Search (leave the search field blank)

186 Customization Guide


12. Add Administrators, Attribute Administrators (Site) and Type Administrators
(Site) to the Participant List, then select OK.

Note
For any other organization you would not need to select Administrators.
But because this is the default site organization, the organization
administrator must also be a site administrator in order to manage types
and attributes.

13. Select Finish.

Customization Tutorial 187


14. Select Create new user.
15. Create an End User using the same steps that you used to create the
Organization Administrator user. Be sure to use the same Organization.
Important: Do NOT add the End User to any groups.

188 Customization Guide


16. Verify that you have defined two users:

17. Now you must declare the Organization Administrator user as an Organization
Administrator. Open the Navigator.

Customization Tutorial 189


18. Select the Browse tab
19. Select the Organizations context.
20. Select the “plus” icon next to your Organization.
21. Select Administrators.

22. Click the add users icon ( ).

23. In the Add Organization Administrators dialog select Search, leaving the
search fields blank. Select the user you created to be the Organization
Administrator, and then select Add>> and OK.

190 Customization Guide


24. Return to your Organization in the Navigator and select Creators.

25. Select “Library Creators” from the Creators pull down menu

Customization Tutorial 191


26. Select the ”Add Users to the Library Creators Group” icon.

27. In the “Add User to the Creators Group” dialog, select Search. Select the End
User and select Add>>. Then select OK.

28. You should now see your user in the Creators table:

192 Customization Guide


At this point in the process, as the System Administrator, you have created an
Organization Administrator and an End User. The Organization Administrator is
also an Attribute and Subtype administrator. The End User is also a Library
Creator.

Customization Tutorial 193


Create a Library and Document
Now as the End User you will create a Library and a document instance in that
Library.
1. You must now login to the Windchill system as the end user. With some
browsers you can do this in a new browser window. Others browsers may
require closing the current browser first.
2. Confirm that you are logged in as the End User (not the Organization
Administrator and not the System Administrator) You should see the name of
the End User displayed at the top of the display:

3. Navigate to the Library context and select “View all”

4. As the End User, create a new Library. Select New Library.

194 Customization Guide


5. Enter the attributes for the Library, and select OK.

6. Now you will see the details for your new library.

Customization Tutorial 195


7. From the Actions menu select New, and from the sub menu New Document:

196 Customization Guide


8. In the New Document dialog, select Document in the Type drop down menu.
Then Browse… to select a local document to upload as the Primary Content.
Change the Name of the document to “Document 1”. Select Finish

Customization Tutorial 197


9. Navigate to your Library’s Folders:

10. Here is the new document in its folder. Note that the Number is automatically
assigned.

11. Select the View Information icon to see details about the document.

198 Customization Guide


Customization Tutorial 199
Allocate Database Columns for Local
Attributes
To create new local attributes, you first need to allocate space for them in the
database. You add columns per database table, per type of attribute for required
data type. You can allocate more than you plan to use immediately for future
growth.
We will add five number columns to the WTDocument table for use later in the
tutorial.
1. From the Windchill shell, run the following command line utility (the
expected console output is also shown): AddColumns
wt.doc.WTDocument Long=5

2. The Upgrade Schema window will automatically appear, and disappear, after
executing:

200 Customization Guide


3. The five new columns have been created on the WTDocument table for the
respective data type. To make use of them, you must restart the Windchill
Method Server. Do that now.

Note
If the server is SOX configured then you have to first de-configure the
SOX and run the Add column command and again configure the server to
SOX.

Customization Tutorial 201


Create a New Attribute Definition and Add
it to the Document Type
1. As the Organization Administrator you will create a new attribute type and
add it to the default Document type.
2. Confirm that you are logged in as the Organization Administrator.

3. To open the Type and Attribute Management, navigate to Organization ▶


Utilities. Then under Business Administration ▶ Type and Attribute
Management.

202 Customization Guide


4. In Manage Types select Document.

Customization Tutorial 203


5. From Actions select Edit.

6. With the Attributes tab selected, you can now select the “Create a new
attribute” icon and a new dialog will appear:

204 Customization Guide


7. Specify a new Integer attribute with Unique Identifier “sizeA”. The type will
be Local. Select Next.

8. Set the Datatype to “Integer Number” and select Next.

Customization Tutorial 205


9. Change the Display Name to “Size A” and select Finish:

10. Type and Attribute Management will now show your Attribute:

11. Set the Default Value for the Size A attribute to “1”, select Save:

206 Customization Guide


12. Close the Attribute panel within the dialog by selecting the collapse panel
button and select “OK” to finish editing. You have now added the “Size A”
local attribute to the Document type:

Customization Tutorial 207


13. In this case, we do not need to change, or add to, any attribute layouts. For
Document, the “Create layout” and “More attributes layout” contain “default
groups” that will automatically include your attribute in Create layouts and
Info Page layouts in Windchill standard UIs.
14. Close the Type and Attribute Management dialog window.

208 Customization Guide


As the End User, Create a Document with
the new Attribute
1. Follow the instructions above that you used to create a document, create a new
document with the following attributes. Remember to do it as the End User
you defined. Note: Set Size A to 101 and the Name to Document 101) then
select Finish:

2. Navigate to the Details for the new document. Here you should see the Size A
attribute with value 101:

Customization Tutorial 209


3. If you go back and look at the attributes for the first document you created, it
will now display “Size A”, but with no value. Even though you specified a
default value for sizeA. This is because the default value only applies to
instances created after the attribute was defined on the type.

210 Customization Guide


Customization Tutorial 211
Create a Document Subtype
As the Organization Administrator, you will create a new document subtype.
1. Verify that you are logged in as the Organization Administrator.
2. Select Organization ▶ Utilities ▶ Type and Attribute Management.
3. In the Type and Attribute Management window, select Document with the right
mouse button and select New Sub-Type

212 Customization Guide


4. Specify the new document type Internal Name and Display Name, then select
OK:

5. Follow the instructions above that you used to create the “Size A” local
attribute, to create a new local attribute, for your new type, called “Size B”
with a default value of “2”.

Customization Tutorial 213


When you are done, your new document type will look something like this:

6. Edit your type and change the Icon for your type to “netmarkets/images/
repair_failure.gif”. The name of the icon is not meaningful, but it is a
distinctive image that you will be able to pick out in the UI later. Note that the
image automatically to the right of the path you just entered:

214 Customization Guide


7. Select OK to save your changes.

Customization Tutorial 215


Create an Instance of the New Document
Subtype
1. Now, as the End User, create an instance of the new document type called
Document 102. Be sure to set the Type of your document to your new type.
Use the default value for Size A and set Size B to 102. Then look at the
attributes for the document instance: Also note that this document instance has
a unique icon (a rectangle with a red cross in it - the “repair_failure.gif” file
that you selected in the previous step).

216 Customization Guide


Model a New Document Subclass
Now you will use Java Annotations provided by Windchill’s Information Modeler
to create a document subclass with a new integer attribute.
1. From the Windows Start menu open a Windchill Shell and change to the src
directory.

2. The new class will be in the package called com.acme. Change directory to
com/acme, creating the directories if necessary.

3. Create a new source file called AcmeModeledDoc.java in the acme directory.


Here are the contents for the source file:
package com.acme;

import wt.doc.WTDocument;
import wt.util.WTException;
import com.ptc.windchill.annotations.metadata.*;

@GenAsPersistable(superClass=WTDocument.class,
properties={
@GeneratedProperty(name="sizeC",
type=Integer.class, initialValue="3",
javaDoc="Integer value to represent the size of C.")},

iconProperties=@IconProperties(standardIcon="netmarkets/images/stop.gif",
openIcon="netmarkets/images/stop.gif")
)
public class AcmeModeledDoc extends _AcmeModeledDoc {

static final long serialVersionUID = 1;

public static AcmeModeledDoc newAcmeModeledDoc()


throws WTException {
AcmeModeledDoc instance = new AcmeModeledDoc();
instance.initialize();
return instance;

Customization Tutorial 217


}
}

The name of the icon is not meaningful, but it is a distinctive image that you
will be able to pick out in the UI later.
4. Now go back to the command prompt and compile your file with this
command: tools class -Dclass.includes=com\acme\*

You will find the compiled class file and generated ClassInfo.ser file (that
contains meta data about the new class) here:..\Windchill\codebase\
com\acme\

218 Customization Guide


5. Now you will generate the SQL scripts for your new document class. Enter
this command in the Windchill Shell:tools -Dgen.input=com.acme.*
sql_script

This will generate the SQL commands necessary to create the database
schema for your new subclass. You will find the generated schema here:
..Windchill\db\sql\com\acme\create_AcmeModeledDoc_

Customization Tutorial 219


Table.sql
6. You can inspect the sql files to see what was generated.
7. Now you will create the table and associated database artifacts for your new
document class. To do this, from within sqlplus, you will execute two
scripts:..\Windchill\db\sql\com\Make_pkg_com_Table.sql
..\Windchill\db\sql\com\Make_pkg_com_Index.sql
8. From the Windchill Shell, login to sqlplus.sqlplus <db_user>/<db_
user_pw>@<sid>
9. At the “SQL” prompt execute the two scripts using full path names similar to
this:@<Windchill>\db\sql\com\Make_pkg_com_Table.sql@
<Windchill>\db\sql\com\Make_pkg_com_Index.sql

10. Now execute a describe command to see the columns in the new table for your
class. Note that there is a “SIZEC” column for the attribute you added directly
to the class.describe AcmeModeledDoc

220 Customization Guide


You may also want count the number of rows in the table to confirm that it is
empty:select count(*) from AcmeModeledDoc;
11. Restart the method server.
12. As the Organization Administrator, open the Type and Attribute Management.
You will now see your modeled document subclass in the type hierarchy. Note
the red flag “stop” icon that you specified for your subclass in the model

13. We must now change the display name for the sizeC attribute and add it to a
group in each layout. Edit your type, and change the default name of the sizeC
attribute to “Size C”. Select Save

Customization Tutorial 221


14. Select the “Create layout”. Drag the “Size C” attribute to the Attributes
column and Save.

222 Customization Guide


15. Select the “More attributes layout”. Drag the “Size C” attribute to the
Attributes column and Save and OK.

Customization Tutorial 223


Create an Instance of the New Document
Subclass
1. As the End User, navigate to your Library folder and create an instance of
your new document type.
• Type: com.acme.AcmeModeledDoc
• Name: Document 103
• sizeC: 103
2. Browse for a file to add as content, and leave the other attributes with default
values.

224 Customization Guide


3. Navigate to the info page for Document 103 and note that the sizeA and sizeC
attributes have the correct values.

4. You now have four documents:


• Document 1 is an instance of the default Windchill document type
• Document 101 is an instance of the default Windchill document type with
the new sizeA attribute that you added
• Document 102 is an instance of the new soft document type you added
• Document 103 is an instance of the new modeled document type you
added

Customization Tutorial 225


226 Customization Guide
Verify the Customizations
To verify what you have done, search for instances of your documents.
1. In the top right corner of the Windchill page, enter “Document 1*” in the
Search box. Your results should look like this:

2. Review the Modeled Object info page for the new modeled subclass.

Note
The instances of the types you created are shown with the custom icons you
specified. This confirms that your new custom types are integrated with
standard Windchill functionality.

Customization Tutorial 227


Customization Tutorial Summary
In this tutorial you have:
• Created new users including an Organization Administrator and an End User
• Made the Organization Administrator a Type and Attribute Administrator
• Made the End User a Library creator
• Created a library
• Created reusable attributes definitions and subtype definitions, and instances
of those types
• Created a modeled type and an instance of that type
• Confirmed that your Windchill development environment is configured to
support modeling with Java Annotations and the Windchill Information
Modeler
• Verified what you have done, by searching for instances of your documents.

228 Customization Guide


9
User Interface Customization
Windchill Client Architecture Overview ...................................................................... 232
Windchill Client Architecture Common Objects Overview............................................ 245
Javascript Functions Overview ................................................................................. 248
Adding Custom Code to all Windchill Client Architecture Pages .................................. 255
MVC Components Overview .................................................................................... 258
MVC Tables ............................................................................................................ 287
Customizing Generic Aspects of JSP Pages.............................................................. 290
Bread Crumbs Component....................................................................................... 299
Client Tabs.............................................................................................................. 311
Checkin/Checkout ................................................................................................... 325
Component Access Control...................................................................................... 330
Attachments............................................................................................................ 337
Attribute Panels....................................................................................................... 348
Customizing Access Control For Packages ............................................................... 400
Customization Tools Overview.................................................................................. 404
Adding Validation Logic for Actions and Properties..................................................... 442
Split Pane / Two Pane.............................................................................................. 463
Defining Layouts in a Type Load File ........................................................................ 474
Configuring the Drag and Drop Zone......................................................................... 478
Customizing Role-Based UI Functions - Attribute Visibility .......................................... 482
Customizing Role-Based UI Functions — Action Visibility ........................................... 494
Preference Framework ............................................................................................ 495
Constructing URLs .................................................................................................. 501
Offline Package Customization................................................................................. 502
System Banner Alert Message ................................................................................. 506
Adding a Status Glyph ............................................................................................. 508
Action Framework for Windchill Client Architecture .................................................... 512
Tab Models ............................................................................................................. 539
Customizing Role-based Visibility ............................................................................. 549
User Interface Stickiness ......................................................................................... 561
Defining Menus ....................................................................................................... 562

229
Adding Custom Content to the Home Page ............................................................... 578
Acquiring Data via Info*Engine ................................................................................. 584
NmObject Utilities.................................................................................................... 590
File Download ......................................................................................................... 596
Dynamically Resolved Attributes for Customizations .................................................. 604
Constructing and Rendering a Table Using the JSP Framework .................................. 606
Windchill Client Architecture Tree ............................................................................. 642
Attribute Customization............................................................................................ 658
Adding Custom Modeled Attributes to all Table Views................................................. 736
Attribute Tables ....................................................................................................... 737
Icon Delegates ........................................................................................................ 742
Creating Custom Graphical Representations ............................................................. 749
UI Validation............................................................................................................ 770
URL Authorization ................................................................................................... 823
Customizing the Find Number Field .......................................................................... 826
Inline Messaging ..................................................................................................... 832
Windchill Client Architecture Wizard.......................................................................... 838
Wizard Processing .................................................................................................. 866
Building Wizards to Create a Single Object................................................................ 892
Building Wizards to Edit a Single Object .................................................................... 914
Customizing Reusable Wizard Steps ....................................................................... 928
Handling External Requests Using an MVC Controller................................................ 959
Client Generated Form Data .................................................................................... 964
Customizing Information Page Components .............................................................. 972
Configuring Pickers ............................................................................................... 1006
Configuring a Context Picker .................................................................................. 1015
Configuring an Item Picker ..................................................................................... 1025
Configuring an Organization Picker......................................................................... 1034
Configuring a Type Picker ...................................................................................... 1043
Configuring a User Picker ...................................................................................... 1061
Configuring a Participant Picker in JCA ................................................................... 1068
Configuring a Participant Picker in AngularJS .......................................................... 1083
Configurable Link Tables........................................................................................ 1090
Configurable Revision Links ................................................................................... 1100
Customizing Windchill Help Center Content............................................................. 1107
Adding Topics to the Help Center TOC .................................................................... 1108
Linking to Help Topics .............................................................................................1114
Windchill Help Center Logging.................................................................................1115
Customizing Indexing Behavior .............................................................................. 1120
Customizing Solr ................................................................................................... 1122
Customizing Faceted Search ................................................................................. 1128

This section contains information related to customizing the Windchill user


interface.

230 Customization Guide


10
User Interface Technology
Overview
Windchill Client Architecture Overview ...................................................................... 232
Windchill Client Architecture Common Objects Overview............................................ 245
Javascript Functions Overview ................................................................................. 248
Adding Custom Code to all Windchill Client Architecture Pages .................................. 255

This chapter explains and gives some basic overview of the Windchill Client
Architecture UI Framework.
Before reading this chapter, you should be familiar with Java, JavaServer Pages
(JSP), JavaServer Pages Standard Tag Library (JSTL) and Expression Language
(EL).

231
Windchill Client Architecture Overview

Note
Before reading this chapter, you should be familiar with Java, JavaServer
Pages (JSP), JavaScript, JavaServer Pages Standard Tag Library (JSTL) and
Expression Language (EL).
• For more information on JSTL see: http://java.sun.com/products/jsp/jstl/
• For more information on EL see: http://java.sun.com/j2ee/1.4/docs/
tutorial/doc/JSPIntro7.html.

The Windchill Client Architecture provides a framework for building pages easily
and consistently by providing a standard set of components and services that are
configurable and customizable. The set of components includes, but is not limited
to, a table, a tree, an information page, a wizard, and a dynamic javascript menu.
At a lower level, these container components use other common components,
called actions, action models and GUI components, to display data inside of them.

The Windchill Client Architecture is Model-View-Controller based. There are two


MVC based paths available for use, a Java Builder based approach and a JSP
based approach.
A good deal of information about the Model-View-Controller design pattern is
available on the web.
For more information about MVC and the Model 2 architecture, see http://www.
oracle.com/technetwork/articles/javase/servlets-jsp-140445.html.

232 Customization Guide


Java Builder based
This approach is the recommended way of implementing tables, trees, information
pages, and panels of attributes since Windchill release 10.0. When implementing
one of these components, the configuration of the component is specified in a
ComponentConfigBuilder (java file) and the data acquisition is specified in a
ComponentDataBuilder (java file).
For more details about this approach, refer to Java Builders on page 234.

JSP and Tags based


This approach was used in previous releases and should only be used for
implementing wizards (create/edit) and property panels. Although tables and trees
can be implemented with this approach it is not recommended. When
implementing one of these components, the configuration of the component and
the data acquisition is defined in a tag (from Windchill Components tag library) in
a JSP.
For more details about this approach, refer to JSP and Tags on page 237.
Please note that at some point in the future, this approach will be deprecated in
Windchill.
The future vision is to have all components in the system converted to use the new
Java model and controller builders. See MVC Components on page 257 for more
information. When creating new customizations use the Java Builders path when
possible. Many previous customizations using the Tag and TagLibs path will
continue to work.

URL Strategy
In a Windchill client application starting at 10.0 the URL consists of multiple
pieces. The URL still begins with the host information and the Windchill web app
name. Then the URL has the following components.
app/ app/ is the address of the shell. The shell renders the header,
navigator and a blank content area.
# The # character is the token. The complete 10.0 URL is actually
made up of two URLs put together. This token marks the end of
the URL for the shell and the beginning of the URL for the
content that will be displayed within the content area.

User Interface Technology Overview 233


ptc1/comp/ After the # token is the URL to the content page. It is loaded via
ptc1/tcomp/ AJAX into the content area. This is a logical content address,
not a physical location. The URL after the # token is normally
ptc1/ an MVC path to a controller, for example: ptc1/comp/recent.
updates.table
comp Used in the URL to specify that the builder to
look up is not type based.
tcomp Used in the URL to specify that the builder to
look up is type-based.

The URL after the # token can also take the formptc1/
<objecttype>/<action name>, which mirrors the action
mappings in actions.xml, for example: ptc1/report/
listUpdates
Query Strings After the question mark is the query-string as in any other URL.
It is possible to have two query strings in the URL. When the ?
is before the # token the query string parameters will be passed
to the shell. When the query string is after the content address
after the # token the parameters will be passed to the page in the
content area.
Most pages need to be loaded through the shell to work correctly. Calling their
URL’s directly will load them without the CSS and JavaScript they need to
function correctly. Every page in Windchill is now being served through a
controller class. Even URLs which look like direct JSPs are being served through
the LegacyController. Spring MVC is used under the covers to configure them.
SeeMVC Components on page 257 for more information.

Java Builders
This approach presents several advantages over the older JSP and Tags based
approach. By separating the model and controller from the JSP, we enable a more
flexible and maintainable system. For example, several different JSPs can now
take advantage of the same java builder. And, because, builders are now written in
java, they can share attributes through inheritance. The basic steps to produce
many components (table, tree, attribute panel, etc) are:
• Describe the component (Component Config Builder)
• Acquire the necessary data (Component Data Builder)
• Render the component (JSP)

234 Customization Guide


Controller – ComponentController
Requests for JCA components are routed to a centralized
ComponentController. This controller derives the component ID from the
request parameters, and then uses Spring configuration to look up builder
implementations. SeeMVC Components on page 257 for more information.

Model – Component Config and Data Builders


The model for your UI is made up of the component configuration information
and the data. These are created by a class or classes that implement the
ComponentConfigBuilder and ComponentDataBuilder interfaces.
• ComponentConfigBuilder
You control the rendering of your UI through a Java Class that implements the
ComponentConfigBuilder Interface. This interface contains one method
buildComponentConfig. This method should contain all the
configuration information needed for the UI you are building. One example of
a ComponentConfigBuilder might look like the following:
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();

table.setLabel("My Table");
table.setSelectable(true);
table.setType("wt.pdmlink.PDMLinkProduct");
table.setActionModel("my_toolbar_actions");
table.setShowCustomViewLink(true);

table.addComponent(factory.newColumnConfig(ICON, true));
table.addComponent(factory.newColumnConfig(NAME, true);
table.addComponent(factory.newColumnConfig(INFO_ACTION, false));
return table;
}
• ComponentDataBuilder
The data for your UI is created by a Java Class that implements the
ComponentDataBuilder Interface. This interface contains one method
buildComponentData. The object returned from this method should
represent the Model for the UI and can take multiple forms. Some examples of
what this method might return are ComponentData, a Persistable, a
QuerySpec, any custom Java Object, etc. One example of a
ComponentDataBuilder might look like the following:
public Object buildComponentData(ComponentConfig config,
ComponentParams params)
throws Exception {

User Interface Technology Overview 235


String tableId="netmarkets.product.list";
return ProductListCommand.getProducts(tableId);
}
• Data Sources
Table and Tree components are able to make use of a new feature called
DataSources. DataSources provide improved perceived table and tree
performance through features like the ability to asynchronously load data and
the ability to sort and scroll data on the client. To make use of this new
asynchronous feature, your Component Data Builder should implement
ComponentDataBuilderAsync for table components and
TreeDataBuilderAsync for Tree components.

View — JSP
In this approach, the JSP is simply a “view”, rather than a combination of all
three, as it is in the JSP and Tags approach. Each component has a default view
(JSP) to render out the component, however if you wish to override the default
view you can call the setView() on the ComponentConfig that your
ComponentConfigBuilder returns. All the view jsps should be located in
codebase\WEB-INF\jsp base location.
• Basic Elements of the JSP
When Creating a JSP view for a Java Builder, you will need to be aware of a
few important jsp fragment files. The first and most important is the begin_
comp.jspf. This files exists in codebase/netmarkets/jsp/util/.
The purpose of this jspf is to setup the model data information required by the
view.
Another jspf that is included is the end_comp.jspf also located in
codebase/netmarkets/jsp/util/. The purpose of this file is to:
Mark that the page load is complete to allow proper functioning of the
javascript within the page. An example of a jsp view might look like:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>

<%@include file="/netmarkets/jsp/util/begin_comp.jspf"%>
<mvc:table setPageTitle="true"/>
<%@ include file="/netmarkets/jsp/util/end_comp.jspf"%>

Supported Components
• Table
• Tree
• Information Page
• Attribute Panel

236 Customization Guide


• Attribute Table
• Property Panel

Related Customization Documentation


• MVC Components on page 257
• Attribute Tables on page 737
• Windchill Client Architecture Tree on page 642
• Information Pages on page 971

JSP and Tags


Several tags and taglibs are delivered as part of the framework. These taglibs
contain a set of handlers for including components and other common
functionality into your pages. The basic steps to produce many components (table,
tree, property panel, wizard, etc.) are:
• Describe the component (JSP)
• Acquire the necessary data (Data Acquisition Tags)
• Render the component (Component Renderer Tags)
The configuration of these phases is done by calling the tag handlers in the JSP
Page. To use the tags, you need to include the components library. The following
code snippet includes the library:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

Controller — JSP
• Basic Elements of the JSP
You will need to be aware of a few important jsp fragment files. The first and
most important is the begin.jspf. This files exists in codebase/
netmarkets/jsp/util/. The purpose of this jspf is to:
○ Include a tag for rendering the shell that surrounds all pages.
○ Take care of housekeeping like:
◆ Instantiates the beans (context, clipboard, etc)
◆ Executes a command (for actions only)
◆ Includes some JS functions
◆ Creates ONE form for the page data (called mainform)
◆ Provides support for closing pop ups and refreshing the main page

User Interface Technology Overview 237


Another jspf that is included is the end.jspf also located in codebase/
netmarkets/jsp/util/. The purpose of this file is:
○ mark the begin and end of the content area for DHTML content switching
○ catch exceptions and handles them if they occur within the page
When constructing a wizard, there is a special beginWizard.jspf file, located in
netmarkets\jsp\components, that should be used instead of the begin.jspf that
will do essentially the same things as the begin.jspf.
• Component Description Tags
Component description tags are the first tag included in the jsp. These
generally take the form of describe*Tag. (E.g. DescribeTableTag)
Component Description Tags define the columns/properties that the
component will display. This happens first in a JSP since the way the data is
retrieved may depend on the properties that are requested. During the
component description phase the developer uses a “describe” tag handler that
tells the infrastructure about the component they would like to display. One
example describe handler is the describeTable, which might look like the
following:
<jca:describeTable var="tableDescriptor" id="my.table.id" configurable="true"
type="com.myco.MyType" label="${myLabel}">
<jca:setComponentProperty key="actionModel" value="my action model"/>
<jca:describeColumn id="name"/>
<jca:describeColumn id="nmActions" />
<jca:describeColumn id="status">
<jca:setComponentProperty key="percent" value="true"/>
</jca:describeColumn>
</jca:describeTable>

Structure of the example


The tag contains a set of nested tags which give it some structure. There are
two kinds of nested tags:
○ setComponentProperty
This tag configures the properties of its parent tag that aren’t exposed as
attributes of the parent tag itself. This gives the infrastructure and the
developer some flexibility about the metadata they’d like to be available
down the road, without always requiring a tag library definition (tld)
update to do so.
○ describeColumn

238 Customization Guide


This tag describes a particular column that the developer wants to display.
Like the parent describeTable tag, this tag accepts child
setComponentProperty tags. There is also a describeProperty tag that has
the same semantics when used in property panels.
Underneath the covers, the describeTable tag is simply configuring a java
bean that implements the ComponentDescriptor interface. The attributes
that are available via the tag handler typically correspond to properties of
the ComponentDescriptor. The ComponentDescriptor object is important
to keep in mind as it comes into play later on during the data acquisition
phase.
The ComponentDescriptor object that the describe tag handlers build is
communicated to the rest of the world via the required "var" attribute. The
handler creates a scoped variable for the ComponentDescriptor object
named whatever the var attribute value is. In the example above, the var
attribute was mapped to "tableDescriptor", but it can be mapped to any
legal JSP variable identifier. Note that this semantic for the var attribute is
reused from the JSTL tag handlers. Since the ComponentDescriptor object
is a scoped attribute, it can be referenced later in the page using the JSP EL
as well as Java code. Subsequent tags can now refer to the descriptor using
the ${varName} syntax, for example.

Model — Data Acquisition Tags


The necessary model data is acquired through data acquisition tags. These
generally take the form of get*Tag. (E.g. getModelTag)
The Data Acquisition Tag will be the second phase and will come second in your
jsp. This is because the Data Acquisition Tag gets the model data based on the
description from Component Description Tag. In the data acquisition phase, the
developer combines a component description with some additional information on
how to actually go and get the data that will back the component. One example of
getting a model for a table might look like the following:
<jca:getModel var="tableModel" descriptor="${tableDescriptor}"
serviceName="com.myco.MyService"
methodName="getMyObjects">
<jca:addServiceArgument value="${myArgument}" type="java.lang.Long"/>
</jca:getModel>

Structure of the example


• descriptor and var
The tag gets a component description by using the EL to look up the scoped
"tableDescriptor" variable. The tableDescriptor variable would typically be put

User Interface Technology Overview 239


in the page by a previous describe tag that had a var value of
"tableDescriptor".
Like the describe tags, the get tags produce a java bean that is added to the
page as a scoped variable named with the var attribute value. In the case of the
get tags, the resulting bean is an instance of ComponentModel.
• What is it doing?
Developers typically don't interact with the ComponentModel object produced
by the get tags. Instead, the developer provides information on some lower-
level API that the client infrastructure invokes and then transforms into a
ComponentModel. The sample code above, for example, will invoke the com.
myco.MyService.getMyObjects(myArgument) method, take the results, and
turn these into a ComponentModel object.

View — Component Renderer Tags


The view is rendered by the Component Renderer Tag. These generally take the
form of render*Tag (E.g. RenderTableTag)
This produces HTML and JavaScript based on the model data. Rendering using
Component Renderer Tags is usually simple for the developer to set up. The
Windchill Client Architecture provides a few render tags that take the
ComponentModel produced by a “get” tag and turns it into HTML and JavaScript.
Like the get tags, these tags uses the EL to accept scoped variable data from the
page:
<jca:renderTable model="${tableModel}"/>

Structure of the example


In this case, the table renderer is taking an input ComponentModel assigned to the
scoped variable "tableModel", and rendering it as a table.

Supported Components
• Wizard (Create/Edit)
• Table
• Tree
• Property Panel
• Attribute Table

Additional Resources
• Tag Library Documentation
The Windchill Tag Library Documentation is delivered with the product and
can be accessed through the UI. To locate the documentation, first enable the

240 Customization Guide


customization examples and tools, then browse to the customization
navigation and select the tools option.
Under the API documentation section of the page you will find a link to the
Windchill Tag Library Documentation
• Related Customization Documentation
○ Windchill Client Architecture Wizard on page 838
○ Wizard Processing on page 866
○ Building Wizards to Create a Single Object on page 892
○ Building Wizards to Edit a Single Object on page 914
○ Attribute Panels on page 348

Common Java Services


GUI Components
GUI Components are objects that define how an attribute is to be rendered. They
are controlled though properties set in the Data Utilities. A GUI Component also
contains a renderer that is responsible for writing out the HTML and/or
JavaScript. For more information on GUI Components see Data Utilities on page
704.

Data Utilities
Data Utilities are delegates invoked during construction of the model that allow
post-processing and/or augmentation of the data returned by data acquisition
APIs. For more information on GUI Components see Data Utilities on page 704.

Action Service
Configuration of actions and action models that are available within the system
are defined using xml files. There is an action service that reads these xml files
and manages the set of actions and action models. Interaction with the service is
done via the components. Developers in general would not call the service
directly. For more detailed information about the action framework see Adding
Actions and Hooking Them Up in the UI on page 511.

Validation Service
Validation of actions and properties can be done via logic encapsulated into a
validator that gets executed when a component such as a action menu, table, or
property panel includes that action or property. When a page including one of
these components is requested, the framework will call the validation service to
determine which of the actions or properties should be displayed, disabled, or
hidden. The service will invoke the appropriate delegates to gather the requested

User Interface Technology Overview 241


status for that action or property. As a customization point, you can write a
delegate that is mapped to a specific property or action, that contains logic to
indicate when that element is valid to show, hide, or disable in the user interface.
The validation framework is tied into the Role Based UI framework Role based
support is included for most actions in the product, and customized actions can
also take advantage of this capability. Role based capability is supported for
reusable attributes created via Type and Attribute Management utility, not modeled
attributes. That validation service will actually call the role based service as a first
pass of validation. If the action or property is valid for the user based on role, the
service will then invoke the appropriate delegate. See Customizing Role-Based UI
Functions - Attribute Visibility on page 482 for more information.
For more detailed information about the validation framework see Adding
Validation Logic for Actions and Properties on page 442.

Additional Resources
Theme
The Windchill theme defines the look and feel (colors, fonts, images etc). These
are controlled by css. For more information on adding custom css see Adding
Custom Code to all Windchill Client Architecture Pages on page 255 for more
detailed information.

Windchill Javascript Functions


The Windchill JSDoc Javascript documentation is delivered with the product and
can be accessed through the UI. This documentation describes common JavaScript
functions which are available for use in your customizations. To locate the
documentation, first enable the customization examples and tools, then browse to
the customization navigation and select the tools option. For more information see
Customization Tools Overview on page 404.
Under the API documentation section of the page you will find a link to the
Windchill JSDoc.

Third Party Javascript Libraries


While PTC does use some 3rd party JavaScript libraries, all supported
customizations use PTC’s own APIs. It is recommended that customizers use
these supported APIs when possible. These underlying libraries may change
without notice, which may negatively affect any customizations. If it is not
possible to avoid using 3rd party library API’s, it is the customizer’s responsibility
to acquire appropriate development licenses, and assume maintenance
responsibilities for those usages going forward.

242 Customization Guide


For example, although the EXT component library has been used to create
Windchill and is therefore available to you in your customization environment, if
you build any customizations that directly reference EXT apis (found in the EXT
namespace) you will be required to purchase EXT licenses for your
customizations. If you only reference APIs in the PTC namespace you will not
need any EXT license.

Javadoc
The Windchill Javadoc is delivered with the product and can be accessed through
the UI. To locate the documentation, first enable the customization examples and
tools, then browse to the customization navigation and select the tools option. For
more information see Customization Tools Overview on page 404.
Under the API documentation section of the page you will find a link to the
Windchill Javadoc.

Java Beans
There is a set of Java Beans that is part of the framework that carries data like
context and session information. The developer does not need to interact with
most of the beans. See Windchill Client Architecture Common Objects Overview
on page 245 for more information.

Enabling Customization Examples and Tools


To enable the customization examples and tools icon in the Navigator you must
set a site preference.
1. Login as the Site Administrator and navigate to Site ▶ Utilities.

2. In the Utilities List Select the Preference Manager. Expand Client


Customization.

User Interface Technology Overview 243


3. Right click on the Client Customization Preference and select Set Preference
and set the preference to “Yes.” Now you will see the customization icon in
the Navigator.

244 Customization Guide


Windchill Client Architecture Common
Objects Overview
This section provides a basic overview of common Windchill Client Architecture
objects used in the UI.
These objects will be heavily used in customizations but are not likely to be
extended except for NmSimpleOid.

NmCommandBean
NmCommandBean provides Windchill Client Architecture state information to
other Windchill Client Architecture layers. It is the what, where, and how of the
UI. It wraps the request object and adds value by parsing the parameters into
related items.
Once initialized by the request, the NmCommandbean can answer Windchill
Client Architecture related questions. It essentially carries the request and helper
methods to access the jca state information.
Interesting attributes:
• Context: the where compcontext, parentContext, element
context, etc are used to determine what page is displayed and where actions
are launched. (Note that this is becoming obsolete and should be deprecated in
the next release.)
• oids : the objects that actions or pages apply to.
Contains a number of helper APIs:
• getActionOid() : gets the object that is the target of the action.
• getPageOid(): gets object that the page is being displayed in this page.
• getViewingContainer() : gets the container that the page is displayed
in.
See the javadoc for more info api usages.

NmAction
NmAction represents a line from actions.xml which describes a page in
Windchill. It is rendered as all the icons and links that one can click to make
changes to the Windchill system. Each jsp page should be described by an
NmAction in an xml file. The localized attributes of the NmAction can be
found in the action.properties or other rbInfo files.

User Interface Technology Overview 245


NmOid
A Netmarkets version of a WTReference that hides some details of the different
reference types and provides helper apis to aid in caching. Furthermore, it is the
object that understands how to parse any string format from the request that
represents an object in the db.

NmSimpleOid
NmSimpleOid represents a non-persisted business object. It is often to represent
some item that has not been created yet or some object that wraps a persistable
with more information. String parsing of the NmSimpleOid is completely
handled by the code for the relevant table and actions and should be in an
NmObjectUtility. See NmObject Utilities on page 590 for more information.

NmContext
NmContext represents a UI address of a page. (Note that this is becoming
obsolete and should be deprecated in the next release.)
• Component is a jsp page
• Jsp page can include multiple components
• Component address includes addresses of ancestor components
• Context (address) of a component B is “Address 1 - Address B”

Example NmContext string a document residing in a folder on a project’s folders


page:
folder$list$OR:wt.projmgmt.admin.Project2:2343$OR:wt.
folder.SubFolder:7195^VR:wt.doc.WTDocument:18913!*

246 Customization Guide


Note
The $, ^, and !* are reserved separator characters.

User Interface Technology Overview 247


Javascript Functions Overview
This section explains some of the common Windchill Client Architecture
javascript functions.
These functions are located in: <Windchill>\codebase\netmarkets\
javascript\util\main.js

Note
More Windchill Javascript API information is available directly in the
Windchill UI. For more information, see Customization Tools Overview on
page 404.

TableUtils — package
Name Purpose
getTableRows (parentNode) Return array of Nmcontexts for each
row in a table given the outer DIV
DOM node.
getTableRowsByID (tableID Return array of Nmcontexts for each
row in a table given a table id
getTreeRows (parentNode) Return array of Nmcontexts for each
row in a table given the outer DIV
DOM node.
findTableID (node) Given some DOM Element, walk up
the DOM tree to figure out which table
this is in.
findParentTableNodeId (node) Given some DOM Element, walk up
the DOM tree to find the table DOM
Node.
getAddedRows (tableid) Gets the hidden input field that contains
the added rows of a table id. Returns
String that can be tokenized.
getRemovedRows (tableid) Gets the hidden input field that contains
the removed rows of a table id. Returns
String that can be tokenized
getParentTR (node) Walk up the Dom tree finding the first
<tr> tag
removeParentRow (oid, node, tableid) Remove a row from a table/tree
isTableCheckBox (node) returns true/false if the dom NODE is a

248 Customization Guide


Name Purpose
row in the table with the class JCA_
tablerow
@param node - checkbox dom node
deSelectOtherTableRows (table id) Invoked when a checkbox is clicked
and it changes the row css so that it
appears as highlighted.
getFormNodes (node) Get all the form nodes within the given
parent node. If parentNode is
unspecified, the entire document is
searched.
disableRow (tr) Disable all form inputs in the given row
updateHeader (tableid) Updates row Count in Title bar.
getUnformattedTableId (tableid) turns the outer div node id into a
normal table id defined by the jsp tags
table__jca.sometable__TABLE -> jca.
sometable
getFormattedTableId (id) turns a div table id into the simple table
id used as in the jsp tags
table__jca.sometable__TABLE -> jca.
sometable
updateFooterCount (tableid, count, Updates Count of selected rows in
changeValue) footer.
disableSelectAllChBox Disables the select all checbox given a
table id
enableSelectAllChBox enables the select all checbox given a
table id

User Interface Technology Overview 249


TreeHandler
Name Purpose
toggle (…) The expand/Collapse function, Finds
the current state of the row and changes
it to the opposite. This may result in
refreshing the page for legacy trees
otherwise an ajax call is made to get
new rows for the expand action.
collapseFolders (oid, action, list) Will collapse a row or expand the
folder row by changing its icon.
Param alist is a list of tree rows, if null
it will be calculated from the page. It is
faster to not lookup the list of tr nodes
over and over.
Param action - 'c' or 'e' for the action
type

asyncResponseHandler
Name Purpose
handleResponse (responseText, Parses actions from an asynchronous
responseObject) response. Generic high level method
that will delegate to all the types of
responses.
stripText (text, Gets rid of unwanted text from the
divID, response. Substrings out antying not
inbetween the html comment.
skipScriptEval,
Can execute javascript blocks
start, conditionally.
end) Start/end are the html comment strings
to use to find the response in.

250 Customization Guide


rowHandler
Name Purpose
addRows (oidList, Add rows to a table.
table_id, oidList is an array of oids to add as
rows.
tableRows,
params) Tablerows is an array of all current
rows to improve performance of the api
Params is extra params to add to the
ajax request.
removeRowsFromParentTable
removeRows ( rows, table_id, visually_ Remove rows from the table, rows is an
remove ) array of oids.

requestHandler
Name Purpose
handleRequest (table_id, params) Refreshes a table given the params
doRequest (url, options) Make the ajax request for the table.
Used by the above method to change
the url with the options set.

Other Functions in main.js


Name Purpose
getElementsByClassNameAndTag Returns all the children of the
(className, parentElement , tag name) parentElement that match the given
Tagname and contain the className.
Optimized version of
getElementsByClassname so that it
does not have to look at all the items in
the page.
refreshDivTag(id, name, url) Refreshes the contents of a div (via
Ajax) when an element fires its change
event.
getElementHtml(params, divID, Used to create a fade effect on a portion
doAsynch, url, doFade, successFunc, of the html page that is being updated
failFunc, options) via an ajax request.
addRows( list, tableId, refresh, Modifies the hidden form fields of
doAjaxUpdate, preventDuplicates ) tables used in wizards when users
dynamically add rows to said table. Can
cause the row to be added dynamically

User Interface Technology Overview 251


Name Purpose
if the doAjaxUpdate is true.
PJLrefreshOpener() and Refreshes the parent window.
refreshOpenerOnly()
getClipboardItems() Family of methods for getting contents
of the Clipboard as a comma delimited
list.

Wizard.js functions
Name Purpose
handleRequest (table_id, Refreshes a table given the params
params)
doRequest (url, options) Make the ajax request for the table.
Used by the above method to change
the url with the options set.
parseAnonymousParams (startIndex, Add request params to the options
params, result) based on the params list passed in.
getParamString Adds all this form params to the ajax
request including the params passed in.
updateStepImage Updates the wizard step indicator
images for all steps based on the
current state.
updateEmbeddedText Updates the embedded help based on
the current step.
getNextStep Gets the next step id.
setNextStepDirty Sets the next step in the wizard to be
refreshed when displayed.
goBack Make the wizard go back one step
goNext Make the wizard go to the next step
setActiveStep (stepId, wizardAction) Makes a specific step active.
wizardAction is an optional parameter.
It indicates if the user is attempting to
go back or forward in the wizard.
findStepIndex Find the index of a step id
setNextStep Override what the next step id is
setStepDirty Set a step to need a refresh should it
display again
setStepClean Set a step to NOT need a refresh should

252 Customization Guide


Name Purpose
it display again
setStepIncomplete Set a step to need to be vistited again as
it needs more info
setStepComplete Set a step to NOT need to be vistited
again as it does not needs more info
setStepRequired Make a user visit a step before the
wizard can be completed
setStepOptional Make a user able to complete the
wizard WITHOUT visiting the
specified step id
removeStep Remove a step from the list of steps
insertStep Add a new step to the list of steps based
on what has already happened -
dynamic steps
resetOkButton Sets the ok button to be displayed or
not based on the current state.
resetNextBackButton Sets the next/back button to be
displayed or not based on the current
state.
disableOkButton Force the finish and apply buttons to be
disabled
enableOkButton Force the finish and apply buttons to be
enabled
getCurrentStep Gets the current active step id
refreshCurrentStep Refreshes the current wizard step
refreshStep Refreshes the speicified wizard step
getAbsoluteUrl This function takes a url and turns it
into an absolute URL.
goProgress Turns on the progress indicator
stopProgress Turns off the progress indicator
onSubmitMain Finish the wizard by executing it on the
server
handleSubmitResult Handles the response of the wizard
submission, the response is mostly a
form result string object that tells the
browser what to do. Not quite jSON yet
though.

User Interface Technology Overview 253


Name Purpose
onClickValidation (evt, key) To do Ajax validation when an action is
clicked.
The event object.
The key to use in validation code
checkRequired (skipErrorMsg) Grabs every input that is styled as
'required' and checks to make sure it
has a value. If any required fields do
not have values, the field in question is
highlighted and an alert message is
displayed. This function returns a
boolean that is true if the required fields
are entered and false if any required
field is not filled in.
@param skipErrorMsg can be used to
suppress the alert message

254 Customization Guide


Adding Custom Code to all Windchill
Client Architecture Pages
This section explains how to add custom code to all Windchill Client Architecture
pages.

Javascript files
To add any custom javascript to all the pages, you should create a new custom
jsfrag file. The file needs to be deployed in: codebase\netmarkets\
javascript\util\jsfrags
The file can be named custom.jsfrag or any other name that is not already in
use.
To include the file in all pages run the combine command. This will make the js
available in main.js: Windchill/bin>ant -f jsfrag_combine.xml

CSS Files
To add any custom css scripts to all the pages, modify the
netmarkets.presentation.cssFiles property in site.xconf to
have the necessary css files included. You can include multiple css files as a
comma or semicolon separated list in the value. Note that order is important, and
that the files will be loaded after the Windchill style sheets so they will properly
override the default styles.
<Property name=" netmarkets.presentation.cssFiles"
overridable="true"
targetFile="codebase/presentation.properties"
value="mypath/mycss.css;mypath/mycss2.css"/>

Customizing the Theme


It is not recommended to change any of the standard Windchill CSS style sheets.
Instead, insert custom stylesheet files using the as described above. To discover
which styles are defined, a good place to start is the theme file: codebase/
netmarkets/themes/windchill/xtheme-windchill.css

User Interface Technology Overview 255


Maintenance Messaging
The file codebase/netmarkets/jsp/util/begin_custom.jspf can
also be used to add custom messages to the page for system maintenance or mass
communication. For example, place the following code in this file:
<div style="color: sienna; position: absolute; top: 15px; z-index: 1000;
left: 300px; font-size: 18px;">
<h1>This is a test</h1></div>
</div>

You should place any HTML for your message within a div as in this example.
You can then use css to position and style the message as desired.

Color Customizations in the Reference Designator


Differences Column
The values for the reference designator differences column can be displayed with
custom css which gives the customizer the ability to display these values in any
color they want.
1. Use a new or existing custom css file. See CSS Files on page 255 for more
information.
2. Create a custom css for the reference designator differences plus values. The
following example will display the values as green:
span.dsb-reference-designator-diffs-plus-value

{
color: #53bc3c;
}
3. Create a custom css for the reference designator differences minus values. The
following example will display the values as red:
span.dsb-reference-designator-diffs-minus-value

{
color: #FF0000;
}

Customization Points
codebase/netmarkets/jsp/util/begin_custom.jspf

256 Customization Guide


11
MVC Components
MVC Components Overview .................................................................................... 258
MVC Tables ............................................................................................................ 287

This section contains an overview of MVC components as well as where to find


information on MVC tables.

257
MVC Components Overview
This explains and introduces the different pieces of the Windchill Client
Architecture UI Framework.
• MVC on page 258
• Data Sources on page 270
• JCA Components on page 279

MVC
Model–View–Controller (MVC) is a software architecture, currently considered
an architectural pattern used in software engineering. Model represents enterprise
data and the business rules that govern access to and updates of this data.
View renders the model. Controller translates interactions with the view into
actions to be performed by the model.
For web-based clients such as browsers uses Java Server Pages (JSP ) to render
the view, Servlet as the controller, and Enterprise JavaBeans (EJB ) components as
the model.

MVC in Windchill
In Windchill 9.x, for JCA Clients, JSP was serving both as the Controller and
View. In Windchill 10.0, we are introducing a clear separation between Controller
and View for which we are using Spring MVC Framework.
The primary motivation for this move is to enable our components to be both
requested by and rendered to any client technologies. The MVC pattern is a well
understood industry standard approach that allows us to better leverage 3rd-party
technologies and training. Finally, the MVC pattern improves the maintainability
and testability of our implementations.
Having multiple servlets as controllers is going to be difficult to manage and
hence we have adopted the Front Controller pattern approach – a main servlet to
make the control more manageable. DispatcherServlet acts as the Front controller.

Request Handling
The servlet and servlet mapping for the Web container is defined in
<Windchill>\codebase\WEB-INF\web.xml. The below mentioned url
patterns are mapped to Spring DispatcherServlet and hence will be termed
as MVC requests.
<servlet-mapping>
<servlet-name>MVCDispatcher</servlet-name>
<url-pattern>/servlet/WizardServlet/*</url-pattern>
<url-pattern>/servlet/ActionsMenu/*</url-pattern>
<url-pattern>/servlet/RecentList/*</url-pattern>

258 Customization Guide


<url-pattern>/servlet/Navigation/*</url-pattern>
<url-pattern>/servlet/SuggestServlet/*</url-pattern>
<url-pattern>/servlet/TypeBasedIncludeServlet/*</url-pattern>
<url-pattern>/servlet/UIValidationAJAXServlet/*</url-pattern>
<url-pattern>/ptc1/*</url-pattern>
<url-pattern>/app/*</url-pattern>
<url-pattern>/gwt/*</url-pattern><servlet-mapping>
</servlet-mapping>

<servlet>
<description>MVC Dispatcher Servlet for JCA</description>
<servlet-name>MVCDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.
DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

The web container, based on the servlet mapping configured, directs all the MVC
Requests to Spring DispatcherServlet.

Application Context
An application Context represents the set of configuration files that are used to
provide configuration information to the application and is in <Windchill>\
codebase\WEB-INF\MVCDispatcher-servlet.xml.

MVC Components 259


• Imports all the Spring configuration xml files that reside at <Windchill>\
codebase\config\mvc\ folder. Any custom configurations should go in
<Windchill>\codebase\config\mvc\custom.xml.
• Defines the handler mapping by loading the mappings specified in the
properties files at <Windchill>\codebase\config\mvc\. Any
custom handler mapping should go in <Windchill>\codebase\
config\mvc\custom.properties.
When the web container is initialized, Spring loads the application context and
hence to get effect of any configuration changes, you need to restart the server.

Request Handling by Spring


The client requests for a resource in the Web application. As seen in earlier
section, the web container directs all MVC request to the Spring
DispatcherServlet. The Spring Front controller will intercept the request and will
find the appropriate handler based on the handler mapping (configured in Spring
configuration files). In other words the handler mapping is used to map a request
from the client to the handler. With the help of Handler Adapter, the Spring Front
controller will dispatch the request to the handler.

In Windchill we use two handler mappings

260 Customization Guide


• DefaultAnnotationHandlerMapping, which maps handlers based on
HTTP paths expressed through the RequestMapping annotation at the type or
method level.
• SimpleUrlHandlerMapping which maps from the URLs to request
handler beans. Mappings are specified in the properties files at
<Windchill>\codebase\config\mvc\
e.g /servlet/WizardServlet* = wizardController
Once the handler is found, it will find the suitable handler adapter from the
configured adapters. In Windchill we use three types of handler adapters
• SimpleControllerHandlerAdapter, an adapter to use the plain
Controller
• AnnotationMethodHandlerAdapter which maps handler methods
based on HTTP paths, HTTP methods and request parameters expressed
through the RequestMapping annotation.
• GwtHandlerAdapter, an adapter to handle GWT client requests (handler
is RemoteServiceServlet)

Handlers
They are beans that can handle a request. An OOTB handler has been provided to
handle requests to build components - com.ptc.mvc.components.
ComponentController. It prepares a ModelAndView
(org.springframework.web.servlet.ModelAndView) which can be
handled by the DispatcherServlet
To build a component, we need its description and the data to be presented. We
have introduced the concept of builders, which will provide these artifacts.
Component description will be represented via ComponentConfig and a
ComponentConfigBuilder provides them. Component data will be
represented via ComponentData and a ComponentDataBuilder provide
them.
ComponentConfig and ComponentData together define the component
information to be shown in the UI and will be represented by
ComponentDefintion. It is the Model in MVC paradigm, where as the
ComponentController is the Controller.

MVC Components 261


How find a builder?
A typical MVC resource to build a component will be ptc1/<handler_
key>/<componentId> where
• handler_key is used to map the request to a handler.
• componentId represent the component to be build.
ComponentController is injected with a ComponentBuilderResolver,
which will find the respective builders for the given componentId.

Internal artifacts of ComponentController


Few notable internals of a ComponentController
• ComponentBuilderResolver, finds the
ComponentConfigBuilder and ComponentDataBuilder for the
componentId specified in the resource
• defaultMappings defines the default views for different
ComponentConfig.
• ComponentParamsFactory create ComponentParams from request
and response that will be made available in the builders.

262 Customization Guide


The builders provide ComponentConfig and ComponentData, from which
the Model, ComponentDefinition is made. ModelAndView is populated
with ComponentDefinition and the view information comes either from the
ComponentConfig or from the defaultMapping provided.
The artifacts that are in green are Windchill Client Architecture (e.g JCA) specific
ones. The black ones are the ones provided by the component owners.

MVC Components
The components that extend/implement ComponentConfig interface are MVC
components. Some of them are :
• TableConfig
• AttributesTableConfig
• TreeConfig
• AttributePanelConfig
• InfoConfig
• ColumnConfig
• PropertyConfig
• PropertyPanelConfig

MVC Builders
There are two types of Builders. The one that provides ComponentConfig are
called ComponentConfigBuilder and the one that provides the
ComponentData are called ComponentDataBuilder.

MVC Components 263


• ComponentConfigBuilder :beans that implement com.ptc.mvc.components.
ComponentConfigBuilder
• ComponentDataBuilder :beans that implement any of the following interface
○ com.ptc.mvc.components.ComponentDataBuilder
○ com.ptc.mvc.components.ComponentDataBuilderAsync
○ com.ptc.mvc.components.TreeDataBuilderAsync

Specifying the componentid


Typically the component ID that a builder maps to is declared using the
@ComponentBuilder annotation in your builder class declaration.
@ComponentBuilder(value = “{<componetId1>, <componetId2>}”)
public class MyBuilder extends … {}
If you wish to implement your config and data builders in separate classes, then
you must supply an additional ComponentBuilderType parameter to the
@ComponentBuilder annotation.
For config builders, this looks like:
@ComponentBuilder(value=“<componetId>", type=ComponentBuilderType.CONFIG_ONLY)
public class MyConfigBuilder implements ComponentConfigBuilder …. {}

For data builders, this looks like:


@ComponentBuilder(value=“<componetId>", type=ComponentBuilderType.DATA_ONLY)
public class MyDataBuilder implements ComponentDataBuilder… {}

Note that framework will throw an error if two builders will have the same
component id. Spring initialization will fail in the MethodServer start up
phase. If you need to override an OOTB builder, please use
OverrideComponentBuilder annotation.
@ComponentBuilder(value="{compId1, compId2, compId3}")
public class OOTBBuilder1 extends …… {
}
@OverrideComponentBuilder
public class MyCustomBuilder1 extends …… {
}

• MyCustomBuilder1 will be mapped to compId1, compId2, compId3


@ComponentBuilder(value="{compIdA, compIdB, compIdC}")
public class OOTBBuilder2 extends ……{
}
@ComponentBuilder(value="{compIdA, compIdC}")
@OverrideComponentBuilder
public class MyCustomBuilder2 extends ……{
}
@ComponentBuilder(value="{compIdB}")
@OverrideComponentBuilder
public class MyCustomBuilder3 extends ……{

264 Customization Guide


}

• MyCustomBuilder2 will be mapped to compIdA, compIdC


• MyCustomBuilder3 will be mapped to compIdB

TypeBased
To build certain components, you may need the Windchill Type of the context
object playing a role in finding the appropriate builder. For example you have an
info page and you want to populate the content based on the Windchill Type. For
these scenarios, we have introduced an annotation “TypeBased” that can be
used in the builder, to attach the builder to a specific Windchill Type. This works
with ComponentBuilder.
@ComponentBuilder("compIdA")
@TypeBased(value="{WTPart, WTDocument}")
public class OOTBBuilder1 extends ……{
}
@ComponentBuilder("compIdA")
@TypeBased(“myPart”)
public class OOTBBuilder2 extends ……{
}

• If the context object’s Windchill Type is WTPart and the componentId =


“compIdA”, the best match builder for that component is OOTBBuilder1
• If the context object’s Windchill Type is a sub-type of WTPart(myPart)
and the componentId = “compIdA”, the best match builder for that
component is OOTBBuilder2
• If the context object’s Windchill Type is a sub-type of
WTDocument(myDoc) and the componentId = “compIdA”, the best
match builder for that component is OOTBBuilder1
While resolving to find the suitable builder, the context object’s Windchill type
hierarchy is respected. The attribute value can take
• Internal Name of the Windchill Type
• If the representation has domain name of the exchange container involved,
then can use ${internet_domain_name} for its representation. e.g
${internet_domain_name}.DynamicDocument

Registering Builders
Once the builders are created, you need to let Spring infrastructure know about it.
Registration can be done either via explicit configuration or by automated
scanning. Automated scanning is the preferred approach for typical use cases.
1. Automated scanning: You can configure to automatically pick up all builders
within a certain package hierarchy. To do this, add the <mvc:builder-

MVC Components 265


scan/> configuration element to <Windchill>\codebase\config\
mvc\custom.xml.
<beans xmlns="xmlns:mvc="http://www.ptc.com/schema/mvc"
xsi:schemaLocation="http://www.ptc.com/schema/mvc
http://www.ptc.com/schema/mvc/mvc-10.0.xsd">
<mvc:builder-scan base-package="com.ptc.windchill.enterprise.
preference.mvc.builders"/>
</beans>

The builder-scan implementation scans the entire classpath, so you should take
care to be specific with the package name you declare if using scanning. (don’t
scan com.ptc.* for example). In addition, this means that classes that are
outside your interest, but that are in the classpath and match the package
hierarchy, will also get scanned. From a performance standpoint
(MethodServer startup) each scan adds up time. You are requested to take
advantage of the OOTB scan provided on “com.ptc.mvc.builders” base
package. This means that all the builders that you author should be under com.
ptc.mvc.builders package. If you are not using the OOTB scan, the rule of
thumb is to use the scan if there are more than 10 builders available in the
package.
2. Explicit configuration : To do this, simply add a bean declaration for the
builder to the <Windchill>\codebase\config\mvc\custom.xml
e.g <bean class=" my.builder.class.name "/>
You are encouraged not to specify the bean name while declaring the bean and
use @ComponentBuilder annotation in the builder for proper registration
of it in the Spring bean factory.

Abstract Builders

266 Customization Guide


Creating Multiple Components
There will be requirement to build multiple components using the same builder
and can have two use cases.

Use Case 1
The components are made from an already existing components/builders. For
example if there is already a component with id="test.ComponentA" and
another with id="test.ComponentB" and we want to get both the
components in a page.
@ComponentBuilder(value="test.multi.AB", type=ComponentBuilderType.CONFIG_ONLY)
public class MultiComponentBuilder extends AbstractComponentConfigBuilder{
@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
MultiComponentConfig configs = new MultiComponentConfig();
configs.addNestedComponent("test.ComponentA");
//you are specifying the componentId
configs.addNestedComponent("test.ComponentB");
configs.setView("/test/multi.jsp");
return config ;
}
}

MVC Components 267


• There is no need for ComponentDataBuilder as this
multiComponent by itself doesn't have any data.
• You need to specify a view jsp for this ComponentConfig as no default
view can handle that.
• When you use addNestedComponent to provide a componentId, make
sure that componentIds are to be handled by the same controller instance. In
other words, you can have only non-type based or type based components
combined together with this approach.

Use Case 2
Here the components need to be defined and they exist together. E.g. you want
property panel coming with a table.
• There is a need for ComponentDataBuilder.
• Infrastructure invokes the buildComponentData for each
ComponentConfig available in the MultiComponentConfig. It’s
invoked in the same order it has been put in the MultiComponentConfig.
• You can access the rawData for the ComponentConfig that has already
been processed from the ComponentParams supplying the componentId
• You need to specify a view jsp for this ComponentConfig as no default
view can handle that.
@ComponentBuilder("test.array.PQ")
public class ComponentArrayBuilder extends AbstractComponentBuilder {

@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
MultiComponentConfig configs = new MultiComponentConfig();

TableConfig table1 = createTable1();


//create a table with id = component1
......
TableConfig table2 = createTable2();
//create a table with id = component2
......
configs.addComponent(table1);
//add the components
configs.addComponent(table2);

configs.setView("/test/array.jsp");
return configs ;
}

@Override
public Object buildComponentData(ComponentConfig config,

268 Customization Guide


ComponentParams params) throws WTException {

if ("component1".equals(config.getId())) {
//return data for table with id= component1
} else {
//return data for table with id= component2
}
}
}

MVC Components 269


Data Sources
It’s an infrastructure for holding the data and streaming the data to the client. It
will enable faster page loads as well as the potential for asynchronous server
processing of results. The basic strategy is to return large result sets to clients in
chunks, along with an ID that can be used to get more chunks. From the UI
perspective it looks like the data is streaming into the client. This approach is
different from DB paging, where we persist the big result set in the database. With
DataSources, the result lives in memory only for as long as it takes the client to
request it in chunks. In addition, there will be support for the server to add chunks
to the datasource in a separate thread, so one can request the datasource and spin
off a thread to work on getting data for it, without the client waiting.

Some of the benefits of using DataSources are


• Display data without overly consuming client- and server-side resources.
• Allow users to interact with the page while data is loading.
• Improve perceived performance.
• Provide messaging and feedback while data is loading.

Modes of Data Sources


Synchronous: This is useful if you have all the data that need to be send to client
with you already and want to put the data in DataSource so that it can be send to
the clients in chunks. The DataSource session takes in a list of objects that you
want sent to the client and returns you a DataChunk object, which contains the
first chunk of data to be send to the client. If the List of data could fit in one
chunk, then the session doesn't even create a DataSource, it just returns you the

270 Customization Guide


chunk. Otherwise a DataSource is created with the data, which can be polled later
for additional chunks. The DataSource will be closed so that no more data can be
added.
Asynchronous: In this case, you haven't got your data yet. You want to submit a
task to get the data in a background thread and have the data returned to the client
later. We leverage the capabilities of Executor framework provided by Java.(for
more details refer JavaDoc of Executor) To create an asynchronous DataSource,
the DataSource session takes a DataSourceTask which will be run by in a
background thread sometime in the future. It returns a DataSourceFuture object,
so that you have a way to access the DataSource information.
Disabled: Not DataSource enabled

DataSources with Data Acquisition


Synchronous data sources with Synchronous data acquisition: Uses synchronous
data acquisition (all data comes from the database in one chunk) and streams
chunks to the client. No blank chunk is sent, so the component is not rendered
until the first data chunk is received. Currently we don’t support this for Tree
components.

Asynchronous data sources with Synchronous data acquisition: Uses synchronous


data acquisition (all data comes from the database in one chunk) and streams
chunks to the client. The first chunk sent to the client contains no table data but
enables the table to be rendered before a full data chunk is available. This gives
the user control of the table and some of its actions sooner. The data chunks then
stream in behind the blank chunk as they are processed.

MVC Components 271


Asynchronous data sources with Asynchronous data acquisition: Uses
asynchronous data acquisition (data is obtained from the database in chunks) and
streams chunks to the client. The first chunk sent to the client contains no table
data but enables the table to be rendered before a full data chunk is available. This
gives the user control of the table and some of its actions sooner. The data chunks
then stream in behind the blank chunk as they are processed. In this case, we have
the potential to see chunks of data rendered in the client while data is still being
acquired from the database.

There is change in loading behavior in case of Trees. In Windchill 9.x, we had


followed the depth first loading approach where by each node was expanded till
its leaf node, before starting to expand it sibling. In Windchill 10, with
DataSource, we have moved the Breadth first loading approach. Nodes are loaded
per level.

272 Customization Guide


Monitoring Data Sources
DataSourceMonitor MBean can be used to monitor and configure various
properties. To find the monitor
• From windchill shell, run “jconsole”
• Select MethodServerMain
• Select MBeans tab
• MBean located at com.ptc>WebAppContexts>${WEBAPP_NAME}
>Monitors>DataSourceMonitor

MVC Components 273


MBean monitoring
Parameter Description
ActiveDataSourceCount The number of datasources that
currently are active in all user sessions
TotalDataSourcesCreated The total number of DataSources that
have been created for all user sessions
TotalDataSourcesDestroyed The total number of DataSources that
have been destroyed for all user
sessions

MBean operations
Parameter Description
cancelLongRunningDataSources Cancel any datasources that have been
running for at least the given amount of
milliseconds, in all user sessions. This
will cancel both active and inactive
DataSources

274 Customization Guide


MBean configuration
Parameter Description
AllEmptyPollingTimeout The timeout in milliseconds to wait for
data chunks when the client polls for
chunks and none of the ids it asked for
have chunks available
ChunkBlockingLimit Controls the number of chunks a
DataSource can hold before it blocks
the addition of more items until
something polls it or it times out. The
actual number of items this resolves to
is
ChunkBlockingLimit*MaxChunkSize.
DataSourceTaskPoolKeepAliveTime The amount of time in milliseconds to
keep idle threads alive in the
DataSource task pool
DataSourceTaskPoolSize The maximum number of threads
allowed in the DataSource task pool
DataSourceTimeout The amount of time in milliseconds to
keep idle DataSources alive
FeedbackBlockingLimit The number of feedback items a
DataSource can hold before it blocks
the addition of more feedback until
something polls it or it times out
InitialChunkPollingTimeout The amount of time in milliseconds to
wait to for the initial chunk of data to
be available, when using asynchronous
datasources. This enables components
to try and display some data in the table
on initial rendering if possible
MaxPollSize The maximum size of data that is
returned by a DataSource for each poll.
PreferredMinPollSize The minimum size of data for a poll.
This is used when polling asynchronous
datasources, to allow the server to
decide whether to wait for more data or
not
PreferredSerializationSize The preferred size in bytes of the total
response to a polling request. If the
initial chunks do not reach this size
limit, then additional chunks are added

MVC Components 275


Parameter Description
until they are over the limit. This
property is not currently used.
ResultLimit The total number of items that can be
added to a DataSource before it fails.
SomeEmptyPollingTimeout The timeout in milliseconds to wait for
data chunks when the client polls for
chunks and some of the ids it asked for
have chunks available, but not all of
them
TreeChildNodeFetchTimeout The timeout in miliseconds to wait for
child data for the tree. The OOTB value
is 180000 ms and can be increased to
avoid time out errors.

Persisting the updated MBean Configuration values


It is possible to persist the updated configuration values of
"DataSourceMonotor" MBean in the XML.
• Open Jconsole and change any of the configurable value of
"DataSourceMonitor" MBean.
• Click on the "DataSourceMonitor" MBean. From the MBeanInfo, copy
the "ObjectName".

276 Customization Guide


• Open the Loader MBean com.ptc > WebAppContexts >${WEBAPP_NAME}
• Got to its "Operation invocation" tab.
• Paste the "ObjectName" as a parameter for
"addInjectionTargetMBean" method and click on the
"addInjectionTargetMBean" button.

MVC Components 277


• Now click the "Save" button. The changed value of the
"DataSourceMonitor" MBean will get persisted in the <WTHome>/
codebase/WEB-INF/wtWebAppMBeans.xml file. On any subsequent
server restart, the last saved value will show up the in
"DataSourceMonitor" MBean.
• Configurable properties can be reverted back to the default values by invoking
"removeInjectionTargetMBean" method with the "ObjectName",
followed by a “save” operation.

278 Customization Guide


JCA Components
These are few implementation of ComponentConfig :
• JcaTableConfig
• JcaAttributesTableConfig
• JcaTreeConfig
• JcaAttributePanelConfig
• JcaColumnConfig
• JcaInfoConfig
• JcaPropertyConfig
• JcaPropertyPanelConfig

JCA Configurations for MVC


All the JCA specific Spring configurations are available in <Windchill>\
codebase\config\mvc\jca-mvc.xml. The below snippet shows the
configuration of url handler mapping. All the url pattern ptc1/comp/* are
mapped to a bean with id componentController and the pattern ptc1/tcomp/*
are mapped to a bean with id typeBasedComponentController.
<bean id="abstractComponentHandlerMapping" abstract="true"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
-----
</bean>
<bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping">
<property name="mappings" ref="componentHandlerMappings" />
-----
</bean>
<bean id="componentHandlerMappings"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties"><props>
<prop key="/comp/**">componentController</prop>
<prop key="/tcomp/**">typeBasedComponentController</prop>
</props></property>
</bean>
Below snippet shows the definition of the bean with componentController id.
• jcaComponentBuilderResolver is injected as
theComponentBuilderResolver
• defaultViewMappings property is defined to map the default views
<bean id="componentController"
class="com.ptc.mvc.components.ComponentController">
<property name="componentBuilderResolver"
ref="jcaComponentBuilderResolver" />
<property name="defaultViewMappings">
<map>

MVC Components 279


<entry key="com.ptc.mvc.components.TreeConfig"
value="/components/tree.jsp" />
<entry key="com.ptc.mvc.components.TableConfig"
value="/components/table.jsp" />
<entry key="com.ptc.mvc.components.AttributesTableConfig“
value="/components/table.jsp" />
<entry key="com.ptc.mvc.components.AttributePanelConfig”
value="/components/attributePanel.jsp" />
</map>
</property>
-----------
</bean>
Below snippet shows the definition of the bean with
typeBasedComponentController id.
• typeBasedComponentBuilderResolver is injected as the
ComponentBuilderResolver. It respects the Windchill Type of the
context object also while finding the best matched builder.
<bean id="typeBasedComponentController"
class="com.ptc.mvc.components.ComponentController“
parent="componentController“>
<property name="componentBuilderResolver"
ref="typeBasedComponentBuilderResolver" />
</bean>
The default handler specified will handle all the MVC url patterns that doesn’t
have a mapping.
<bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping">
<property name="defaultHandler" ref="netmarketsController" />
-----
</bean>
<bean id="netmarketsController"
class="com.ptc.jca.mvc.controllers.LegacyController" />

ComponentConfigFactory
Builders which are ComponentConfigFactoryAware will be injected with
a ComponentConfigFactory. ComponentConfigFactory provides
instances of different implementations of ComponentConfig (eg table, tree
etc). In JCA, the injection happens in the bean post processor and is configured in
<Windchill>\codebase\config\mvc\jca-mvc.xml.
<bean class="com.ptc.mvc.components.support.ComponentBuilderBeanPostProcessor">
.....
<property name="componentConfigFactory" ref="jcaComponentConfigFactory" />
<property name="infoComponentConfigFactory">
......
</property>
<property name="typedAttrLayOutFactory">
<bean class="com.ptc.jca.mvc.components.JcaTypedAttrLayOutFactory" />

280 Customization Guide


</property>
</bean>
<bean name="jcaComponentConfigFactory"
class="com.ptc.jca.mvc.components.JcaComponentConfigFactory"
factory-method="getInstance" />

JCA DataBuilders

ComponentDataConvertor
<bean id="jcaComponentDataConverter"
class="com.ptc.jca.mvc.components.JcaComponentDataConverter" />
<bean id="jcaComponentDataBuilder"
class="com.ptc.jca.mvc.components.DefaultJcaComponentDataBuilder"
scope="prototype">
<property name="componentDataConverter"
ref="jcaComponentDataConverter" />
</bean>
<bean id="jcaComponentBuilderResolver“
class="com.ptc.jca.mvc.components.JcaComponentBuilderResolver">
......
<lookup-method name="createJcaDataBuilder"
bean="jcaComponentDataBuilder" />
</bean>
The data that is available from the ComponentDataBuilder need to be
processed so that it can be consumed by JCA. Running the data thorough the
dataUtilities happen in this stage. JcaComponentDataConverter does that
and is injected into the jcaComponentBuilderResolver.

MVC Components 281


ComponentBuilder Resolver
• If the DataBuilder specified is an instance of
ConvertingComponentDataBuilder,
JcaComponentBuilderResolver uses that as the
ComponentDataBuilder.
• If the DataBuilder specified is an instance of ComponentDataBuilder,
JcaComponentBuilderResolver uses that as the internal builder for the
DefaultJcaComponentDataBuilder.

Generate MVC URLs


There are two types of JCA MVC urls.
• Non TypeBased JCA MVC url : Here the context object doesn’t participate in
the builder resolution process.
• TypeBased JCA MVC url : Here the context object’s type participate in the
builder resolution process.
This is generated using action definition
<action>
<component name="myCompId" ……/>
</action>
<action>
<component name="myCompId" " typeBased="true" ……/>
</action>
e.g
<action name="CustEx_mvc_table">
<component name="carambola.mvc.table" windowType="page" />
</action>

282 Customization Guide


<action name="primaryAttributes" resourceBundle="com.ptc.core.ui.navigationRB">
<component name="primaryAttributes" typeBased="true" windowType="page"/>
---
</action>
<Windchill>/codebase/ WEB-INF/tlds/mvc.tld has helper
functions that can be used
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%>
---
<jsp:include page="${mvc:getComponentURL('part.report.multiLevelBOM')}" />
-----

JCA Components with DataSources

Table Size Limit


The maximum number of rows displayed in a table is driven by this preference
which has a USER level visibility. It will be applicable to all the JCA tables in the
system. Currently the OOTB default value is 2,000 rows and you can vary it based
on client hardware and browser type.

For trees, the limit is enforced but can be overridden by the end users. Once the
tree reaches the size limit, collapse of any node will remove its children from the
client, to free some resource in the client. This will happen till the number of
nodes in the client comes below the size limit.

MVC Components 283


Action Handling
Actions can be broadly divided into three groups.
These actions can be performed once your objects are loaded.
• Group 1 – Actions which act only on loaded data
○ Row-level and multi-select actions
○ Select all, Ctrl/Shift select, Clear all
○ View selected objects only
• Group 2 – Actions which act on the entire data set
These actions can be performed anytime (If incomplete data set, goes to the
server to get all the data)
○ Switching table views
○ Search in table
○ Export list
• Group 3 – Actions which apply to the table itself
These actions can be performed anytime
○ Create actions
○ Cancel data loading
○ Save table view

284 Customization Guide


Sorting
Sorting is a special action and with DataSource, depends on the data in the client.
• If complete data set
○ Sorting happen in the client
• If data still loading
○ Sorting happen on the data already in the client
○ Insert remaining polling rows into the client in sorted order
• If results limit was reached
○ Sorting happen in the client
○ Only the rows that are in the client are sorted (not the complete data set)
• Version column is an exception, which makes a server trip to do the sorting,
but only on the data set available in the client.

Tips

Enabling Spring Logging


Please add the following entry in <Windchill>\codebase\WEB-INF\
log4jMethodServer.properties and restart the server.
log4j.logger.org.springframework=DEBUG

Accessing Localized Messages


ResourceBundleClientMessageSource can be used to get the localized messages.
String resourceBundle = "com.ptc.test.TestResource";
ClientMessageSource messageSource =
new ResourceBundleClientMessageSource(resourceBundle);
String message = messageSource.getMessage(TestResource.TEST);

Entry in the TestResource file

@RBEntry("Test Message")
public static final String TEST = "test";
If your builder extends OOTB abstract builders, take advantage of its api
AbstractComponentConfigBuilder.getMessageSource(String resourceBundle)
AbstractComponentDataBuilder.getMessageSource(String resourceBundle)
AbstractInfoConfigBuilder.getMessageSource(String resourceBundle)

MVC Components 285


Storing View Components
All the view jsps should be placed under <Windchill>\WEB-INF\jsp and
the value you specify while specifying it should be relative to <Windchill>\
WEB-INF\jsp.
table.setView("/carambola/carambolaMVCExampleTable.jsp");

Requesting the Nm*Bean in JCA Component Builders


NmHelperBean helper = ((JcaComponentParams) params).getHelperBean();
NmCommandBean nmCommandBean = helper.getNmCommandBean();
HttpServletRequest request = nmCommandBean.getRequest();

Thread Safety of Builders


By default the builders follow the thread safety paradigm of servlets (Singleton
scope), meaning that instance variables in your builders must be thread-safe.
Communication between your config and data builder APIs can be done through
either the config object itself, or via ComponentParams.
public class TestComponentBuilder extends AbstractComponentBuilder{
@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
Object myObject;
//add information that you want to pass to data builder
params.setAttribute("myKey", myObject);
-----
}
@Override
public Object buildComponentData(ComponentConfig config,
ComponentParams params)
throws WTException {
//get the information that was put in config builder
Object myObject = params.getAttribute("myKey");
-----
}
}

286 Customization Guide


MVC Tables
MVC Tables are discussed in Constructing and Rendering a Table Using the JSP
Framework on page 606.

MVC Components 287


12
Customizing HTML Clients Using
the Windchill JSP Framework
Customizing Generic Aspects of JSP Pages.............................................................. 290
Bread Crumbs Component....................................................................................... 299
Client Tabs.............................................................................................................. 311
Checkin/Checkout ................................................................................................... 325
Component Access Control...................................................................................... 330
Attachments............................................................................................................ 337
Attribute Panels....................................................................................................... 348
Customizing Access Control For Packages ............................................................... 400
Customization Tools Overview.................................................................................. 404
Adding Validation Logic for Actions and Properties..................................................... 442
Split Pane / Two Pane.............................................................................................. 463
Defining Layouts in a Type Load File ........................................................................ 474
Configuring the Drag and Drop Zone......................................................................... 478

This chapter explains and gives some basic overview of the Windchill Client
Architecture UI Framework.
Before reading this chapter, you should be familiar with Java, JavaServer Pages
(JSP), JavaServer Pages Standard Tag Library (JSTL), and Expression Language
(EL).

289
Customizing Generic Aspects of JSP
Pages
This section contains the following topics:
• Customizing the UI with Ajax on page 291

290 Customization Guide


Customizing the UI with Ajax

Objective
This section will describe how to dynamically update a portion of a Windchill
page by:
1. Using the partial page refresh capabilities built into the Windchill action and
form processing frame work
or
2. Making an Ajax call to the Method Server directly from your JavaScript code.

Scenario 1
A UI component on your page executes an action. When the action completes,
you would like to update a portion of the launch page to reflect the results of an
action.
• Example: A user launches a wizard to create a new part from the folder
browser of a product. When the user clicks OK you send the form to the server
and create the part. After doing so, you would like to add a row to the folder
browser table that displays the part just created.
• Example: A user clicks a menu item in a product folder browser to delete a
document. The menu item action calls a command to delete the object from
the database. When the command completes, you would like to delete the row
for that object from the folder browser table.
• Solution: Use the partial page refresh capabilities built into the Windchill
action and form/command processing framework

Scenario 2
You would like to refresh an inline element of the page when some event occurs
• Example: You have a page that displays time values in a default time zone. It
also has a button that allows the user to change the time zone. When the user
changes the time zone, you want to redisplay the time values accordingly.
• Solution: Add an onChange event handler for the time zone button that calls
the requestHandler.doRequest() JavaScript function to recompute
the time display value.

Background
To make the Windchill product faster and more scalable, it is necessary to use
some Ajax based operations to cut down on the refresh times of pages. All actions
should be Ajax based where possible. The only actions that should not be Ajax
based are those that require most of the page to be updated.

Customizing HTML Clients Using the Windchill JSP Framework 291


Solution
Specify some Ajax based configuration and code in the action to allow the Ajax
refresh to work.

Solution Elements
Element Type Description
<your actions>.xml XML XML file that defines menu, toolbar,
wizard, and other actions in the
Windchill action framework
<your>formProcessor.java Java A processor that performs operations
based on user data submitted in a
wizard
<your wizard step>.jsp Jsp Jsp to partially refresh in a wizard

FormResult Java A class used to communicate results


from a form processor back to the
framework.
DynamicRefreshInfo Java A class that provides information
about the type of partial refresh that
should be done.
The information included is:
• Oid : the oid that was just created/
updated/deleted. (the new oid in
the case of update)
• locationOid : the oid of the parent
location where the object was just
created/deleted in a tree, or the oid
of the original in the case of
update, or just null otherwise
• action : add, update or delete. Use
the NmCommandBean constants:
DYNAMIC_ADD, DYNAMIC_
UPD, DYNAMIC_DELETE
DynamicNmContextRefre- Java Tree specific specialization of the
shInfo DynamicRefreshInfo for handling tree
paths.

292 Customization Guide


Refresh a row in a table
In the class <your>formProcessor.java, return some dynamic refresh Info
in the FormResult:
DynamicRefreshInfo di = new DynamicRefreshInfo(newOid,oid,NmCommandBean.DYNAMIC_UPD) ;
result.addDynamicRefreshInfo(di);
return result;

Note that rows can be added and removed from the table by switching the flag on
the refreshInfo to be NmCommandBean.DYNAMIC_ADD or DYNAMIC_
DELETE respectively.

Special Tree Refresh Instructions


The second OID or context object passed to the tree refreshInfo is specified
to be the parent row. So in the case of adding a row to a tree, it is necessary to
specify which parent folder to show the new item under.

Refresh the whole table


Add a component specific onAfterAction event listener for this action to
make the appropriate call to refresh a certain part of the window such as
PTC.navigation.reload(). One example in the product is the
onAfterAction listener on the miniNavigator which refreshes the whole
miniNavigator component for many actions:
PTC.miniNavigator.onAfterAction.

Making an Ajax Call in Windchill


You can make your own Ajax request to the server for data whenever the
techniques described above do not meet your needs.
Element Type Description
requestHandler.doRequest Javscript A Javascript “class” with
methods for making Ajax
requests
getElementHtml Javascript Javascript function that
can update part of the
page. Uses the
requestHandler to fetch
the new html from the
server.

Customizing HTML Clients Using the Windchill JSP Framework 293


Procedure – Making an Ajax Call
To make Ajax calls in Windchill, use the requestHandler.doRequest()
JavaScript method. You provide this method with the URL to call on the server
and other optional parameters, if desired. It returns a response, which is a
JavaScript XMLHttpRequest object.
The following example shows how this method is used in Windchill to reset a
hidden field in the DOM called “itemTypeInstanceId” when the user
changes the value in the object type picker of an object creation wizard.
<script>
.
.
.
var params = ‘pickerVal=’ + elementVal; // elementVal is the new value
of the type picker
var options = {
asynchronous: false,
parameters: params
};
var url = “netmarkets/jsp/components/resetItemTypeInstanceId.jsp”;
var response = requestHandler.doRequest(url, options);
var newTypeInstanceId = response.responseText;
element = document.getElementById(currentObjectHandle +
“itemTypeInstanceId”);
element.value = newTypeInstanceId;
.
.
.
</script>
In this case, the “pickerVal” parameter is passed to the jsp in the request
parameters. The jsp makes a call to a server method to compute a new
TypeInstanceIdentifier for the object and passes it back in the response:
<%
String pickerChoice = request.getParameter("pickerVal");
String typeInstanceIdentifier =
createBean.getNewTypeInstanceIdStringForNewItem(pickerChoice);
out.clearBuffer();
out.write(tiid);
out.flush();
%>

By default, doRequest() will make an asynchronous request so that page


processing is not blocked while waiting for a response. If you want the request to
be synchronous you must set asynchronous to false in the options passed to the
method, as shown above.

294 Customization Guide


If the request is to be asynchronous, you will need to provide a JavaScript
function to call when the response is received successfully in the options
parameter to doRequest(). For example:
var options={
asynchronous: true,
parameters: 'oid=' + oid,
onSuccess: function(response) {
var response = response.responseText;
var json = response.evalJSON();
var locationValue = json.locationValue;
var folderOid = json.folderOid;
setFolder(window, locationValue, folderOid);
}
};

In the example above, the jsp that is invoked calls a Java tag that writes a JSON
object to the response.
<req:getFolderAndContactByOidTag oidString="${param.oid}" />
Rather than define the onSuccess function inline, you can just specify the name
of a function to be called:
onSuccess: handleResponse,

In addition to an onSuccess callback, you can optionally specify a


onFailure callback function. If you do not specify an onFailure callback,
the error response will just be logged to the JavaScript console.

Procedure - Batching Ajax Requests


If you have to make many Ajax requests to the same URL, you can batch them
using a JavaScript BatchRequest object to reduce network traffic. When you
create a BatchRequest object, you pass it a configuration object telling it the
maximum number of requests to send in one batch request, the URL to call to
process the requests, and the callback methods for success or failure. You then add
requests to the BatchRequest object. When either the maximum batch size is
reached or 500 milliseconds has elapsed, the batch request will automatically be
sent asynchronously to the server. In the meantime, you can continue adding
requests to the BatchRequest object.
The BatchRequest object will exist for the life of the page in which it is
invoked. When the user navigates away from the current page, the
BatchRequest will be killed and any unprocessed requests will be deleted.
Below is an example of how to create a BatchRequest in JavaScript. See
numericJSRenderer.jsfrag for the complete method.
try {
if(!jsca.columns.numericRenderer.batchRequests) {
jsca.columns.numericRenderer.batchRequests = new PTC.jca.
batch.BatchRequest({

Customizing HTML Clients Using the Windchill JSP Framework 295


url: getBaseHref() + "ptc1/numeric/",
maxBatchSize: 50,
successCallback: function(response) {
var result = PTC.decode(response.responseText);
for (var i=0,length=result.length; i < length; i++) {
$(jsca.columns.numericRenderer.uniqueIdPrefix +
result[i].uniqueId).innerHTML =
result[i].displayValue;
}
},
failureCallback: function(response) {
jsca.columns.numericRenderer.log.error
("ERROR in jsca.columns.numericRenderer()
getting numeric component data for displaying.");
}
});
}
} catch(e) {
// Handle error that could be thrown when creating BatchRequest
}
Once the request is created, you call its addRequest() method to add requests
to it, passing it the parameters you would send to the
requestHandler.doRequest() method.
jsca.columns.numericRenderer.batchRequests.addRequest({
type : data.type,
externalForm : data.rawValue,
isPercent : data.isPct,
isCurrency : data.isCurrency,
uniqueId : uniqueId
});

In this example, the batched requests are sent to a servlet engine controller class
called “NumericController”. The individual requests provide information
about a number value that needs to be displayed on the page. The controller loops
through the individual requests, calls a Java class to create a localized display
value for the number, and returns a JSONArray of JSONObjects, each of which
contains a display value and a unique id corresponding to the id of a HTML div
tag on the page. The success callback function replaces the contents of the div tags
with the display values.
If you use a controller class to process the batch request, it should be annotated
with the Spring @Controller and @RequestMapping annotations. Here is a
portion of the NumericController class (see NumericController for
the complete class).:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

296 Customization Guide


.
.
.
@Controller
@RequestMapping(value = "/numeric/**")
public class NumericController {

@RequestMapping(method = { RequestMethod.POST, RequestMethod.PUT })


protected void convertToString(
@RequestParam("data") final String data,
HttpServletRequest request, HttpServletResponse response) throws IOException {

JSONArray result = new JSONArray();

try {

JSONArray requests = new JSONArray(data);

for (int i = 0; i < requests.length(); i++) {


JSONObject req = requests.getJSONObject(i);
try {
String type = req.getString("type");
String externalForm = req.getString("externalForm");
String isPercent = req.optString("isPercent");
String isCurrency = req.optString("isCurrency");
String uniqueId = req.getString("uniqueId");

String displayValue = NumericFormat.formatValueForDisplay(type,


externalForm,
Boolean.valueOf(isPercent), Boolean.valueOf(isCurrency));

JSONObject singleResponse = new JSONObject();


singleResponse.put("displayValue", displayValue);
singleResponse.put("uniqueId", uniqueId);

result.put(singleResponse);
} catch (Exception e) {
.
.
.
}
}

response.setContentType("application/json; charset=UTF-8");
PrintWriter out = response.getWriter();
out.print(result.toJSONString());

Customizing HTML Clients Using the Windchill JSP Framework 297


} catch (Exception e) {
log.error("Problem displaying and formatting
number in NumericController.", e);
}

Refreshing a Large Block of the Page


There is often the need to refresh a section of the page without a full page refresh.
In this case there are some helpful javascript functions. In particular, the
getElementHtml function is optimized to replace the innerHTML of the
given div id with the response from the given url. If the div id is in the
response, only the innerHTML of the div will be used as the replacement. See
the jsDoc for more information about this function:.
getElementHtml( params, divId, true, url)

Sample Code
Examples of usage in out-of-box code. Many examples exist, search
actions.xml files for ajax=”component” ajax=”row” or the processors
for calls to addDynamicrefreshInfo.

298 Customization Guide


Bread Crumbs Component
You can create a list of navigation bread crumbs at the top of a Windchill page.
A list of “bread crumbs” is displayed at the top of many Windchill pages. These
bread crumbs show the location of the page in the page hierarchy. Each crumb is a
link that will take the user to the corresponding page in the hierarchy.
Example bread crumb list:

See the package javadoc for


com.ptc.windchill.enterprise.navigation.breadcrumb for
information on the classes and process used to produce bread crumbs.

Scope/Applicability/Assumptions
This process should be applied when you want to create bread crumbs for one or
more Windchill pages that do not currently have bread crumbs or you want to
modify the bread crumbs displayed on a Windchill page.

Intended Outcome
Bread crumbs are displayed as desired.

Solution
Create and register a BreadCrumbDelegate Java class with an inner class that
extends AbstractBreadCrumbGenerator to display the bread crumbs.

Prerequisite Knowledge
To create the necessary bread crumb classes you will need an understanding of the
Java programming language.

Customizing HTML Clients Using the Windchill JSP Framework 299


Solution Elements
Element Type Description
BreadCrumbController Java class The controller class that
receives AJAX requests
for bread crumbs. It
returns a response that is
the string form of a JSON
array of crumbs.
BreadCrumbDelegateFac- Java class A factory used by the
tory BreadCrumbController to
locate a
BreadCrumbDelegate
capable of producing the
bread crumbs for a given
page.
BreadCrumbDelegate Java interface A delegate that contains
an inner
AbstractBreadCrumbGen-
erator class and that
knows which pages the
generator class can
produce bread crumbs for.
AbstractBreadCrumbGen- Java class A subclass of this base
erator class creates the bread
crumbs for a page.
*.wt.properties.xconf Properties xconf file Contains the property
“com.ptc.windchill.
enterprise.breadcrumb.
BreadCrumbDelgate” that
lists all available
BreadCrumbDelegates.

300 Customization Guide


Procedure — Creating a New BreadCrumbDelegate Class
Creating the BreadCrumbDelegate Class
Bread crumb delegate classes should implement the BreadCrumbDelegate
interface. This interface has two methods: canHandle() and
getGenerator().
• The canHandle() method is called by the
BreadCrumbDelegateFactory to determine if the delegate’s inner
AbstractBreadCrumbGenerator class (see below) is capable of
producing bread crumbs for a given page. The canHandle() method is passed
the page URL, the context object from the URL, if any, and the container
object from the URL, if any. It should return true or false.
• The BreadCrumbController calls the getGenerator() method of
the delegate chosen by the factory to get a new instance of its inner
AbstractBreadCrumbGenerator class.

Note
Since the factory creates only one static instance of each delegate, the delegate
class itself should not use class instance variables or be stateful in any way.

Creating the AbstractBreadCrumbGenerator Inner Class


Your delegate class should have an inner class that is a subclass of
AbstractBreadCrumbGenerator. The getCrumbs() method of the
inner class will be called by the BreadCrumbController to generate the
JSONArray of crumbs. A new instance of the inner generator class will be created
each time it is called so generator classes may be stateful.
The constructor of the generator class will be passed the URL of the page, the
context object for the page, if given on the URL, and the container for the page, if
given on the URL. The constructor should call the init() method of the
superclass.
The JSON objects returned in the array by the getCrumbs() method should
have the following format:
{text: 'display text', url: 'http://my/url'}
For example:
[{"text":"Products","url":"app/#ptc1/comp/netmarkets.product.list"},
{"text":"Product1","url":"http://<someServer>/Windchill/app/#ptc1/tcomp/infoPage?
oid=OR%3Awt.pdmlink.PDMLinkProduct%3A105250&u8=1"}]
See Sample Code on page 303 for example classes.

Customizing HTML Clients Using the Windchill JSP Framework 301


Procedure — Registering the BreadCrumbDelegate
To register your BreadCrumbDelegate you must add it to the list of delegates
contained in the wt.property
“com.ptc.windchill.enterprise.navigation.breadcrumb.
BreadCrumbDelegate.” This property is defined as follows:
<Property name="com.ptc.windchill.enterprise.navigation.breadcrumb.
BreadCrumbDelegate"
multivalued="," default=
"com.ptc.windchill.enterprise.navigation.breadcrumb.
FolderedBreadCrumbDelegate" />
The default delegate, FolderedBreadCrumbDelegate, is the delegate that
will be called if no other delegate claims a page. The value of the default delegate
is hard-coded and cannot be changed. Changing the value in the property will
have no effect.
Additional delegates may be added to the delegate list in a custom or module-
specific *.xconf file using the AddToProperty tag. For example:
<AddToProperty name="com.ptc.windchill.enterprise.navigation.breadcrumb.
BreadCrumbDelegate
value="com.ptc.windchill.enterprise.navigation.breadcrumb.
WorkspaceBreadCrumbDelegate~10"/>
You can optionally assign a priority to a delegate, as shown above, by appending a
‘~’ followed by a priority value to the delegate class name. A priority value may
be any number less than Integer.MAX_VALUE; the lower the number, the
higher priority. To see the priorities of existing delegates you can look at the
composite property value in <Windchill>/codebase/wt.properties.
The BreadCrumbDelegateFactory will call the canHandle() methods
of delegates in priority order until it finds one that responds affirmatively.
Therefore, if there are multiple delegates that could generate the crumbs for a
given page, the one with the highest priority will be used. If multiple delegates
have the same priority, they will be called in random order. The canHandle()
method of delegates which do not have a “~<priority>” suffix will be called
last, in random order.

302 Customization Guide


Sample Code
The following code is extracted from the
AssignmentsBreadCrumbDelegate which generates the bread crumbs for
an task (WorkItem) object.
public class AssignmentBreadCrumbDelegate implements BreadCrumbDelegate {

@Override
public boolean canHandle(Persistable contextObject, WTContainer container,
String url)
throws WTException {
if (contextObject instanceof WorkItem || contextObject instanceof
ActionItem) {
return true;
}
return false;
}

@Override
public AbstractBreadCrumbGenerator getGenerator(Persistable contextObject,
WTContainer container, String url) throws WTException {
return new AssignmentCrumbGenerator(p, container);
}

public class AssignmentCrumbGenerator extends AbstractBreadCrumbGenerator {

/**
* IDs for Assignment list components.
*/
protected static final String PRODUCT_ASSIGNMENTS_LIST_ID =
"netmarkets.product.assignments.list";
protected static final String LIBRARY_ASSIGNMENTS_LIST_ID =
"netmarkets.library.assignments.list";
protected static final String QUALITY_ASSIGNMENTS_LIST_ID =
"com.ptc.qms.listAssignments";
protected static final String PROJECT_ASSIGNMENTS_LIST_ID =
"project.assignments";

protected WTContainer container;

/**
* Initialize as a generator and set instance variable
* container so that the Assignments crumb can be made.
* First tries to set container to c. Next
* tries to set container to contextObject's container (if
* contextObject is WTContained). Next tries to set
* container to contextObject's source object's container.
* Lastly tries to set container to contextObject's
* primary business object container.
*
* @param contextObject

Customizing HTML Clients Using the Windchill JSP Framework 303


* @param c
* @throws WTException
*/
public AssignmentCrumbGenerator(Persistable contextObject,
WTContainer c)
throws WTException {
init();

// If no container is passed in, try to get it from contextObject.


if (c == null && contextObject!= null) {
WTContained containedItem = null;

if (contextObject instanceof WTContained) {


// This will either be an ActionItem (which is contained)
// or could possibly be a future WorkItem, if it ever
// implements WTContained.
containedItem = (WTContained) contextObject;
} else if (contextObject instanceof WorkItem) {
// Use the WorkItem's source if it is contained.
ObjectReference sourceRef = ((WorkItem)
contextObject).getSource();

if (sourceRef != null) {
Persistable source = sourceRef.getObject();
if (source instanceof WTContained) {
containedItem = (WTContained) source;
}
}

// If there is still no containedItem, try use the


// WorkItem's primary business object.
if (containedItem == null) {
PersistentReference primaryObjectRef = ((WorkItem)
contextObject)
.getPrimaryBusinessObject();
if (primaryObjectRef != null) {
Persistable primaryObject = primaryObjectRef
.getObject();
if (primaryObject instanceof WTContained) {
containedItem = (WTContained) primaryObject;
}
}
}
}

if (containedItem != null) {
c = containedItem.getContainer();
}
}
container = c;
}

304 Customization Guide


@Override
public JSONArray getCrumbs() {
try {
addContainerCrumbs(container);
} catch (Exception e) {
log.error("Couldn't create the crumbs for container "
+ container, e);
addCrumb(getSecuredInfoCrumb());
}

try {
addCrumb(createAssignmentsCrumb());
} catch (Exception e) {
log.error("Couldn't create the Assignments Table crumb.", e);
addCrumb(getSecuredInfoCrumb());
}

return crumbs;
}

/**
* Makes the Assignments List crumb for a given assignment object.
*
* @return JSONObject
* @throws WTException
* @throws JSONException
*/
protected JSONObject createAssignmentsCrumb() throws JSONException,
WTException {
if (container == null) {
log.warn("The Assignments list crumb will not be made because
container is null.");
return null;
}

String url = getAssignmentsListUrl(container);


String localizedText = navigationBundle
.getString(navigationRB.ASSIGNMENTS);
return createCrumb(url, localizedText);
}
/**
* Given a container, will return a URL for the assignment list
table.
* Example:
* app/#ptc1/comp/netmarkets.product.assignments.list?
oid=OR%3Awt
* .pdmlink.PDMLinkProduct%3A12345&u8=1
*
* @param container
* @return String

Customizing HTML Clients Using the Windchill JSP Framework 305


*/
protected String getAssignmentsListUrl(WTContainer container) {
String url = "";

if (container instanceof PDMLinkProduct) {


url = MVCUrlHelper.getComponentURL(PRODUCT_ASSIGNMENTS_
LIST_ID);
} else if (container instanceof Project2) {
// Could be project or program. Same URL in either case.
url = MVCUrlHelper.getComponentURL(PROJECT_ASSIGNMENTS_
LIST_ID);
} else if (container instanceof WTLibrary) {
WTLibrary libObj = (WTLibrary) container;
if (libObj.isQMSTypeContainer()) {
// If Quality container then navigate to Quality
Assignment
// page
url = MVCUrlHelper
.getComponentURL(QUALITY_ASSIGNMENTS_LIST_ID);
} else {
// If Library container then navigate to Library
Assignment
// page
url = MVCUrlHelper
.getComponentURL(LIBRARY_ASSIGNMENTS_LIST_ID);
}
} else {
// This is the case where container is null or of unsupported
// container type.
return null;
}

url = url.replaceFirst("/", MVCUrlHelper.APPPREFIX);

String containerOid = "OR:"


+ container.getPersistInfo().getObjectIdentifier()
.toString();
try {
containerOid = URLEncoder.encode(containerOid, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("Could not encode the container oid.", e);
}

url += "?oid=" + containerOid + "&u8=1";

return url;
}
}
}

306 Customization Guide


Additional Resources
Related Package/Class Javadoc
• com.ptc.jca.mvc.controllers.BreadCrumbController
• com.ptc.windchill.enterprise.navigation.breadcrumb.
BreadCrumbDelegateFactory
• com.ptc.windchill.enterprise.navigation.breadcrumb.BreadCrumbDelegate
• com.ptc.windchill.enterprise.navigation.breadcrumb.
AbstractBreadCrumbGenerator
• com.ptc.windchill.enterprise.navigation.breadcrumb.
FolderedBreadCrumbDelegate

Packaged Samples
This section contains information on the sample code that is provided within the
system.

Bread Crumbs Based on the Context Object


This example shows how bread crumbs can be created based on the context object
of the page. The bread crumbs for this example were created by the
FolderedBreadCrumbDelegate. This is the default delegate that will be
called to create bread crumbs, if it can, when no other delegate claims the ability
to handle the page. This is accomplished with the following code:
@Override
public boolean canHandle(Persistable p, WTContainer container, String url)
throws WTException {
return true;
}
The FolderedBreadCrumbDelegate first tries to use a passed in
WTContainer (“container” in this case), if any. If no container is passed in, the
delegate uses the Persistable context object (“p” in this case) to determine where
the object lives in the system. If the Persistable is itself a container, use that as the
crumb. If the Persistable is not a container, attempt to get the Persistable’s
container as the crumb. If all of the previous options fail, simply return an empty
crumb.
public class FolderedBreadCrumbDelegate implements BreadCrumbDelegate {

@Override
public AbstractBreadCrumbGenerator getGenerator(Persistable p,

Customizing HTML Clients Using the Windchill JSP Framework 307


WTContainer container, String url) throws WTException {
return new FolderedCrumbGenerator(p, container);
}

public class FolderedCrumbGenerator extends AbstractBreadCrumbGenerator {

protected Persistable p;

protected WTContainer container;

public FolderedCrumbGenerator(Persistable p, WTContainer container)


throws WTException {
init();

// If a container is present, use it. Else if p is itself a


// container, use that. Otherwise get p's
// container.
if (container != null) {
this.container = container;
} else if (p instanceof WTContainer) {
this.container = (WTContainer) p;
} else if (p instanceof WTContained) {
this.container = ((WTContained) p).getContainer();
}

this.p = p;
}

@Override
public JSONArray getCrumbs() {
// Try to add the container crumbs.
try {
addContainerCrumbs(container);
} catch (Exception e) {
addCrumb(getSecuredInfoCrumb());
}

// Try to add the trail of parent folder crumbs.


try {
addFoldersIfNeeded(container, p);
} catch (Exception e) {
addCrumb(getSecuredInfoCrumb());
}

return crumbs;
}

308 Customization Guide


When visiting the info page link for our example haiku, you can see the bread
crumb shows that this particular object resides under Site ▶ Folders. Note: only
users with adequate permissions will be able to view this object’s info page.

Location of Example
To navigate to this example in the product go to Customization ▶ Component
Catalog ▶ Bread Crumb ▶ Bread Crumb Component based on the Context Object.

Note
The Component Catalog is not enabled in the Windchill UI by default. For
instructions on enabling the Component Catalog, see Enable Customization
Utilities on page 404.

Actions for this Example


None

Action Models for this Example


None

Files Used in This Example


• com/ptc/windchill/enterprise/navigation/breadcrumb/
FolderedBreadCrumbDelegate.java
• com/ptc/core/components/components.wt.properties.xconf

Bread Crumbs Based on the URL


This example shows how to create bread crumbs based on the URL path of a
given page. The canHandle() method of the
CarambolaBreadCrumbDelegate used in this example checks if the URL
path contains certain strings. If the URL contains “componentCatalog”,
“carambola”, “apiDocs” or “jsapi”, the method will return true. Its
generator class then returns a bread crumb array depending on the contents of the
URL. For example, if the URL contains “carambola” and “breadCrumb”, the
“Component Catalog” and “Bread Crumb Component” crumbs will be
added.

Customizing HTML Clients Using the Windchill JSP Framework 309


Location of Example
To navigate to this example in the product go to Customization ▶ Component
Catalog ▶ Bread Crumb ▶ Bread Crumb Component based on the URL.

Note
The Component Catalog is not enabled in the Windchill UI by default. For
instructions on enabling the Component Catalog, see Enable Customization
Utilities on page 404.

Actions for this Example


None

Action Models for this Example


None

Files Used in This Example


• com/ptc/carambola/customization/examples/breadcrumb/
CarambolaBreadCrumbDelegate.java
• com/ptc/carambola/carambola.wt.properties.xconf
• com/ptc/carambola/CustomizationPage.java

310 Customization Guide


Client Tabs
Users and administrators want to create and configure additional tabs on
information pages.
Information pages are composed of one to several tabs. Each information page is
configured out-of-the-box with a set of tabs, and default content on those tabs.
Out-of-the-box tabs are created and configured by creating or editing an action
model (see Customizing Information Page Components on page 972 for more
information on creating tab sets for an information page). These tabs are then
available for that information page for all users.
Tabs may also be created dynamically by users, by clicking the “+” icon on the tab
set. These tabs can be configured by adding content. Since these tabs are not
defined via an action model as the other tabs, a mechanism to persist the tab and
its content is required. Also, administrators may wish to create and configure tabs
on information pages that are available for all users in their site and/or
organization.

Scope/Applicability/Assumptions
This document assumes you are familiar with configuring Windchill information
pages, and configuring information page tab sets in particular.

Intended Outcome
Upon reading this best practice you should understand how information page tabs
can be created and configured by users and administrators. You should also be
able to utilize the customization points to customize how tabs are handled for
information pages.

Solution
Tabs created dynamically by users and administrators will be persisted in the
database.

Prerequisite Knowledge
To apply this process, you need to have an understanding of the following:
• Basic development involving Java, XML, and JavaScript particularly
JavaScript Object Notation (JSON)
• An understanding of how information page tabs are created and configured via
action models (See Customizing Information Page Components on page 972
for more information)

Customizing HTML Clients Using the Windchill JSP Framework 311


Solution Elements
Element Type Description
ClientTab.java Java class Located at <WT_
HOME>\com\ptc\core\ui
\tab
Provides the definition for
the persisted tab object in
the database. Contains all
necessary information
needed to associate a tab
with its content, the
object type, the creator,
etc.
TabSetDelegate.java Java interface Located at <WT_
HOME>\com\ptc\core\ui
\tab
Defines the interface for
determining the set of
tabs to be used for the
information component.
DefaultTabSetDelegate. Java class Located at <WT_
java HOME>\com\ptc\core\ui
\tab
Provides the default
implementation of the
TabSetDelegate interface.
This class will determine
what tabs to display for
an information page.
JSONTabServiceAdapter. Java class Located at <WT_
java HOME>\com\ptc\core\ui
\tab
Used to convert JSON
objects from the client to
persistable objects on the
server.
ClientTabHelper.java Java class Located at <WT_
HOME>\com\ptc\core\ui
\tab\server

312 Customization Guide


Element Type Description
A helper class to provide
access to the ClientTab
service, as well as other
helper methods.
ClientTabService,java Java interface Located at <WT_
HOME>\com\ptc\core\ui
\tab\server
Defines the interface for
the storage, retrieval, and
deletion of the ClientTab
objects.
StandardClientTabSer- Java class Located at <WT_
vice.java HOME>\com\ptc\core\ui
\tab\server
Provides the default
implementation of the
ClientTabService to store,
update, and delete
ClientTab objects.
TabManager.jsfrag Javascript fragment Located at <WT_
HOME>\netmarkets
\javascript\util\jsfrags
The client code
responsible for managing
the state of the tabs,
including the creation,
modification, or deletion
of tabs. This client code
will interact with the
server via AJAX requests.
TabController.java Java class Located at <WT_
HOME>\com\ptc\jca\mvc
\controllers
The server code that is
responsible for receiving
the HTTP requests from
the client and performing
the appropriate action
(creation, deletion, or
modification of a tab).

Customizing HTML Clients Using the Windchill JSP Framework 313


Element Type Description
RenderInfoPageModel- Java class Renders the whole info
Tag.java model (including the tab
set)
infoPage.jsfrag Javascript fragment Renders the tab set, has
code to update the tab set
as user adds/removes tabs
or tables from the tabs.
InfoPageTabSetDataUtili- Java class Looks up the tab delegate
ty.java to use for finding the info
page tab set.

Below is a diagram illustrating the relationship of some of the more important


components listed above:

The tabs that a user sees an information page are thus a combination of the actions
defined by the actions model XML, any tabs created by the site administrator, any
tabs created by the organization administrator, and any tabs created by the user. It
is important to note that information tabs are linked to an object type. That is, if
“Tab A” is created for a document, then “Tab A” will be seen on every document
information page, but not on information pages for other object types (i.e. Part).
The default implementation of the TabSetDelegate follows the following
algorithm for determining what tabs to display for a given information page:
• Retrieve the tabs defined by the action model
• Retrieve the tabs defined by the site administrator for the object type

314 Customization Guide


• Retrieve the tabs defined by the user’s organization administrator for the
object type
• Retrieve the tabs defined by the user for the object type
This behavior can be customized by writing your own TabSetDelegate. See
Customizing Tabs by Implementing Custom TabSetDelegate on page 322 for
more information.

Customization Points
This section contains the following topics:
• Customizing Tabs via Windchill UI on page 315
• Customizing Tabs by Implementing Custom TabSetDelegate on page 322
• Customizing Tabs by Implementing Custom TabController on page 322

Customizing Tabs via Windchill UI


This section contains the following topics:
• General Procedure on page 315
• Out-of-the-Box (OOTB) Tabs on page 318
• Customizing Tabs — Site Administrator on page 319
• Customizing Tabs — Organization Administrator on page 320
• Customizing Tabs — Standard User on page 321
• Reordering Tab Content Items on page 321

General Procedure
Users can create and configure a tab by visiting an information page for the type
you wish to configure. Click the tab with the “+” icon to create a new tab, and
configure the tab as needed.
It is important to note that throughout this process the tab is being saved, without
any explicit action required. The very act of creating a new tab creates a new tab
object in the database. Any actions to the tab, including changing its name, adding
content, or deleting it, are immediately saved on the server.
The general procedure for adding and configuring a tab for a specific type is
illustrated below. In this example, we will create and configure a tab that will
display history information for documents:
1. Visit the information page of any document, and create a new tab by clicking
the “+” tab:

Customizing HTML Clients Using the Windchill JSP Framework 315


2. This will create a new tab, named “New Tab 1” (or “New Tab 2” or some
variation, depending on how many newly created tabs there are):

3. You can than rename this tab to something more meaningful. In this case,
since this tab will be used to display history information, we will rename it to
“History” by right-clicking on the tab itself, and invoking the Rename Tab
action:

4. Enter the desired name into the resulting dialog, and you should see the tab’s
new name:

316 Customization Guide


Note
There is a OOTB tab named History. This example assumes that you have
hidden the OOTB History tab by commenting out <subModel name=
?docObjectHistoryTab?/> in the <Windchill>/codebase/
config/actions/DocumentManagement-actionmodels.xml
file.

5. New tabs are initially added to the right most end of the tab set. You can move
your new tab to a different position in the tab set using a left-mouse click and
drag-and-drop:

6. At this point, we have created a tab, given it a descriptive name, and moved it
to the desired position in the tab set. We have yet to add any content to it,
however, so it is not very useful yet. We’ll add content to the tab by clicking
the “Customize” link. The Customize menu shows the content items that can
be added to the tab. Content items are typically tables or attribute panels. The
main Customize menu shows categories of content items. Each category has a
submenu showing the content items in that category. You can select all the
content items in a category by checking the box associated with the category
or you can select individual content items within a category. We’ll add the
“Version” table to our new tab by selecting it in the Customize menu:

7. Now we have a History tab, with the Version component added to it.
Depending on the administrative role of the user performing this action, this

Customizing HTML Clients Using the Windchill JSP Framework 317


tab and its content will either be unique to the user, available for all users
within the organization, or available for all users within the site, for all
documents. This is explained in the following sections.
In order to delete any user created tab, you can delete by right clicking on the
tab itself and invoking “Close Tab” action.

8. You will get below confirmation dialog, by clicking OK, the tab will get
deleted and by clicking Cancel you will be returned to the page.

9. The tab can also be deleted by clicking “x” on the tab itself.

Out-of-the-Box (OOTB) Tabs


A set of tabs can be configured out-of-the-box. These tabs are configured in an
actionModels.xml file, like this:
<model name=”partInfoPageTabSet” resource=”com.ptc.core.ui.navigationRB”>
<submodel name=”partInfoDefaultDetails” type=”object”/>
<action name=”productStructureGWT” type=”psb”/>
</model>
The model can contain the following elements:
• submodel : specifies the tab name (display name mapped to the name of the
submodel) and the items (tables) to render on the tab. Each action defined

318 Customization Guide


within the submodel, a corresponding item (table) is rendered to the body of
the tab.
• action : specifies the tab name (display name mapped to the name of the
action) and the component or JSP to include as the tab body. The HTML
returned from the action is rendered as the body of the tab.
The action model is set in the component builder for the given component. Please
refer to Sample Code on page 324 for usages of Client Tabs for a specific
component.
Out-of-the-box tabs can only be modified by changing the action definition in the
XML file. Users (site administrator, organization administrator, or standard users)
are not allowed to change the name of the tab, change the contents of the tab, or
remove the tab.
All users will have the ability to change the order in which the tabs appear, this
includes out-of-the-box tabs.

Customizing Tabs — Site Administrator


A site administrator can create and configure tabs, per object type, that will be
available for all users in that site. If the site administrator creates a History tab, for
example, as detailed in General Procedure on page 315, that tab will be seen on all
document information pages, for all users in the site. The site administrator will
not see all the tabs for all of the organizations. They will just see what tabs are at
the site level.
Tabs created by a site administrator, can only be managed by a site administrator.
That is, only a site administrator can change the name of the tab, can change the
contents (including the ordering of the contents) of the tab , can make it Public so
that all the users in the system can see it, or remove the tab.
All users will have the ability to change the order in which the tabs appear, this
includes out-of-the-box tabs and tabs created by a site administrator.
By default, the tabs created by a Site Administrator will be private tabs and are not
seen by any other users. The tab can be made public by invoking the “Set Public”
tab action. At this point all the users in the system can see this tab and its content.
Notice that the color of the tab changes and an icon appears next to the customize
menu to indicate that the tab is public.

Customizing HTML Clients Using the Windchill JSP Framework 319


A public tab can be made private by invoking “Set Private” tab action. Making a
public tab private will remove the tab for all other users, this could be confusing to
the users.

Customizing Tabs — Organization Administrator


An organization administrator can create and configure tabs, per object type, that
will be available for all users in that organization. If the organization administrator
creates a History tab, for example, as illustrated in General Procedure on page
315, that tab will be seen on all document information pages, for all users in that
organization.
Tabs created by an organization administrator, can only be managed by an
organization administrator. That is, only an organization administrator can change
the name of the tab, can change the contents (including the ordering of the
contents) of the tab, can make it Public so that all the users in that organization
can see it, or remove the tab.
A site administrator will not be able to manage a tab created by an organization
administrator.
All users will have the ability to change the order in which the tabs appear, this
includes out-of-the-box tabs and tabs created by an organization or site
administrator.
By default the tabs created by an Organization Administrator will be private tabs
and are not seen by any other users in that organization. The tab can be made
public by invoking the “Set Public” tab action. At this point all the users in that
organization can see this tab and its content. Notice that the color of the tab
changes and an icon appears next to the customize menu to indicate that the tab is
public.

A public tab can be made private by invoking “Set Private” tab action. Making a
public tab private will remove the tab for all the users of that organization; this
could be confusing to the users.

320 Customization Guide


Customizing Tabs — Standard User
A standard user can also create and configure tabs, per object type, that will be
available for only that user. If the user creates a History tab, for example, as
illustrated in General Procedure on page 315, that tab will be seen on all document
information pages, for only that user.
Tabs created by a standard user, can only be managed and seen by that user. That
is, only that user can change the name of the tab, can change the contents
(including the ordering of the contents) of the tab, or remove the tab. Standard
users do not see the Set Public/Set Private tab actions. These actions are limited to
Site and Organization administrators.
A site administrator or organization administrator will not be able to manage a tab
created by a standard user.
All users will have the ability to change the order in which the tabs appear, this
includes out-of-the-box tabs and tabs created by administrators.

Reordering Tab Content Items


If a tab contains more than one content item, the content items may be reordered
using the Table of Contents links on the tab. Left-click on a content item link and
drag-and-drop the link to the position corresponding to where you want the item
to appear on the tab:

As stated earlier, administrators can only reorder the contents of tabs created by
administrators and users can only reorder the contents of tabs they created. If you
do not have the ability to modify the order of the contents, the content items will
not be displayed as links in the Table of Contents.

Customizing HTML Clients Using the Windchill JSP Framework 321


Customizing Tabs by Implementing Custom TabSetDelegate
It is possible to control a different algorithm for displaying the tabs. The
TabSetDelegate class is what brings together tabs from the *actions.xml and
tabs that are stored in the database. The RenderInfoPageModelTag will take
the output from the TabSetDelegate.getDefaultAndDynamicTabs()
and render out JSON that will display the tabs on the client. The code could look
something similar to the following:
public class DefaultTabSetDelegate implements TabSetDelegate {

/**
* This is the main method to add the site, org and user tabs along side
* the default set that was in the action model.
*/
public NmHTMLActionModel getDefaultAndDynamicTabs() {…code here}
To add your own TabSetDelegate class you can specify the following in the
service.properties file:
<Service context="default" name="com.ptc.core.ui.tab.TabSetDelegate">
<Option serviceClass="com.ptc.core.ui.tab.your.package.
CustomizedClassDelegate"
requestor="infoPage" selector="wt.part.WTPart"/>
</Service>
The selector is specified for the type of wt.part.WTPart. This means that the
delegate will be called for part information pages and all soft types of WTPart.

Customizing Tabs by Implementing Custom TabController


Ajax requests are sent to the TabController in order to have the information
persisted into the database. This can be customized by extending or creating a new
controller with a request mapping that would be similar to the following example
code:
@Controller
@RequestMapping(value = "/tab/**")
public class MyTabController {

/**
* Creates, Updates, or deletes the tab by calling the @link
{JSONTabServiceAdapter}.
*
* @param data - String version of the JSON object
* @param action - will be set to one of the following values:
[create, update, delete]
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(method = { RequestMethod.POST, RequestMethod.PUT })
protected void createAndUpdateTab(@RequestParam("data") final String data,
@RequestParam("action") final String action,

322 Customization Guide


HttpServletRequest request,
HttpServletResponse response) throws IOException {…code here…}

Exporting and Importing Client Tabs


Exporting
You can export client tabs using a command line application.
1. From the Windchill shell, enter: java
com.ptc.core.ui.ixb.ClientTabExport tabname
The required tabname parameter is the name of the tab to export.
• For a home page, this should be the string homepage.
• For other tabs, the name is that shown on the tab in the UI.
• To export a tab that includes spaces in the name, double-quote the
parameter: “My Custom Tab”.
2. You will be prompted for a Windchill user name and password. Enter the Site
Administrator’s credentials.
3. Wildcards are added internally; the resulting query is: select * from
CLIENTTAB where NAME like %tabname%;
4. The export utility reports the names of exported tabs, and the location of the .
jar file it produces:
> java com.ptc.core.ui.ixb.ClientTabExport a
2011-10-14 09:55:38,377 INFO [main] com.ptc.core.ui.ixb.ClientTabExport
- Exporting tab OrgAttr
2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport
- Exporting tab my custom tab
2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport
- Exporting tab jcrpage
2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport
- Exporting tab homepage
2011-10-14 09:55:40,127 INFO [main] com.ptc.core.ui.ixb.ClientTabExport
- Exported to <WT_HOME>\Windchill\temp\IXBExpImp\1279724139377-1977404926
\Export5586892419340327596.jar

Importing
Importing ClientTab records is performed from the Windchill Import/Export
Management utility.

1. Log into Windchill on the destination system as the Site Administrator.


2. From the Site ▶ Utilities ▶ System Administration ▶ Import/Export Management.

Customizing HTML Clients Using the Windchill JSP Framework 323


3. The Windchill Import/Export Management utility presents an option to import
or export.
4. Choose Import. In the import dialog box, paste or browse to the path of the
exported .jar file.

Note
If the container or user of an imported tab (whichever applies) is not present
on the destination system, that tab is not imported. A warning will be
displayed.

Sample Code
Examples of Usage in Windchill Code
• Information Page
The information page uses Client Tabs to manage out-of-the-box, site defined,
organization defined, and user defined tabs. The information page will set the
default action model (the model specified in the actions model XML file that
defines tabs and their contents) on the TabSetDelegate, and then query
the TabSetDelegate for any administrator or user created tabs.
The default, out-of-the-box implementation of the TabSetDelegate will
return an action model that is the default action model, plus all administrator
and user-defined tabs.
For more information about defining tabs for an information page, please refer
to Customizing Information Page Components on page 972.

Packaged Samples
There is a carambola information page underCustomization ▶ Example ▶
Information Page.
http://<machineNam>/<webApp>/app/#ptc1/tcomp/
infoPage?typeIdForTypeLookup=
com.ptc.carambola.customization.examples.infoPage.Caram
bola

324 Customization Guide


Checkin/Checkout
Objective
You want to be able to checkin and checkout an object.

Background
The ability to check in and checkout gives the ability to track changes to an object
by providing an iteration history of each change. Also if a user has an object
checked out, no other user may modify the object until it has been checked back
in.
In order for an object to work with the checkin/checkout common component it
must implement the wt.vc.wip.Workable interface.

Scope/Applicability/Assumptions
• The object implements either the Workable interface.
• Familiarity with the actions framework
• Familiarity with the basic concepts of checkin/checkout

Customizing HTML Clients Using the Windchill JSP Framework 325


Intended Outcome
By following these procedures you should be able to add or modify the checkin
and checkout actions.
• Checkout action (no wizard involved)

• Checkout status icon after the object is checked out

326 Customization Guide


• Checkin wizard (in this case with primary content but the primary attachment
component will not appear if your object does not support it).

Solution
Use the Checkin/Checkout common components with your object.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Windchill “work in progress” checkin/checkout concepts.
• The actions framework in the Windchill client architecture.
• Basic development involving HTML forms, JSP, and XML.

Procedure – Adding checkin/checkout actions to a business object


In the action model xml file that defines the action model with the menufor
attribute for your object type add the following actions. This will provide checkin,
checkout, checkout & download, undo checkout, replace content, and checkout &
edit actions for your object. Note, only add checkout & download and replace
content actions if you are adding these actions for an object that implements the
FormatContentHolder interface and you expect it may have primary content.
<action name="checkin" type="wip"/>

Customizing HTML Clients Using the Windchill JSP Framework 327


<action name="checkout" type="object"/>
<action name="checkout_and_download" type="wip"/>
<action name="undocheckout" type="object"/>
<action name="replace_content" type="wip"/>
<action name=" checkoutAndEdit " type="YOUR TYPE FROM YOUR TYPE’S
ACTIONS XML"/>

Checkout and edit however requires additional coding. Create an additional action
definition in the actions.xml file for your object type. Name the action
“checkoutAndEdit” so that the validation framework will pick it up properly. Then
set the url attribute to point to your wizards edit jsp file.
Example:
<action name="checkoutAndEdit">
<command
class="com.ptc.core.components.forms.EditObjectFormProcessor"
method="execute" url="netmarkets/jsp/document/edit.jsp"
windowType="popup" /
</action>

Add the appropriate entries for this action in your rbinfo file (see actions
framework documentation). In your edit jsp file you will need to add the following
tag above the wizard declaration.
<%@ taglib prefix="wip"
uri="http://www.ptc.com/windchill/taglib/workinprogress"%>

<wip:autoCheckOutItem />

This will allow the wizard to checkout the object if the object is not already
checked out.

Caution
Using this tag on wizards other than edit or without a processor that is
extending EditObjectFormProcessor is not supported and may result in
unstable code.

Sample Code

Examples of Usage in Windchill Code


To view a sample action model with checkin/checkout actions see the document
action models (<Windchill>\codebase\config\actions\DocumentManagement-
actionmodels.xml)

328 Customization Guide


To view a sample checkout and edit action see the action definition in the
document actions definitions (<Windchill> \codebase\netmarkets\jsp\document
\edit.jsp) and the document edit JSP file (<Windchill>\codebase\config\actions
\DocumentManagement-actions.xml)

Customizing HTML Clients Using the Windchill JSP Framework 329


Component Access Control
Objective
You want to use a consistent interface to view and manipulate access control
permissions on individual Windchill objects.

Background
The Common Access Control Component was developed to provide a consistent
interface for Windchill ProjectLink and Windchill PDMLink users to view and
manipulate access control permissions on individual Windchill objects. The
feature is available in the out of the box Security Clerk through the Edit Access
Control action and also in the Create Document and Create Part wizards.
To learn more about the action and window, see the Edit Access Control section of
the Windchill Basic Administration Guide.
This feature for individual object instances is implemented using ad hoc ACLS.
The access component for a folder also has the additional capability of defining
permissions and propagating them throughout the folder contents.
Preferences are supported to permit sites to tailor the visibility and updatability of
individual access control permissions to meet their specific access control
requirements.

Scope/Applicability/Assumptions
This feature only applies to objects that implement the
wt.access.AdHocControlled interface. The AdHocControlled
interface holds information that controls access to a specific instance of an object
class. The ad hoc ACL specifies only positive permissions. It cannot be used to
deny access to an object. If the ad hoc ACL grants a permission that is denied in
the policy ACL, the ad hoc rule supersedes the policy rule, and the access right is
granted.

Intended Outcome
The feature may be used in two ways:
• The Edit Access Control action can be added to the object’s action model and
the action will be available in the object’s action list.

330 Customization Guide


Note
The visibility of the action may be constrained by profiles defined in the
Role Based UI. See the Windchill Basic Administration Guide for more
details about profile- and role-based visibility administration.

• The Access Control Component can be included as a step in the object’s


Create wizard. It appears as an optional Set Access Control step in the create
process, which is highlighted in the wizard at this point.

Customizing HTML Clients Using the Windchill JSP Framework 331


Solution
Use the Access Control Component to provide an interface to view and
manipulate access control on Ad Hoc controlled objects.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Windchill client architecture
• Basic development involving HTML forms, JSP, and tag libraries.
• The actions framework in the Windchill client architecture.

Solution Elements
Element Type Description
actionmodels.xml XML <Windchill>\codebase\
actionmodels.xml
The actionmodels file defines the actions
available in named action models.
Create<myObject>.jsp JSP The outer jsp file defining a create wizard

332 Customization Guide


Procedure - Adding an Edit Access Control action to an
action model
Include the following in the desired action model in your object's
actionmodels.xml:
<action name="ManageSecurity"
type="accessPermission"/>

Procedure - Including an Access Control Step in a Create Wizard


Update the main Create<myObject>.jsp to define the JCA tag library:
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components" %>

Include the access control wizard step:


<jca:wizardStep action="setAccessControlWizStep" type="object"/>

Customization Points

Configuring the access permissions


The permissions presented for view and update in the common access control
component are configurable at the site, org, and application container with the
preference service. At each container level, administrators can select the
permissions that members of the container will be permitted to view and
potentially update.
The initial values for the permission configurations are loaded from
<Windchill>\loadFiles\preference.foundation.xml with a
csvcategoryName of “SECURITY_PERMISSION_CATEGORY”.
Below is an example loading the initial system configuration for the Read
permission.
<csvPreferenceDefinition
handler="wt.preference.LoadPreference.createPreferenceDefinition">
<csvname>security/accessPermissionRead</csvname>
<csvvisibility>HIDDEN</csvvisibility>

<csvcategoryName>SECURITY_PERMISSION_CATEGORY</csvcategoryName>

<csvdisplayName>com.ptc.core.security.securityResource:READ</csvdisplay
Name>

<csvdescription>com.ptc.core.security.securityResource:READ</csvdescript
ion>

Customizing HTML Clients Using the Windchill JSP Framework 333


<csvlongDescription>com.ptc.core.security.securityResource:READ</csvlong
Description>
<csvdefaultValue>UPDATE</csvdefaultValue>

<csvhandler>com.ptc.windchill.enterprise.preference.handler.ChoiceMultiPr
eferenceValue
Handler:readPermission:HIDE,com.ptc.core.security.securityResource,HIDE:V
IEW,com.ptc.
core.security.securityResource,VIEW:UPDATE,com.ptc.core.security.security
Resource,
UPDATE</csvhandler>
</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition
handler="wt.preference.LoadPreference.setClientDefinitionLink">
<csvname>security/accessPermissionRead</csvname>
<csvclientName>WINDCHILL</csvclientName>
</csvLinkPreferenceClientDefinition>

The initial state of the permission configuration can be modified by changing the
“csvdefaultValue” for the permission entry. The possible values are
“HIDE”, “READ”, and “UPDATE”.

Sample Code

Examples of usage in OOTB code

Edit Access Control Action in document action model


Edit Access Control is an action available in the action list on a document info
page. The action is included in the “docs details page actions” action model
defined in <Windchill>\codebase\actionmodels.xml
<!-- list used on document details page -->
<model name="docs details page actions">
<action name="oldedit" type="document"/>
<action name="download" type="document"/>
<action name="route" type="workflow"/>
<action name="setState" type="lifecycle"/>
<action name="createSubscription" type="subscription"/>
<action name="checkout" type="object"/>
<action name="checkin" type="document"/>
<action name="undocheckout" type="object"/>
<action name="rollupIterations" type="object"/>
<action name="update" type="document"/>
<action name="rename" type="document"/>

334 Customization Guide


<action name="ManageSecurity" type="accessPermission"/>
<action name="delete" type="object"/>
<action name="bookmarkIt" type="bookmark"/>
<action name="create_deli" type="deliverable"/>
<action name="cut" type="object"/>
<action name="copy" type="object"/>
<action name="export" type="object"/>
<action name="viewInProductView" type="document"/>
<action name="pdmCheckInApply" type="object"/>
<action name="SBSendToPdm" type="sandbox"/>
<action name="sandboxUndoCheckoutDetails" type="object"/>
<action name="removeShare" type="object"/>
<action name="EDA_COMPARE" type="EDAcompare"/>
<action name="VALIDATION_MANAGER" type="EDAcompare"/>
<action name="SETUP_FILE" type="EDAcompare"/>
<action name="wtObjCompare" type="ocmp"/>
</model>

Access Control Step in Create Document Wizard


The Create Document wizard is an example of Access Control as a step in a create
wizard.
Source file: wcEnterprise\DocumentManagement\src_web\
netmarkets\jsp\document\create.jsp
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components" %>
<%@ taglib prefix="docmgnt"
uri="http://www.ptc.com/windchill/taglib/docmgnt" %>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:initializeItem operation="${createBean.create}"/>

<docmgnt:validateNameJSTag/>

<jca:wizard title="${param.titleString}">
<jca:wizardStep action="setContextWizStep" type="object"/>
<jca:wizardStep action="defineItemWizStep" type="object"/>
<jca:wizardStep action="setAttributesWizStep" type="object"
/>
<jca:wizardStep action="attachments_step" type="attachments"
/>
<jca:wizardStep action="setAccessControlWizStep"
type="object"/>

Customizing HTML Clients Using the Windchill JSP Framework 335


</jca:wizard>

<jca:action actionName="fileSelectionAndUploadApplet"
actionType="attachments" />

<script type="text/javascript">

setUserSubmitFunction(submitFileContent);
</script>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

The definition of “setAccessControlWizStep” is in Source file, <Windchill>\


codebase\config\actions\Security-actions.xml, which defines :
<action name="setAccessControlWizStep"
id="setAccessControlWizStep" preloadWizardPage="false">

<command
class="com.ptc.core.security.forms.UpdatePermissionsFormDelegate" method=""
windowType="wizard_step"/>
</action>

336 Customization Guide


Attachments
Objective
You want to add or modify the ability to add, modify, and download content from
a format content holder or content holder business object

Background
The ability to add attachments to an object is the ability to upload and associate a
file, link to a url, or describe an external location of content and associate that
content data with this object. For example you may create a document and upload
one or more files. You may also add multiple urls that point to additional
information as supporting material for a change request.
Object types such as documents implement an interface called
FormatContentHolder which allows them to associate one piece of content
as “primary content”. There can only be one primary content though. Object types
such as a change requests implement ContentHolder which allow them to
have multiple secondary content but not primary attachments. Objects that
implement FormatContentHolder however can have both primary and
secondary attachments because FormatContentHolder is a specialization of
the ContentHolder interface.

Scope/Applicability/Assumptions
Assumptions:
• The wizard that is using the attachment components implements either the
FormatContentHolder or the ContentHolder interfaces.
• The wizard is using the Windchill Client Architecture wizard framework
• The user is familiar with the actions framework

Intended Outcome
By following these procedures you should be able to add or modify the following
components to your UI.

Customizing HTML Clients Using the Windchill JSP Framework 337


Primary content component in a wizard (object must be a
FormatContentHolder)

Secondary attachments component in a wizard (object must be a


ContentHolder)

338 Customization Guide


Attachments table in a details page (object must be a ContentHolder)

Primary content component in an info page properties panel (object must be a


FormatContentHolder)

Primary content component in an info page properties panel (object must be a


FormatContentHolder)

Solution
Use the Attachments Common Components with customized JSP clients
associated to that object type.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML forms, JSP, and JSP custom tags
• The wizard is using the Windchill Client Architecture wizard framework
• The user is familiar with the actions framework

Customizing HTML Clients Using the Windchill JSP Framework 339


Solution Elements
Element Type Description
attachments.tld Java tag Defines any common
definition component tags you will need to
use the attachments common
components.
Runtime location:
codebase\WEB-INF\tlds\
attachments.tld
AttachmentsDownload Java file Servlet that redirects download
AppletServlet.class to the appropriate file for the
object.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar
AttachmentsValidation Helper. Java file Supporting methods for
class validating various attachments
related actions.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar
AbstractAttachments Java file General form processing
SubFormProcessor.class delegate that provides shared
attachments functionality to the
primary and secondary form
processors.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar
PrimayAttachment Java file Form processing delegate that
SubFormProcessor.class attaches primary attachments to
the object.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

340 Customization Guide


Element Type Description
SecondaryAttachments Java file Form processing delegate that
SubFormProcessor.class attaches secondary attachments
to the object.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar
AttachmentsDataUtility Helper. Java file Supporting methods for
class displaying attachments data in a
data utility.
Runtime location:
codebase\WEB-INF\lib\
wncWeb.jar

Procedures

Adding primary content to a wizard


To add primary attachment support to a wizard of an object that implements the
FormatContentHolder interface you will need to add the applet tag to the
main wizard jsp and the primary attachment tag to a wizard step.
On the main wizard jsp (which defines the <jca:wizard tag and the wizard
steps) add the following tag definition and
fileSelectionAndUploadApplet tag. The tag will render a tiny invisible
applet which is used for file browsing and file uploading.
<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

<attachments:fileSelectionAndUploadApplet/>v

On the wizard step you will need to add the same taglib definition above (but not
the applet tag) and the following tag. This tag will render the actual primary
attachment input components such as the file chooser or the url inputs.
<attachments:primaryAttachment/>

Adding secondary attachments to a wizard


To add secondary attachment support to a wizard of an object that implements the
ContentHolder interface you will need to add the applet tag to the main
wizard jsp and the attachments wizard step.

Customizing HTML Clients Using the Windchill JSP Framework 341


On the main wizard jsp (which defines the <jca:wizard tag and the wizard
steps) add the following tag definition and
fileSelectionAndUploadApplet tag. The tag will render a tiny applet
which is used for file browsing and file uploading.
<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

<attachments:fileSelectionAndUploadApplet/>

Inside your wizard definition (inside the <jca:wizard tags) add the following
wizard step in the order that you would like it to appear.
<jca:wizardStep action="attachments_step" type="attachments" />

Note
Attachments are not supported in Change Task wizards.

Adding primary attachments to an info page


On your info page jsp you will need to add the following inside the
describePropertyPanel tags to get the primary attachment info and
download icon included in the info page attributes.
<jca:describeProperty id="primaryAttachmentProperties" label="${primaryLabel}"/>

To get it on the additional attributes info page add this to your object's
attributes.jsp
<jsp:include
page="/netmarkets/jsp/attachments/attachments_table.jsp"
flush="true">

<jsp:param name="role" value="PRIMARY" />

</jsp:include>

Adding secondary attachments to an info page


On your object's attributes.jsp add the following to get the secondary
attachments to show up under the more attributes sub navigation of the info page.
<jsp:include
page="/netmarkets/jsp/attachments/attachments_table.jsp"
flush="true">
<jsp:param name="role" value="SECONDARY" />
</jsp:include>

342 Customization Guide


Adding Primary attachment actions to an object
In the action model xml file that defines the action model with the menufor
attribute for your object type add the following actions. This will provide
download or url redirect actions depending on if the object has a primary file or
url.
<action name="download_primary_attachment"
type="attachments"/>

<action name="redirect_primary_attachment"
type="attachments"/>

<action name="checkout_and_download" type="wip"/>

<action name="replace_content" type="wip"/>

Customization Points
<primaryAttachment> tag attributes

Parameter Default Possible Req? Description


Value Values
allowFile true True/False no Allows the Local File
option to be displayed.
allowUrl true True/False no Allows the URL Link
option to be displayed.
allowExternal true True/False no Allows the External
Storage option to be
displayed.

Customizing HTML Clients Using the Windchill JSP Framework 343


<primaryAttachment> tag attributes (continued)
Parameter Default Possible Req? Description
Value Values
fixedFilePath null Valid file no Renders the file path
path specified instead of
allowing the user to
choose the file. If
fixedFileUpload param
on this tag and the
forceApplet param on
the
fileSelectionAndUpload
Applet tag are both set
this can be used to force
the specified file to be
uploaded and attached to
the object.
forceApplet False True/False no Determines if we should
force the applet to be
rendered regardless of
the upload mechanism
preference

How to hide primary content for an object


In order to hide primary content for an object you will need to do the reverse of
the above five procedural steps by removing those entries from the wizards, jsp’s,
and the action model. You will also need to modify \codebase\
netmarkets\jsp\wip\checkin_step.jsp and remove the if block for
FormatContentHolder with the page include for the
FormatContentHolder page (leave the
“getRespectiveNonFormatContentHolderPage” include there).

Additional notes about documents:


For documents only (not other FormatContentHolders) you will find
similar entries in the wizard jsp’s but they may slightly vary by referring to an
MSOI tag which extends the attachments tags. Removing these tags will remove
primary attachments from documents but it will also render desktop integration
useless since desktop integration depends on having file primary attachments. You
will also need to remove the createMulti action from all action models since
it depends on primary content.

344 Customization Guide


How to remove url & external data options
On the primaryAttachment tag you may set the allowUrl and
allowExternal attributes to false. In the event that you wish to disable url and
external data options for documents only you can modify the following file.
codebase\WEB-INF\tags\primaryAttachmentWithMSOI.tag

Limitations

Primary content
For primary attachments code to function properly you need both the
primaryAttachment tag as well as the
fileSelectionAndUploadApplet tag, regardless of whether or not you
are using applet upload. While some behavior can be controlled by custom code
we highly recommend that you first try adjusting the site level preferences and tag
attributes to accomplish your goal before customizing your code.
The fileSelectionAndUploadApplet tag must be on the jsp that defines
the wizard but outside of the wizard tags or it will not function properly.

Secondary content
For secondary attachments code to function properly you need attachments step
defined in your wizard as well as the fileSelectionAndUploadApplet
tag, regardless of whether or not you are using applet upload. The
fileSelectionAndUploadApplet tag must be on the jsp that defines the
wizard but outside of the wizard tags or it will not function properly.

Customizing HTML Clients Using the Windchill JSP Framework 345


Sample Code

Examples of Usage in Windchill Code

Secondary attachments
Excerpt from the create change request wizard (<Windchill>\codebase\
netmarkets\jsp\changeRequest\create.jsp).
...

%><%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments"

...

<jca:wizard helpSelectorKey="change_createChangeRequest"
buttonList="DefaultWizardButtonsWithSubmitPrompt"
formProcessorController="com.ptc.windchill.enterprise.change2.form
s.controllers.ChangeRequestFormProcessorController">

...

<jca:wizardStep action="attachments_step" type="attachments"


/>

...

</jca:wizard>

<attachments:fileSelectionAndUploadApplet/>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Primary attachments
Wizard JSP
<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

...

<jca:wizard buttonList="DefaultWizardButtonsWithSubmitPrompt">

...

346 Customization Guide


<jca:wizardStep action="attributes_step" type="attachments"
/>

...
</jca:wizard>

.<attachments:fileSelectionAndUploadApplet/>

...

Attributes Step JSP


<%@taglib prefix="attachments"
uri="http://www.ptc.com/windchill/taglib/attachments" %>

...

<attachments:primaryAttachment>

...

Customizing HTML Clients Using the Windchill JSP Framework 347


Attribute Panels
You want to display attributes of a Windchill object in a name: value format. The
attribute values could be read-only or editable.
The practices described in this section should be used when you want to display
attributes of a single Windchill object for viewing or editing. The attribute panel
object may or may not be TypeManaged, however to configure the panel from a
layout it must be TypeManaged.

Intended Outcome
After reading this document you should be able to create simple and advanced
attribute panels in either edit or view mode. Specifically, you will learn how to:
• Create advanced attribute panels using Type Management layouts
• Create simple and advanced attributes panels by manually configuring the
panels in a Java builder class
• Create simple attribute panels using JSP tags
• Include your panel in a JSP page
• Convert custom attribute panels/tables created in Windchill Release 9.0 or
later to Windchill Release 10.0 attribute panels

Background
Windchill provides an attribute panel component that can be used to display
attributes of a Windchill object. Typically, these are used to display attributes in
read-only mode on object info pages or in edit mode in wizards. Attribute panels
can be configured to be a simple list of name:value pairs or they can be
configured to have a more complex layout with:
• A border
• Attribute groups, each with a title and expand-collapse capability
• Multiple columns
The former will be referred to in this document as “simple attribute panels” and
the latter as “advanced attribute panels.”

Attribute Panel Examples


This is an example of a simple view-only attribute panel:

348 Customization Guide


This is an example of a simple editable attribute panel:

This is an example of an advanced view-only attribute panel with two groups and
multiple columns in each group:

This is an example of an editable advanced attribute panel with a single group and
one column:

Customizing HTML Clients Using the Windchill JSP Framework 349


The advanced panel layout features are new for Windchill Release 10.0.
Previously, only simple attribute panels, formerly called property panels, were
used:

Also, prior to Windchill Release 10.0, object attributes were sometimes displayed
in table format rather than in panels:

The attribute table format is no longer used in Windchill 10.0, although


customizations using the attribute table component will continue to work.

350 Customization Guide


Definition of Terms
Definition of terms used in this section.
Term Definition
simple attribute panel A single-column list of attribute name:
value pairs
advanced attribute panel Attribute name:value pairs
contained in one or more groups, each
with a title and an example-collapse
feature. Groups may have multiple
columns of attribute pairs. A border
surrounds the entire panel.
context object The context object for a panel, typically
derived from a URL parameter such as
“oid”
datum object The object that is passed to the data
utilities that create the data model for
the panel. The datum is created by the
buildComponentData() method
of builder classes. Also sometimes
called “row object.” See NmObject
Utilities on page 590 for more
information.
target object May be used when the datum for the
panel is a composite object. The target
object specifies the specific member of
the datum object that should be used for
the panel or attribute within the panel.
For example, if your datum was a
WTPartUsageLink, you could
specify a target object of
RoleAObject.
The target object must be addressable
from the datum object.
See NmObject Utilities on page 590 for
more information.

Customizing HTML Clients Using the Windchill JSP Framework 351


Solutions

Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:
• The JSP-based client architecture framework in Windchill
• The Windchill MVC builder framework
• Lightweight Customization (LWC) in Windchill using the Windchill Type and
Attribute Management utility
• JSPs, tag libraries, and JSTL
The Additional Resources on page 387 section includes references to many or all
of these subjects.

Overview
Both simple and advanced attribute panels can be created using Java builder
classes. Simple attribute panels can also be created using only JSP tags in certain
limited cases. When a builder class is used to create a panel for a TypeManaged
object, the contents and configuration of the panel can be defined in a layout in the
Type and Attribute Management utility and retrieved by the builder class.
Alternatively, the contents and configuration of the panel can also be defined in
the builder itself. The recommended approach is to:
• Use a layout-based based panel created by a Java builder whenever possible.
This provides:
○ easier customization
○ a UI for ease of configuration
○ greater reusability
○ a more consistent product
• Use a non-layout based panel created by a Java builder if:
○ The object type being displayed is not TypeManaged or
○ The type is TypeManaged but layouts are already defined for all related
screen types and none are appropriate for your purpose
• Use a JSP-tag based panel only if:
○ You want to create a simple attributes panel and
○ You only want to display a few attributes which do not require complex
configurations and

352 Customization Guide


○ You don’t want the overhead of creating a builder class
The system provides OOTB builders for several layout-based advanced attribute
panels used for common, shared actions. These actions are:
Action Name Action Object Component Description
Type Builder ID
visualizationAn- object ComponentId. Used to display the
dAttributes VIS_AND_ “Visualization and
ATTRIBUTES Attributes” panel
on information
pages
primaryAttrbutes object ComponentId. Used to display the
PRIMARY_ “Attributes” panel
ATTRIBUTES on information
pages of object
types that have no
visualization
component
attributes object ComponentId. Used to display the
ATTRIBUTES_ID “More Attributes”
panel on
information pages

To display these panels you just specify the appropriate component builder id in
the URL or action used to generate the panel on your page. You do not need to
write any Java code or JSPs. The system also provides OOTB builders for the
layout-based “Attributes” panels in object create and edit wizards that can be
displayed by using the common step actions for wizards.
To display a panel for a different layout or create a manually-configured panel you
can extend an existing Java builder class.
The decision diagram below provides general guidelines for how you should
determine which builder to use for your panel, with references to the section of
this document that describes the builder.

Customizing HTML Clients Using the Windchill JSP Framework 353


354 Customization Guide
Solution Elements
Element Type Description
Type and Attribute Application The application where
Management utility you can:
• Define attributes on a
type
• Define attribute
layouts
• Configure the display
properties of an
attribute
See Type and Attribute
Management for more
information about this
utility.
MVC Builder Java class Creates the configuration
and datum object for the
panel. Also can be used to
specify the view (JSP) for
the panel if a custom view
is desired.
AttributePanelConfig Java class The object that contains
theGroupConfig(s) for
an attribute panel. Also
has several properties that
can be used to configure
the panel.
GroupConfig Java class The object that contains
the
AttributeConfig(s)
for an attribute panel.
Also has several
properties that can be
used to configure the
group.
AttributeConfig Java class Contains information
about one attribute to be
displayed in the panel,
including its name and
properties that control
how the attribute should

Customizing HTML Clients Using the Windchill JSP Framework 355


Element Type Description
be displayed.
ComponentConfigFactory Java class A factory that generates
AttributePanelCon
figs, GroupConfigs,
and
AttributeConfigs
TypedAttrLayOutFactory Java class A factory capable of
generating an attribute
panel configuration from
a Type Management
layout for a given object
type and screen type
ScreenDefinitionName Java enum Identifiers for the screen
types shown in the Type
and Attribute Management
utility Layouts tab. For a
given object type each
screen type maps to one
layout. However, a layout
may map to more than
one screen type.
ComponentId Java class Contains constants for
some widely used
component builder ids.
ComponentMode Java enum Determines whether
view-only or input fields
are displayed for
attributes.
ComponentType Java enum Indicates how the
attribute panel is being
used. The
ComponentType can
affect such things as
whether or not an
attribute is visible or
hidden, how an attribute
is displayed (e.g., link vs
text), and the HTML
name given to an input
field.

356 Customization Guide


Element Type Description
If the ComponentType
is WIZARD_
ATTRIBUTES_TABLE
the system will give
attribute input fields
HTML names that the
system can use to set the
attribute values on the
object for you. If you
want to set all the
attribute values yourself
in a form processor, you
should use the component
type WIZARD_TABLE.
<Windchill>/codebase/ JSP Default view JSP for an
WEB-INF/jsp/ advanced attribute panel.
components/ Occasionally, you may
attributePanel.jsp. need to use a custom JSP
for the view if you want
to display additional
components on the page
or include additional
javascript.
<Windchill>/codebase/ JSP Default view JSP for a
WEB-INF/jsp/ simple attribute panel.
components/ Occasionally, you may
simpleAttributePanel.jsp need to use a custom JSP
for the view if you want
to display additional
components on the page
or include additional
javascript.

Customizing HTML Clients Using the Windchill JSP Framework 357


Solution – Create an Advanced Attribute Panel with a
Visualization Component Using the Primary Attributes
Layout
This is a composite panel comprised of:
1. The visualization component for the object type, if any, and
2. The attributes in the layout that maps to the screen type “Information Page -
Primary Attributes" (ScreenDefinitionName.INFO) for the type of the
object displayed in the panel
This builder is invoked by the “visualizationAndAttributes” action
defined for the type “object.” This action is widely used to display the
Visualization and Attributes component on object info pages:

The component builder id for this builder is


“visualizationAndAttributes” (ComponentId.VIZ_AND_
ATTRIBUTES).
See the javadoc for VisualizationAttributesBuilder for more
information.
To include this panel in your page you only need to specify the component builder
id in the panel action or URL. See How to Find an Attribute Name/Id on page 376
for more information on how to include panels in a JSP page.
If you have created a new Windchill type for which you would like to define a
unique Visualization and Attributes panel, you will typically only need to define a
layout for the INFO screen type in the Type and Attribute Management utility and
possibly create a visualization delegate to display the visualization component.
In the rare cases where you need to modify some aspect of the panel, such as the
view JSP, you should create a custom builder extending the
VisualizationAttributesBuilder. You might want to modify the view JSP to include
additional components or javascript on the page. See Customizing Information
Page Components on page 972 for more information.

358 Customization Guide


Solution – Create an Advanced Attribute Panel Without a
Visualization Component Using the Primary Attributes
Layout
This is a panel identical to that described the previous section, but with no
visualization component. It is created using the builder class
PrimaryAttributesBuilder. The component builder id for this panel is
“primaryAttributes” (ComponentId.PRIMARY_ATTRIBUTES).
This builder is invoked by the “primaryAttributes” action defined for the
type “object.” This action is used to display the “Attributes” component on
object information pages for types that do not have a visualization component:

See the javadoc for PrimaryAttributesBuilder for more information.


To include this panel in your page you only need to specify the component builder
id in the panel action or URL. See How to Find an Attribute Name/Id on page 376
for more information on how to include panels in a JSP page.

Customizing HTML Clients Using the Windchill JSP Framework 359


Solution – Create an Advanced Attribute Panel Using the
Create, Edit, or More Attributes Screen Type Layout
The system provides the builder TypedAttributesPanelBuilder:
• Information Page – More Attributes (ScreenDefinitionName.MORE_
ATTRIBUTES)
• Create New (ScreenDefinitionName.CREATE)
• Edit (ScreenDefinitionName.UPDATE)

Note
For a few objects the system has defined subclasses of
PrimaryAttributesBuilder for the default builder.

This builder has the component builder id “attributesTable”


(ComponentId.ATTRIBUTES_ID) and is used for the following actions
defined for object type “object”:
• “attributes”
The action typically used to display the component typically labeled “More
Attributes” on object information pages
• “defineItemAttributesWizStep”
Action which uses this builder indirectly to create the “Attributes” panel in
object creation wizards. See Customizing Reusable Wizard Steps on page 928
for more information.

360 Customization Guide


• “editAttributesWizStep”
Action which uses this builder indirectly to create the “Attributes” panel in
object edit wizards. See Customizing Reusable Wizard Steps on page 928 for
more information.

See the javadoc for TypedAttributesPanelBuilder for more information


on the ComponentMode, ComponentType, view JSP, and datum object used
for these panels. Note that the wizard panels have a ComponentType of
ComponentType.WIZARD_ATTRIBUTES_TABLE so that the editable fields
will be given HTML names such that the wizard processing framework can

Customizing HTML Clients Using the Windchill JSP Framework 361


identify the attributes that it should automatically set on the object being created
or edited. See Building Wizards to Create a Single Object on page 892 for more
information.
To include the “More Attributes” panel in your page you only need to specify the
component builder id in the panel action or URL See How to Find an Attribute
Name/Id on page 376 for more information on how to include panels in a JSP
page. To include the wizard panels in a wizard, use the common wizard step
actions shown above.
If you have created a new Windchill type for which you would like to display one
of these panels, you will typically only need to define a layout for the appropriate
screen type in the Type and Attribute Management utility. In the rare cases where
you need to modify some aspect of the panel, such as the view JSP, you should
create a custom builder extending the TypedAttributesPanelBuilder.
See Customizing Information Page Components on page 972 for more
information.
To modify the attributes displayed in these panels and their display properties you
can modify the layout in the Type and Attribute Management utility. If it is
necessary to modify a configuration property or the view JSP for a special use
case, you can extend TypedAttributesPanelBuilder and override the
buildAttributeComponentConfig() method (see Solution – Create an
Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute
Management Utility on page 363). However, this should be avoided if at all
possible as it will make the product less consistent.
The following configuration properties are not overridable:
• ComponentMode of the panel
• ComponentType of the panel
• Datum object
If you want to modify any of these elements, you should write a custom builder
extending AbstractComponentBuilder. See Solution – Create an
Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute
Management Utility on page 363 for more information.

362 Customization Guide


Solution – Create an Advanced Attribute Panel Using Any
Layout Defined in the Type and Attribute Management
Utility
Create an advanced attribute panel using a layout defined in the Type and Attribute
Management utility. Attributes may be editable, view-only, or a combination of
editable and view-only.
1. The attributes of the object type and their display properties are defined in the
Type and Attribute Management utility and in the Java class file for the type.
2. The layout and content of the attribute panel are defined in the Type and
Attribute Management utility.
3. A MVC Java builder class builds the panel configuration from the layout
definition using the TypedAttrLayOutFactory. It also retrieves/creates
the datum object for the panel.
4. GUI components for the attributes are created by data utilities.
5. The attributes and their data are rendered in a view JSP by the rendering
framework using the configuration and data model created by the builder and
the data utilities.
See Advanced Panel with Modified Context Object on page 392 for an example of
this solution.

Procedure – Creating the Attribute Panel


Either the builder
com.ptc.jca.mvc.buildersTypedAttributesPanelBuilder or
the builder com.ptc.mvc.components.AbstractComponentBuilder
can be extended for creating a panel that is layout-based. If want to use the
ComponentMode, ComponentType, and datum object set by the
TypedAttributesPanelBuilder (refer to Solution – Create an Advanced
Attribute Panel Using the Create, Edit, or More Attributes Screen Type Layout on
page 360 above) , you can extend the TypedAttributesPanelBuilder for
convenience. Otherwise, you should extend the
AbstractComponentBuilder.

Extending the TypedAttributesPanelBuilder


The panel produced by this builder by default is described in Solution – Create an
Advanced Attribute Panel Using the Create, Edit, or More Attributes Screen Type
Layout on page 360.
This builder calls the TypedAttrLayOutFactory to create the
AttributePanelConfig and nested GroupConfigs and
AttributeConfigs for the panel. In your custom builder you can modify the
screen type used to look up the layout for the panel or the view used to render the
panel.

Customizing HTML Clients Using the Windchill JSP Framework 363


Typically, the configuration of the group(s) and attributes in the panel should be
done in the Type and Attribute Management utility layout for consistency of the
product. However, on rare cases you might have the need to modify a
configuration property. For such a special use case, you can also postprocess the
config objects created by the factory to modify configuration properties, such as
the title of a group, the display mode of an attribute (editable/view-only), or the
selection list style of a Boolean attribute. Most of the group and attribute
configuration properties set in the Type and Attribute Management utility can be
overridden in the builder class by setting properties on the GroupConfigs or
AttributeConfigs. See Customization Points on page 380 for a list of
configurable properties.

Modifying the Panel Configuration


To modify the panel configuation, override the
buildAttributePanelConfig() method. The
buildAttributePanelConfig() method creates an
AttributePanelConfig.
Examples of some configuration changes you might want to make are:
• The Type and Attribute Management utility layout to be used for the panel.
○ To use a different screen type for the layout lookup, use the
TypedAttrLayOutFactory to retrieve a different
AttributePanelConfig :
getTypedAttrLayOutFactory().getAttributePanelConfig(getComponentConfigFactory(),
params, ScreenDefinitionName.<your screen type>);

The class ScreenDefinitionName lists the available screen types.


• Change the ComponentMode of one or more of the attribute fields to view-
only in an editable attribute panel or vice versa.
○ If the component mode is not specifically set on the attribute’s
ComponentConfig, the component mode defined for the panel will be
used.
○ See Modifying a Property of an AttributeConfig in an
AttributePanelConfig Created by the TypedAttrLayOutFactory on page
386 example code in for how to make a single field editable or view-only.
• The label for a group within the panel or an individual attribute.
○ This can be specified by calling setLabel() method on the group or
attribute config.

Modifying the Panel View (JSP)


See How to Modify the Panel View JSP on page 376

364 Customization Guide


Modifying the Panel Context Object
See How to Modify the Panel Context Object on page 377

Extending the AbstractComponentBuilder


Because you want a layout-based panel, your custom builder should implement
com.ptc.mvc.components.TypedAttrLayOutFactoryAware,
which will give you access to an instance of the TypedAttrLayOutFactory
which you will need to obtain configs based on a layout.
The AbstractComponentBuilder does not provide any default behavior so
you will need to write the following methods from scratch:
• public void setTypedAttrLayOutFactory(TypedAttrLayOutFactory factory)
• protected AttributePanelConfig buildComponentConfig(ComponentParams
params)
• public Object buildComponentData(ComponentConfig config,
ComponentParams params)

setTypedAttrLayOutFactory()
The TypedAttrLayOutFactory is used to create panel configs based a given
screen type. You should declare a global variable of that type and implement this
method, as follows:
TypedAttrLayOutFactory tfactory;
public void setTypedAttrLayOutFactory(TypedAttrLayOutFactory factory) {
this.tfactory = factory;
}

The framework will call this method to provide you with an instance of the
factory.

buildComponentConfig()
This method should create the AttributePanelConfig by calling the
TypedAttrLayOutFactory and passing it the ScreenDefinitionName
corresponding to the layout you want to use for your panel. For example:
AttributePanelConfig panelConfig =
tfactory.getAttributePanelConfig(getComponentConfigFactory(), params,
ScreenDefinitionName.CREATE);

The AttributePanelConfig that is returned will have nested


GroupConfigs and AttributeConfigs as defined in the layout.
If desired, you can tweak the configs that are returned by the factory to modify
any of the configuration properties listed in Customization Points on page 380.
See Procedure – Creating the Attribute Panel on page 363 for some examples.

Customizing HTML Clients Using the Windchill JSP Framework 365


Also see How to Modify the Panel View JSP on page 376 and How to Modify the
Panel Context Object on page 377

buildComponentData()
This method should return a single datum object for the panel. For view-only
panels, this is typically a Persistable object instance. For wizards, this should
usually be a TypeInstance, which will contain the constraints that have been
defined for the attributes in addition to the attribute values.
To return a Persistable datum object, it is typically appropriate just to return the
context object, as follows: Object datumObject =
params.getContextObject();
Alternatively, you could query for the Persistable object.
To obtain a TypeInstance datum object for a create or edit wizard, you can
call CreateAndEditModelGetter.getItemAttributes() as
described in Obtaining a TypeInstance Datum Object on page 386. Alternatively,
you could use TypeInstance APIs to obtain the TypeInstance.

366 Customization Guide


Solution – Create a Simple or Advanced Attribute Panel
Using a Configuration Created in a Java Builder Class

Overview
Create a simple or advanced attribute panel using a configuration defined in a Java
builder class. Attributes may be editable, view-only, or a combination of editable
and view-only. This approach is applicable for object types that are not
TypeManaged. It may also be used for TypeManaged objects, but we recommend
you use layout-based panels for those types whenever possible, for ease of
customization and other reasons cited earlier.
1. The attributes of the object type and their display properties are defined in the
Java object class file or in the Type and Attribute Management utility.
2. A MVC Java builder class creates the panel configuration and retrieves/creates
the datum object for the panel.
3. GUI components for the attributes are created by data utilities.
4. The attributes and their data are rendered in a view JSP by the rendering
framework using the configuration and data model created by the builder and
the data utilities.
Examples of this solution are given in:
• Advanced Attribute Panel on page 389
• Advanced Attribute Panel in a Wizard on page 390
• Advanced Attribute Panel on an Information Page on page 391
• Simple Attribute Panel using a Java Builder on page 394
• Simple and Advanced Attribute Panels in a Wizard on page 396

Procedure – Creating the Attribute Panel


Either the builder
com.ptc.jca.mvc.builders.AbstractAttributesComponent
Builder or the builder
com.ptc.mvc.components.AbstractComponentBuilder can be
extended for creating a panel that is not layout-based. .
The AbstractAttributesComponentBuilder sets the
ComponentMode and datum object as described in the class javadoc. These
configurations are not overridable. If you want your panel to be configured as
described, you can extend AbstractAttributesComponentBuilder for
convenience. Otherwise, you should extend AbstractComponentBuilder.

Customizing HTML Clients Using the Windchill JSP Framework 367


Extending AbstractAttributesComponentBuilder

Creating the Panel Configuration


1. Implement the buildAttributesComponentConfig() method to
create the panel configuration.
a. Create the panel config.
Call the ComponentConfigFactory embedded in the class to create
an AttributePanelConfig.
ComponentConfigFactory factory = getComponentConfigFactory();
AttributePanelConfig panelConfig = factory.newAttributePanelConfig
(<id of your component>);

Set the desired properties on the panel config. See AttributePanelConfig


Properties on page 380 for configuration points. Do not set the component
mode as it will be overridden by the parent class. Also, do not set the
ComponentType in this method, that can be done in step 2.
b. Create the attribute and group configs.
Every panel must have at least one group. Simple attribute panels must
have only one group, which will not be visible in the UI. For simple
attribute panels, you can use the technique described in Case 1 below,
which will automatically create a group config for you. For advanced
attribute panels, use the technique in Case 2 below to create one or more
groups with labels of you choosing.
Case 1: Simple attribute panel
i. Create one attribute config for each attribute you want to display using
the ComponentConfigFactory :
AttributeConfig attrConfig = factory.newAttributeConfig
(“<attribute name>”);

Set additional properties on the AttributeConfig if desired. See


AttributeConfig Properties on page 383 for configuration points. Note
you should not set rowPos, colPos, or colSpan properties on
AttributeConfigs for simple attribute panels.
ii. Add the attribute configs to the panel as follows:
panelConfig.addComponent(attrConfig);

The addComponent() method will create a group config


automatically the first time it is called.

368 Customization Guide


Case 2: Advanced attribute panel
i. Create at least one GroupConfig using the
ComponentConfigFactory :
GroupConfig groupConfig = factory.newGroupConfig
("<id of your group>");
groupConfig.setLabel("<your group label>");

The label is the title that will be displayed in the UI and should be
localized from a resource file if appropriate:

Set the desired properties on the GroupConfig. See GroupConfig


Properties on page 382 for configuration points.
ii. Create the attribute configs and add them to the group config.
Create an AttributeConfig for each attribute you want to display
in the panel using the ComponentConfigFactory. For example:
AttributeConfig attrConfig = factory.newAttributeConfig(“<attribute name>”);

Set the desired properties on each attribute config. See AttributeConfig


Properties on page 383 for configuration points.
Add each AttributeConfig to the GroupConfig :
groupConfig.addComponent(attrConfig);

iii. Add the group config to the panel config.


panelConfig.addComponent(groupConfig);

2. Override the getComponentType() method to set the component type of


the panel, if desired. If you do not override this method, the parent class will
set the ComponentType as described below.
• If ComponentMode is ComponentMode.VIEW, ComponentType is
set to ComponentType.INFO_ATTRIBUTES_TABLE
• Otherwise, ComponentType is set to ComponentType.TABLE
If the panel is to be displayed in a create or edit wizard and contains attributes
you want the framework form processors to set automatically for you, you
should return component type ComponentType.WIZARD_ATTRIBUTES_
TABLE. Otherwise, you can accept the default setting for wizard panels.

Modifying the Panel View (JSP)


See How to Modify the Panel View JSP on page 376 for more information.

Customizing HTML Clients Using the Windchill JSP Framework 369


Modifying the Panel Context Object
See How to Modify the Panel Context Object on page 377 for more information.

Extending AbstractComponentBuilder
You will need to implement two methods in your builder:
• ComponentConfig buildComponentConfig(ComponentParams params)
• Object buildComponentData(ComponentConfig config, ComponentParams
params)

buildComponentConfig()
This can be implemented as described in Procedure – Creating the Attribute Panel
on page 367 above except that you will also need to set the ComponentMode
and ComponentType of the panel in this method. You do that by calling the
following methods on the AttributePanelConfig :
setComponentMode(ComponentMode)
setComponentType(ComponentType)

This is also where you should set a custom view JSP, if desired.

buildComponentData()
See Procedure – Creating the Attribute Panel on page 363 for more information.

370 Customization Guide


Solution - Create a Simple Panel Using JSP Tags

Overview
Use JSP tags to configure, acquire the data for, and display a simple attribute
panel. Attributes may be editable, view-only, or a combination of editable and
view-only. The type of the context object may or may not be TypeManaged.
1. Use the describePropertyPanel tag to define the attributes to be
displayed in the panel and other configuration properties.
2. Use the getModel tag to specify a server method that should be called to
retrieve the datum object for the panel.
3. The getModel tag calls data utilities to create GUI components for the
attributes
4. Use the renderPropertyPanel tag to display the panel on the JSP page.
An example of this solution is given in section Simple Attribute Panels using JSP
Tags on page 395.

Procedure – Creating the Attribute Panel


Create the JSP page in which you want to display your panel. This could have
other components in addition to your attribute panel. Include the following taglib
directive in your JSP page:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

Describe the Attribute Panel


To describe the property panel use the describePropertyPanel and
describeProperty tags:
<jca:describePropertyPanel var="<name of the descriptor>">>
<jca:describeProperty id="<attribute name>" />
<jca:describeProperty id="<attribute name>" />
<jca:describeProperty id="<attribute name>" />
</jca:describePropertyPanel>

The name of the descriptor can be any name that identifies your panel. It will be
used as the name of the variable in the JSP context that holds the panel descriptor
object.
Both of these tags have optional attributes that can be used to configure how the
GUI components for attributes are created and/or displayed. See the javadoc for
the tags for more information.

Customizing HTML Clients Using the Windchill JSP Framework 371


Acquire the Data Model for the Attribute Panel
The getModel tag will acquire a datum object for the panel by calling a service
method you specify. It will then call the data utilities to produce the GUI
components for the attributes using the datum object. For example:
<jca:getModel var="<name of the data model>"
descriptor="${<name of the descriptor>}"
serviceName="wt.fc.StandardPersistenceManager"
methodName="refresh">
<jca:addServiceArgument value="${commandBean.primaryOid.oid}"
type="wt.fc.ObjectIdentifier" />
</jca:getModel>

The value for <name of the data model> can be any name you wish to
assign to your model. It will be used as the name of a scoped variable in the JSP
context that will hold the created data model.
The value for <name of the descriptor> should be that used in your
describePropertyPanel tag.
The serviceName and methodName parameters specify a service method that
should be called to acquire the datum object for the model. The
addServiceArgument subtag can be used to pass parameters to the service
method. Typically, the StandardPersistenceManager.refresh()
method is used to acquire a Persistable for the daum object of view-only panels.
For example:
<jca:getModel var="propertyModel" descriptor="${propertyPanelDesc}
"serviceName="wt.fc.StandardPersistenceManager" methodName="refresh">
<jca:addServiceArgument value="${commandBean.primaryOid.oid}
" type="wt.fc.ObjectIdentifier" />
</jca:getModel>

Alternatively, a query command or service method can be called to retrieve the


datum object.
The datum object for a wizard panel should typically be a TypeInstance. The
CreateAndEditModelGetter.getItemAttributes() method can be
used to acquire a TypeInstance datum object for wizards that include an
initializeItem tag. For example:
<jca:getModel var="attributesTableModel" descriptor="${meetingPanelModel}"
serviceName="com.ptc.core.components.forms.CreateAndEditModelGetter"
methodName="getItemAttributes">
<jca:addServiceArgument value="${ meetingPanelDescriptor }"
type="com.ptc.core.components.descriptor.ComponentDescriptor"/>
<jca:addServiceArgument value="${commandBean}"
type="com.ptc.netmarkets.util.beans.NmCommandBean"/>
<jca:addServiceArgument value="${nmcontext.context}"
type="com.ptc.netmarkets.util.misc.NmContext"/>

372 Customization Guide


</jca:getModel>

See the getModel tag javadoc for more information.

Render the Property Panel


To render the property panel use the renderPropertyPanel tag. For
example:
<jca:renderPropertyPanel model="${<name of the data model>}"/>

The value for <name of the data model> should be that used in your getModel tag.

Customizing HTML Clients Using the Windchill JSP Framework 373


Converting a Tag-based Attribute Panel to a MVC Attribute
Panel
In prior releases all attribute panels, known as “property panels,” were created and
displayed using the tag-based approach described in the preceding section. Also,
in prior releases, it was possible to create attribute tables, which were very similar
in construction except that a describeAttributesTable tag was used
instead of a describePropertyPanel tag and a renderTable tag was
used instead of a renderPropertyPanel tag.
Such panels and attribute tables can fairly easy be converted to MVC attribute
panels, as outlined below. Note that if you convert a panel or table to a MVC
panel, you should be sure to remove any
*typedservices.properties.xconf file entries related to the panel or
table in addition to removing the related JSP files.
If the panel is for a custom object type that is Typed and it corresponds to one of
the screen types for which an OOTB builder class is available (see section
Solution – Create an Advanced Attribute Panel with a Visualization Component
Using the Primary Attributes Layout on page 358, Solution – Create an Advanced
Attribute Panel Without a Visualization Component Using the Primary Attributes
Layout on page 359, and Solution – Create an Advanced Attribute Panel Using the
Create, Edit, or More Attributes Screen Type Layout on page 360), you should
simply define a layout for that screen type in the Type and Attribute Management
utility. Add each attribute included in your describePropertyPanel/
describeAttributesTable tag to the layout. Most of the configuration
attributes available for the tags can be defined in the Type and Attribute
Management utility.
To display your panel, use one of the techniques described in How to Include an
Attribute Panel in a JSP Page on page 377. You do not need to write a Java builder
class unless you need to use a different view JSP or datum object than that defined
by the OOTB builder. Note: if your custom object type does not implement Typed,
you can modify it to implement TypeManaged so that it will be displayed in the
Type and Attribute Management utility and layouts can be defined for it.
If your custom object type is Typed or TypeManaged and your panel is for one of
the screen types available in the Type and Attribute Management utility for which
no OOTB builder exists, you should create a layout in the Type and Attribute
Management utility for that screen type. Add each attribute included in your
describePropertyPanel/ describeAttributeTable tag to the
layout and configure its display in the Type and Attribute Management utility based
on the attributes you had included in your describeProperty tag. You will
also need to create a Java builder class to create an AttributePanelConfig
from the layout (see Solution – Create an Advanced Attribute Panel Using Any
Layout Defined in the Type and Attribute Management Utility on page 363). In
your Java builder class, you should include a buildComponentData() method that

374 Customization Guide


creates the panel datum object by calling the same method invoked by your
getModelTag(). To render the panel, use one of the techniques described in How
to Include an Attribute Panel in a JSP Page on page 377.
If you choose not to make your object type TypeManaged or the panel is not for
one of the available screen types, create a Java builder class for your panel as
described in Solution – Create a Simple or Advanced Attribute Panel Using a
Configuration Created in a Java Builder Class on page 367, following the
techniques for a simple attribute panel. Note that:
• The AttributePanelConfig created by your builder’s
buildComponentConfig() or
buildAttributesComponentConfig() method corresponds to the
config created by your describePropertyPanel/
describeAttributesTable tag. Translate any attributes on your tag to
the equivalent properties on the AttributePanelConfig. See How to
Modify the Panel Context Object on page 377 for how to modify the panel
context object, which corresponds to the “oid” attribute of the
describePropertyPanel tag.
• The AttributeConfigs created by your builder correspond to the configs
created by your describeProperty tag. Translate any attributes on your
describeProperty tag to the equivalent properties on the
AttributeConfig.
• The buildComponentData() method of the builder corresponds to the
getModel tag. You can call the same method to acquire the panel datum
object in your buildComponentData() method as you did from your
getModel() tag.
• The tag <mvc:simpleAttributePanel> corresponds to the
renderPropertyPanel/renderTable tag. This tag is called by the
view JSP <Windchill>/codebase/WEB-INF/jsp/components/
simpleAttributePanel.jsp. Typically, you should specify that JSP
view by calling the setView() method on the AttributePanelConfig
in your builder. Note that the default component id used for
AttributePanelConfigs is attributePanel. If you specified a
compId attribute on your tag you may need to create a custom JSP view page
for your panel and set the view to that JSP. In your custom JSP, you should set
the component id by including a compIdattribute on the
<mvc:simpleAttributePanel> tag.

Customizing HTML Clients Using the Windchill JSP Framework 375


General Procedures

How to Annotate Your Custom Builder Class


You should annotate your builder class with the component builder id you will use
for your panel. You should also include a TypeBased annotation if you want to
use different builders for different object types for the same component builder id.
For example:
@ComponentBuilder(“exampleBuilderId”)
@TypeBased(value = "com.acme.SomeType")
public class ExamplePanelBuilder extends TypedAttributesPanelBuilder

How to Find an Attribute Name/Id


When creating an AttributeConfig or a describeProperty tag you
must specify the name/id of the attribute.
See How to Find an Attribute ID on page 706 for more information.

How to Access Request and Context Information in Builder Methods


The ComponentParams parameter passed to buildComponentConfig()
and uildComponentData () method is an instance of the concrete class
JcaComponentParams. This class provides you access to all the request
parameter values and attributes, as well as the typical beans used by JCA clients,
such as the NmCommandBean, NmSessionBean, and NmContextBean.
See Windchill Client Architecture Common Objects Overview on page 245 for
more information on these classes.

How to Modify the Panel View JSP


The view is defined in the AttributePanelConfig. By default it is
<Windchill>/codebase/WEB-INF/jsp/components/
attributePanel.jsp, which is the view for an advanced attribute panel. If
you are creating a simple attribute panel, you should modify the view to use
<Windchill>/codebase/WEB-INF/jsp/components/
simpleAttributePanel.jsp.
You can modify the view in the buildAttributePanelConfig() method
by calling the setView() method on the AttributePanelConfig.
For example:
panelConfig.setView(“"/components/simpleAttributePanel.jsp"”;

You could also modify the view to use a custom JSP if you want to display other
components on the page or include additional javascript. The path name of the JSP
passed to the setView() method should be relative to <Windchill>/
codebase./WEB-INF/jsp.

376 Customization Guide


To display your advanced panel in your custom JSP use the following tag for an
advanced panel:
<mvc:attributePanel/>

or this tag for a simple attribute panel:


<mvc:simpleAttributePanel/>

You should include the following taglib directive in your custom JSP:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>

Note that any JSP page that renders a MVC component should include the
following directive before rendering any page content:
%@include file="/netmarkets/jsp/util/begin_comp.jspf"%

and the following directive at the end of the page:


<%@ include file="/netmarkets/jsp/util/end_comp.jspf"%>

These should be used in lieu of any other include directives for *begin* or
*end* files.

How to Modify the Panel Context Object


The TypedAttributesPanelBuilder and
AbstractAttributesComponentBuilder use the context object from the
request to create the datum object for a panel. On rare occasions, it might be
necessary to use a different context object for a panel. This should be done with
extreme care. It must be done before any of the panel configs are created. Also, it
could have unwanted side effects if other components are displayed on the page.
This technique should only be used for view-only panels. Within a wizard, the
context object or type is always determined from the wizard step context.
To specify a different context object, change the context object prior to building
the panel config as follows:
((JcaComponentParams)params).setContextObject(contain
er);

How to Include an Attribute Panel in a JSP Page


The techniques below apply to attribute panels created using Java builders. To
display attribute panels on information pages, see Customizing Information Page
Components on page 972 for more information.

To Display a Link or Button That Launches Your Panel


To include a link or button that will launch your panel on a JSP page, create an
action for your panel in your custom-actions.xml file and reference the
action in an action tag in your JSP page. Your action should have a component
subtag whose name is the id for your component builder.

Customizing HTML Clients Using the Windchill JSP Framework 377


Example action:
<action name="myAttributePanel">
<component name="myPanelComponent" typeBased="true" windowType="page" />
</action>

See Action Framework for Windchill Client Architecture on page 512 for more
information on actions and action attributes.
Example action tag:
<%@ tagliburi="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>
.
.
.
<jca:action actionName="myAttributePanel" actionType="object" showIcon="false”/>

See the javadoc for the action tag for more information on the available tag
attributes.
An alternative way to include a link to your panel is to use an <a> tag with a href
constructed using the getComponentURL tag or
getTypeBasedComponentURL tag. The former would be used when there is
a single builder for a component builder id. The latter would be used when there
are alternative builders for the builder id based on the type of the panel object. For
example:
%@page import="com.ptc.netmarkets.util.misc.NetmarketURL"%
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%>
.
.
.
<a href="<%=NetmarketURL.APPPREFIX%>${mvc:getTypeBasedComponentURL’
(myPanelComponent)}">

In this example “myPanelComponent” is the component builder id.

To Include Your Panel Inline on a JSP Page


Use the getComponentURL or getTypeBasedComponentURL tag to
include your panel in a page. For example:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%>
.
.
.
<jsp:include page="${mvc:getComponentURL(‘attributesTable’)}" />

The getTypeBasedComponentURL should be used with builders that have a


TypeBased annotation. It will generate a URLwith a “tcomp” handler key that
tells the system to do a type-based lookup of the builder class. For example:
Windchill/ptc1/tcomp/attributesTable?typeBased=%27true%27&

378 Customization Guide


typeIdForTypeLookup=%27wt.doc.WTDocument%27&portlet=component

If the panel builder is not TypeBased, use the getComponentURL tag.

Customizing HTML Clients Using the Windchill JSP Framework 379


Customization Points

AttributePanelConfig Properties
The following parameters may be set using methods on the
AttributePanelConfig class.
Parameter Default Possible Req? Description
Value values
id “attributePa- Any string no The id given to
nel” the
Component
Definition
for the panel.
Also appears
in the HTML
div names
wrapping the
component. If
specified, you
will need to
use a custom
view JSP for
the panel and
pass this id as
the “compId”
parameter to
the
<mvc:attri
bubtePa
nel> or
<mvc:sim
pleAttribu
tePanel>
tag in the JSP.
view (JSP) <Windchill>/ Any JSP no The view will
codebase/ receive the
WEB-INF/jsp/ Component
components/ Definition
attributePanel. defined by the
jsp. builder and
controllers and
render it.

380 Customization Guide


Parameter Default Possible Req? Description
Value values
component- Component- See Solution yes See Solution
Mode Mode.VIEW Elements on Elements on
page 355 page 355
The value for
the panel
config will be
applied to
attribute
configs unless
overridden
component- Component- See Solution yes See Solution
Type Mode.TABLE Elements on Elements on
page 355 page 355
The value for
the panel
config will be
applied to
attribute
configs unless
overridden
targetObject The datum See Solution no See Solution
object is the Elements on Elements on
target object page 355 page 355
by default The value for
the panel
config will be
applied
attribute
configs unless
overridden
The following parameters on the parent interface are NOT applicable to
AttributePanelConfigs:
helpContext
actionModel
label
type

Customizing HTML Clients Using the Windchill JSP Framework 381


GroupConfig Properties
The following parameters are applicable to AttributeGroupConfigs and
may be set using methods on the GroupConfig class.
Parameter Default Possible Required? Description
Value values
sortOrder none Integer yes The position of
number the group in
the panel.
id none Any string yes The id that
will be applied
to HTML div
tags containing
the group.
label none Any String no The label
displayed at
the top of the
group
The following parameters on the parent interface are NOT applicable to
GroupConfigs:
helpContext
actionModel
component-
Mode
component-
Type
targetObject

382 Customization Guide


AttributeConfig Properties
The following properties are applicable to AttributeConfigs and may be set
using methods on that class. Many additional properties are available on the
parent interface PropertyConfig. See Attribute Customization on page 658
for more information on these.
Parameter Default Possible Required? Description
Value values
colPos 1 Any number no The column
position of the
attribute
within the
group. Only
applicable to
advanced
attribute
panels.
colSpan 1 Any positive no Set the number
number of columns the
attribute
should span. A
“column” is
one
name:value
pair. Only
applicable to
advanced
attribute
panels. See the
javadoc for
AttributeCon-
fig for more
information.
component- – See the no See Solution
Mode javadoc for Elements on
Component- page 355
Mode If not
specified, the
value for the
panel config
will used.
id none Any string yes The identifier
for the

Customizing HTML Clients Using the Windchill JSP Framework 383


Parameter Default Possible Required? Description
Value values
attribute. See
How to Find
an Attribute
Name/Id on
page 376
label none Any String no The label
displayed for
the attribute. If
not specified,
the label will
be determined
as described in
Attribute
Customization
on page 658.
rowPos – Any number no The row
position of the
attribute
within the
group. If not
specified,
attributes will
displayed in
the order
added to the
group config.
Only
applicable to
advanced
attribute
panels.
targetObject – See Definition no See Definition
of Terms on of Terms on
page 351 page 351 .
If not
specified, the
value for the
panel config
will be used, if
any.

384 Customization Guide


Parameter Default Possible Required? Description
Value values
The following parameters on the parent interfaces are NOT applicable to
AttributeConfigs:
component-
Type
helpContext
actionModel
type

Customizing HTML Clients Using the Windchill JSP Framework 385


Sample Code

Example of Usage in Windchill Code

Modifying a Property of an AttributeConfig in an AttributePanelConfig


Created by the TypedAttrLayOutFactory
This shows how you might modify an AttributeConfig in an
AttributePanelConfig created by the TypedAttrLayOutFactory.
List<ComponentConfig> components = attributePanelConfig.getComponents();
for (ComponentConfig componentConfig : components) {
if( componentConfig instanceof JcaGroupConfig){
List<ComponentConfig> attributeConfigs = ((JcaGroupConfig)
componentConfig).getComponents();
for (ComponentConfig attributeConfig : attributeConfigs) {
String attributeName =((AttributeConfig)attributeConfig).getId();
if(attributeName.equals("name")){
attributeConfig.setComponentMode(ComponentMode.EDIT);
}
if(attributeName.equals("folder.id")){
((JcaAttributeConfig)attributeConfig).setDataUtilityId
("saveAsVariantSpecLocationDataUtility");
}
}
}
}

Obtaining a TypeInstance Datum Object


For a panel in an object creation or edit wizard, you should typically return a
TypeInstance datum object so the data utilities will have access to constraints
that may have been defined for attributes. This code shows how to use the
CreateAndEditModelGetter.getItemAttributes() method to
obtain a TypeInstance in your builder’s buildComponentData()
method. This method requires that the panel is displayed within the context of a
wizard with an initializeItem tag.
JcaComponentParams jcaParams = (JcaComponentParams) params;
ComponentDescriptor cdesc = jcaParams.getDescriptor();
NmCommandBean commandBean =
jcaParams.getHelperBean().getNmCommandBean();
NmContext nmContext =
jcaParams.getHelperBean().getNmContextBean().getContext();
ArrayList typeInstances =
CreateAndEditModelGetter.getItemAttributes
(cdesc, commandBean, nmContext);

386 Customization Guide


Additional Resources
Related Customization Documentation
• Windchill Client Architecture Overview on page 232
• Action Framework for Windchill Client Architecture on page 512
• NmObject Utilities on page 590
• Attribute Customization on page 658
• Windchill Client Architecture Common Objects Overview on page 245
• Acquiring Data via Info*Engine on page 584
• Customizing Role-Based UI Functions - Attribute Visibility on page 482
• Customizing Information Page Components on page 972
• Building Wizards to Create a Single Object on page 892
• Building Wizards to Edit a Single Object on page 914

Related Package/Class Javadoc


• com.ptc.core.components.forms.CreateAndEditModelGetter
• com.ptc.core.lwc.common.ScreenDefintionName
• com.ptc.core.ui.resources.ComponentMode
• com.ptc.core.ui.resources.ComponentType
• com.ptc.jca.mvc.components.JcaComponentParams
• com.ptc.jca.mvc.builders.PrimaryAttributesBuilder
• com.ptc.jca.mvc.builders TypedAttributesPanelBuilder
• com.ptc.jca.mvc.builders VisualizationAttributesBuilder
• com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder
• com.ptc.mvc.components.AbstractComponentBuilder
• com.ptc.mvc.components.AttributeConfig
• com.ptc.mvc.components.AttributePanelConfig
• com.ptc.mvc.components.ComponentConfig
• com.ptc.mvc.components.ComponentConfigBuilder
• com.ptc.mvc.components.ComponentId
• com.ptc.mvc.components.GroupConfig
• com.ptc.mvc.components. TypedAttrLayOutFactory
• com.ptc.mvc.components. TypedAttrLayOutFactoryAware

Customizing HTML Clients Using the Windchill JSP Framework 387


• com.ptc.netmarkets.util.misc.NetmarketURL
• Common Components Tag Lib Javadoc

388 Customization Guide


Packaged Samples
The examples described below can be viewed on the Customization tab of the
Windchill product. See Customization Tools Overview on page 404 for
information on enabling the customization examples.

Advanced Attribute Panel


This example demonstrates how to create a non-layout-based advanced attribute
panel using a Java builder class. It constructs a panel for an object of type
“AttributePanelExampleObject,” a fake business object type that has
getter methods for all the attributes displayed in the panel.
The builder class has the builder id ComponendId.ATTRIBUTES_ID, which is
the id used for the common action “attributes” to display the More Attributes panel
on information pages. So that the system will use this builder instead of the
AbstractAttributesComponentBuilder (which has the same id) for the
panel, it has a TypeBased annotation specifying it is for the
AttributePanelExampleObject type.
If you take a look at the getter methods of the
AttributePanelExampleObject class, you will notice that some of them
return GuiComponents for the attribute value. Although this would not
typically be done in a production client, the Windchill Client Architecture
framework will handle these values.
See Solution – Create a Simple or Advanced Attribute Panel Using a
Configuration Created in a Java Builder Class on page 367 for more information
on creating non-layout-based advanced attribute panels.

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Advanced Attribute Panel.

Actions for this Example


Action Name Object Type Name File
attributePanel carambola /config/actions/
Carambola-actions.xml

Action Models for this Example


None

Customizing HTML Clients Using the Windchill JSP Framework 389


Files Used in This Example
Source File Description
/com/ptc/mvc/builders/carambola/ Builder that creates the configuration
CarambolaAttributePanelBuilder and datum object for the panel
/com/ptc/carambola/customization/ The Java class for the object type
examples/attributePanel/ represented in the panel
AttributePanelExampleObject.java
codebase/config/actions/Carambola- Contains the action for the example
actions.xml

Advanced Attribute Panel in a Wizard


This panel is the same one used in the Advanced Attribute Panel example, only
displayed in a wizard.
The wizard step on which the panel is displayed is constructed by the
DefineItemAttributesWizStepBuilder, which is used to create the Set
Attributes step for most Windchill object creation wizards. The step builder has
the view JSP defineItemAttributesWizStep.jsp.
That JSP contains the tag <mvc:attributesTableWizComponent/>,
which creates and displays the attribute panel using the builder with the id
ComponentId. ATTRIBUTES_ID for the wizard object type. The builder with
that component builder id for the AttributePanelExampleObject type is
the CarambolaAttributePanelBuilder.
See the Advanced Attribute Panel on page 389 for more information about this
builder

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Advanced Attribute Panel in a Wizard.

Actions for this Example


Action Name Object Type Name File
attributeWizardExample object /config/actions/
Carambola-actions.xml
attributePanelWizStep carambola /config/actions/
Carambola-actions.xml

Action Models for this Example


None

390 Customization Guide


Files Used in This Example
Source File Description
/com/ptc/mvc/builders/carambola/ Builder that creates the configuration
CarambolaAttributePanelBuilder and datum object for the panel
codebase//netmarkets/jsp/carambola/ The main JSP for the wizard
customization/examples/wizard/
attributeWizardExample.jsp
codebase/WEB-INF/jsp/object/ The common JSP used by most
defineItemAttributesWizStep.jsp Windchill create wizards for the Set
Attributes wizard step
/com/ptc/carambola/customization/ The Java class for the object type
examples/attributePanel/ represented in the panel
AttributePanelExampleObject.java
codebase/config/actions/Carambola- Contains the actions for the example
actions.xml

Advanced Attribute Panel on an Information Page


This panel is the same one used in the Advanced Attribute Panel on page 389
example, only displayed on a tab in the information page for the Carambola object
type.
The action for this panel is the information page for the Carambola object type:
<action name="infoPageExample">
<command url="ptc1/tcomp/infoPage?typeIdForTypeLookup=com.ptc.carambola.
customization.examples.infoPage.Carambola" windowType="page"/>
</action>

The action tag used to invoke the action from the JSP adds the parameters
“tlnAction” and “tlnType” to the infoPage URL to tell the system to
navigate to the tab in the Carambola information page that has the
“attributePanel” action component.
<%
HashMap<String,String> advPanelInfoPageParams = new HashMap<String,String>();
// automatically forward to the tab for attribute panel.
advPanelInfoPageParams.put("tlnAction", "attributePanel");
advPanelInfoPageParams.put("tlnType","carambola"); %>
<jca:action actionName="infoPageExample" actionType="carambola"
button="false" params="<%=advPanelInfoPageParams%>" shellURL="true"/>

The attributePanel action (defined for object type “carambola”) is the


same one used to display the panel in the Advanced Attribute Panel on page 389
example:
<action name="attributePanel">

Customizing HTML Clients Using the Windchill JSP Framework 391


<component name="attributesTable" typeBased="true" windowType="page"
urlParams="typeIdForTypeLookup=com.ptc.carambola.customization.examples.
attributePanel.AttributePanelExampleObject"
<label>Advanced Attribute Panel</label>
</action>

Although the attributePanel action is in the information page table of


contents action model, it is not in the tab set action model for the Carambola
type so the system creates a new tab in the information page for it.
Note that the panel is for an AttributePanelExampleObject even though
the information page is for a Carambola object. This is because the datum object
returned by the panel builder is an AttributePanelExampleObject.
See the Advanced Attribute Panel on page 389 example for more information
about the panel and builder used to produce it.

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Advanced Attribute Panel on an Information Page.

Actions for this Example


Action Name Object Type Name File
infoPageExample carambola /config/actions/
Carambola-actions.xml

Action Models for this Example


None

Advanced Panel with Modified Context Object


This is a view-only attribute panel based on a layout defined in the Type and
Attribute Management utility. It displays the layout that maps to the screen type
“Information Page – More Attributes” (ScreenDefinitionName.MORE_
ATTRIBUTES) for the container of a “Poem” object. It is displayed on a new tab
in a Poem info page.
Note: To display this example, the Poem type must have been loaded into your
Windchill system.
Also, to see this layout-based panel, you must create an object of type Poem in a
product, project, or library container using the New Document wizard. If you
don’t have a Poem object in one of those containers you will see a non-layout-
based panel showing only the container name.
The example illustrates:

392 Customization Guide


• How to create a layout-based panel using a Java builder class
• How to use a context object for the panel that is different from the page
context object
• How to change the title of an attribute panel group
The panel was configured using a Java MVC builder class that extends
TypedAttributesPanelBuilder.
The builder overrides the buildAttributePanelConfig() method of its
superclass so that it can reset the context object for the panel and set the title of
the single panel group.
The builder resets the context object by calling
JcaComponentParams.setContextObject(). Resetting the context
object should be done with care. It must be done before the panel configs are
created and can have unintended consequences if other components are displayed
on the page.

To reset the title of the group the builder calls the setLabel() method on the
group config. If it did not reset the title, the group would have the title specified in
the Type and Attribute Management utility.
Like the example Advanced Attribute Panel on an Information Page on page 391,
the attribute panel is displayed on a new tab of the Poem information page by
specifying “tlnaction” and “tlntype” parameters on the info page URL.
See Advanced Attribute Panel on an Information Page on page 391 for more
information on how this is done.
See Solution – Create an Advanced Attribute Panel Using Any Layout Defined in
the Type and Attribute Management Utility on page 363 for more information on
creating layout-based attribute panels.

Location of Example
To navigate to this example in the product go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Advanced Panel with Modified Context Object.

Actions Models Used in This Example


None

Actions Used in This Example


None

Customizing HTML Clients Using the Windchill JSP Framework 393


Files Used in This Example
Source File Description
Com/ptc/mvc/builders/carambola/ Builder that creates the configuration
LiteratureContextObjectAttributePanel- and datum object for the panel
Builder

Simple Attribute Panel using a Java Builder


This example, which uses the SimpleAttributesPanelBuilder, is similar
to the Advanced Attribute Panel on page 389 example except it configures the
panel as a simple list of name:value pairs.
The builder makes this a simple attribute panel by doing the following three
things:
1. It creates only one GroupConfig. In this example, the GroupConfig is
created implicitly by the AttributePanelConfig the first time an
AttributeConfig is added to it.
2. It does not specify rowPos, colPos, or colSpan properties on the
AttributeConfigs.
3. It explicitly sets the view for the panel config to "/components/
simpleAttributePanel.jsp.”
The buildComponentData() method of the builder for this panel illustrates how
you can you something other than a Persistable object as the panel datum object.
Although panel objects will typically be Windchill business objects, that does not
have to be the case. Any object from which it is possible to access the attribute
values via a bean-style getter method or a Map-style get() method can be used. In
this case, the row data is a HashMap. See Windchill Client Architecture Common
Objects Overview on page 245 for more information.
See Solution – Create a Simple or Advanced Attribute Panel Using a
Configuration Created in a Java Builder Class on page 367 for more information
on creating simple attribute panels using Java builders.

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Simple Attribute Panel Using a Java Builder.

Actions Models Used in This Example


None

Actions Used in This Example


None

394 Customization Guide


Files Used in This Example
Source File Description

com/ptc/mvc/builders/carambola/ Builder that creates the configuration


attributePanel/ and datum object for the panel
SimpleAttributesPanelBuilder.java
com/ptc/carambola/property/ Contains the method
PropertyUtils.java getExamplePropertyPanelDa
ta(), which constructs the HashMap
that is the datum for this panel.

Simple Attribute Panels using JSP Tags


This example shows two attribute panels.
The first panel is the same one shown in the Simple Attribute Panel Using a Java
Builder example, but in this case the panel is created and displayed using JSP tags.
See the Simple Attribute Panel using a Java Builder on page 394 example for
more information about the panel datum object.
The second panel shows how you can create and render GUIComponents directly
on a JSP page using GUI component wrapper tags. No
describePropertyPanel tag was used for this panel because the GUI
components are being created and configured by the wrapper tags and not by data
utilities. No getModel tags were used because the data for the panel is acquired
and placed in the page context by a different tag.
See Solution - Create a Simple Panel Using JSP Tags on page 371 for more
information on creating simple panels using JSP tags.

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Attribute Panel ▶ Simple Attribute Panel Using JSP Tags.

Actions Models Used in This Example


None

Actions Used in This Example


None

Customizing HTML Clients Using the Windchill JSP Framework 395


Files Used in This Example
Source File Description
codebase/netmarkets/jsp/carambola/ JSP for panel
customization/examples/attributePanel/
simplePanelUsingTags.jsp
com/ptc/carambola/property/ Contains the method
PropertyUtils.java getExamplePropertyPanelDa
ta(), which is called by the getModel
tag in the JSP

Simple and Advanced Attribute Panels in a Wizard


This is a composite example displaying four attribute panels in the Set Attributes
step for a new object of type Novel. (Note: this is not a working wizard as no
FormProcessor has been defined for it).

Panel 1
This is a composite component that displays:
• A simple panel containing a single attribute – the name of the container for the
new object
• The type of object being created
○ Note that if this object type had subtypes, a type picker would be displayed
here instead of a read-only field
• A simple panel with an input field for Organization Id (only displayed if the
preference Display ▶ Expose Organization is set to “Yes”)
• An advanced panel titled Attributes, which contains most of the non-driver
attributes of the new object. This panel is based on the layout for the screen
type “Create New” (ScreenDefinitionName.CREATE) for the parent
WTDocument type.
This composite panel is created automatically by the JCA framework when we
included the contents of the file <Windchill>/codebase/WEB-INF/jsp/
object/defineItemAttributesWizStep.jsp in our wizard step JSP.
That file is the default JSP for the Set Attributes wizard step. If we had not wanted
to include additional panels in this wizard step, we could have used the default
action “defineItemAttributesWizStep” in the wizardStep tag and
not had to write any JSPs or Java code for the wizard.

396 Customization Guide


Panel 2
This panel, titled “Additional Attributes” is an advanced attribute panel displaying
two attributes of Novel that were not included in the “Create New” layout for the
Novel type.
This panel is created by the following statement in the step jsp:
<jsp:include page="${mvc:getComponentURL('carambola.attributePanel.
WizardPanelForEnabledAndDepartment')}"/>

This statement tells the JCA framework to look for a Java builder class with the
component builder id
“carambola.attributePanel.WizardPanelForEnabledAndDe
partment.” It will find the builder class
EnabledAndDepartmentPanelBuilder, which will configure the panel,
acquire the data for it, and set the JSP that will display the panel.
Some things to note about this builder are:
• The buildComponentData() method returns a TypeInstance for a new
Novel object. If the panel object is a Windchill business object, it is important
that datum object be a TypeInstance so that any constraints defined for the
attributes are captured and made available to the data utilities.
• The panel component type is set to ComponentType.WIZARD_
ATTRIBUTES_TABLE. This is needed so that the HTML names of the input
fields are created such that the framework can identify the attributes it needs to
set on the object after the wizard is submitted.
See Solution – Create a Simple or Advanced Attribute Panel Using a
Configuration Created in a Java Builder Class on page 367 for more information
about this technique for creating attribute panels.

Panel 3
This is a simple attribute panel with one property, “Copyrighted,” that is not
an attribute of the Novel object type. You might use this technique when you want
to capture some additional information from the user besides the object’s
attributes. Note that because the Copyrighted information is not an object
attribute, a custom FormProcessor or FormProcessorDelegate would
be needed to handle this information when the wizard is submitted.
This panel is created by the following statement in the step JSP:
<jsp:include page="${mvc:getComponentURL
('carambola.attributePanel.WizardPanelForCopyrightInfo')}"/>

Just as in the previous example, this statement tells the JCA framework to call a
MVC Java builder class, which, in this case, is the class
CopyrightAttributePanelBuilder. Some things to note about this
example builder are:

Customizing HTML Clients Using the Windchill JSP Framework 397


• In this case we don’t set the component type of the panel to
ComponentType.WIZARD_ATTRIBUTES_TABLE because we don’t want
the framework to create an HTML name for the input field such that the
framework form processors would try to set the value of the field as an
attribute on the object. Instead, we want the HTML name to be such that our
custom form processor can find the property value in the form data and
process it. In this case, the value will have the key “copyrighted,” which
is the column name set in the buildComponentData() method.
• We set the view to “components/simpleAttributePanel.jsp” in
our panel config because we do not want a border around our panel or other
advanced features.
• The buildComponentData() method of the builder returns a HashMap
as the datum that will be passed to the data utilities. The key is the string
“copyrighted” and the value is a BooleanInputComponent. We need
to create the input component because the DefaultDataUtility would
not know the type of the property we want to display and could not determine
which type-specific data utility should be used. Alternatively, we could have
created and registered a data utility for this property.
See Solution – Create a Simple or Advanced Attribute Panel Using a
Configuration Created in a Java Builder Class on page 367 for more information
about this technique for creating attribute panels.

Panel 4
This is a simple attribute panel containing one attribute of the panel object type. In
this case the panel was created using JSP tags in the wizard step JSP.
See Solution - Create a Simple Panel Using JSP Tags on page 371 for more
information about this technique for creating attribute panels.

Actions Models Used in This Example


None

Actions Used in This Example


Action Name Object Type Name File
wizardWithAttributePa- attributePanel /config/actions/
nels Carambola-actions.xml
defineItemAttributesWiz- Novel /config/actions/
StepForAttrPanelWizard Carambola-actions.xml

398 Customization Guide


Files Used in This Example
Source File Description
codebase/netmarkets/jsp/carambola/ Main wizard JSP
customization/examples/attributePanel/
wizardWithAttributePanels.jsp
/com/ptc/mvc/builders/carambola/ Builder for the wizard step
attributePanel/
DefineItemAttributesWizStepBuilder-
ForAttrPanelWizard
codebase/WEB-INF/jsp/carambola/ JSP for the wizard step
attributePanel/
defineItemAttributesWizStepForAttrPa-
nelWizard.jsp
com/ptc/mvc/builders/carambola/ Builder for the Additional Attributes
attributePanel/ panel
EnabledAndDepartmentPanelBuilder.
java
com/ptc/mvc/builders/carambola/ Builder for the Copyrighted panel
attributePanel/
CopyrightAttributePanelBuilder.java
codebase/config/actions/Carambola- Contains the actions for the example
actions.xml
com/ptc/carambola/customization/ UI text for example
examples/attributePanel/
AttributePanelExampleResource.java

Customizing HTML Clients Using the Windchill JSP Framework 399


Customizing Access Control For
Packages
Objective
You want to customize the default roles, domain structure, or access control policy
rules associated with Packages across all contexts.

Background
Before you can use packages within a context, you must first enable packages for
that context. When you enables packages for a given context, the system loads a
site-wide package template XML file. The package template file contains package
specific roles that are applied to the container team, the default domain structure
for packages, and package-related policies.
The default domain structure will create a Package domain specific to the current
context. All packages created within the context, as well as all of the objects
created within the packages (collections, folders, documents, links, and deliveries)
will use this package domain by default. Out of the box, the package domain is
Private. This means that it won't inherit any policies from the container's default
domain.

Scope/Applicability/Assumptions
This guide assumes that you want to customize the default roles, domain structure,
or access control policy rules associated with Packages across all contexts. You
should be familiar with managing Packages, teams, and administering access
control for Windchill business objects.

Intended Outcome
Customize the default roles, domain structure, or access control policy rules
associated with Packages across all contexts.

Solution
Use the package template XML file to customize the default roles, domain
structure, and access control policy rules associated with Packages across all
contexts.

400 Customization Guide


Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Administering Packages
• Creating business XML files for templates
• Windchill team concepts
• Administering Domains and Policies
• Access Control

Solution Elements
Element Type Description
packageTemplate.xml XML The XML file that
contains the roles, domain
structure, and policies
associated with Packages.
This file is loaded when
you enable packages for a
context.
Location: <Windchill>/
loadXMLFiles
packageSharedTeamTem- XML The XML file that
plate contains the shared team
roles. This file is loaded
in addition to the
packageTemplate.xml file
when you enable
packages for a context
that is using a shared
team that isn’t extended.
Location: <Windchill>/
loadXMLFiles

Procedure - Modifying Domain Structure


The packageTemplate.xml file supports customization of the roles, domain
structure, and access control policy rules.
To modify the roles, refer to the projectMember element described in Creating
Business XML Files for Context Templates for each context. To modify the
domain structure, refer to the DomainStructure Element section. To modify the
access control policy rules, refer to the Common AccessControlRule Element
section.

Customizing HTML Clients Using the Windchill JSP Framework 401


If you modify the domain structure in the packageTemplate.xml file, you
must update the Default Domain Path for Packages site-level preference. This is
because the domain path must be the same in both places. The existence of the
domain specified in the preference is used to determine if packages have been
enabled for a context. It is also used to determine the default domain associated
with a Package when it is created.

Limitations
The packageTemplate.xml applies to the entire site which means you cannot
customize it for specific contexts or specific packages.
If you change the default domain path, you may have to enable packages again. If
the domain already exists in a context, you won't be prompted to enable packages
again.
If the context is using a shared team that isn't extended, the roles from
packagedSharedTeamTemplate.xml will be used and the roles from
packageTeam.xml will be ignored.

Sample Code

Examples of Usage in Windchill Code


Filename: <Windchill>/loadXMLfiles/packageTemplate.xml
Package Team Role:
<projectMember>
<Role roleType="PACKAGE MANAGER"/>
</projectMember>

Package Domain Structure:


<OrgStructure>
<DomainStructure>
<domainLevel>
<parentDomain>private</parentDomain>
<domainName>package</domainName>
<description>The default domain for packages.</description>
</domainLevel>
</DomainStructure>
</OrgStructure>

Package Access Control Policy Rule:


<AccessControlRule>
<domainName>package</domainName>
<externalTypeId>WCTYPE|wt.fc.WTObject</externalTypeId>

402 Customization Guide


<lifecycleState>ALL</lifecycleState>
<WTPrincipleReference isInternal="true">
<groupName>PACKAGE MANAGER<groupName>
<groupType>ALL</groudType>
</WTPrincipleReference>
<grantPermissionSet>
<AccessPermissionSet>
<permissionField name="ALL"/>
</AccessPermissionSet>
</grantPermissionSet>
</AccessControlRule>

Additional Resources

Other Related Windchill Documentation


• Access Control chapter in the Windchill Business Administrator's Guide
• Team chapter in the Windchill Business Administrator's Guide
• Creating XML Files for Templates and Shared Teams section in the Windchill
Business Administrator's Guide

Customizing HTML Clients Using the Windchill JSP Framework 403


Customization Tools Overview
Enable Customization Utilities
There are a number of customization utilities included within the Windchill user
interface. They are not enabled by default.
To enable the customization utilities:
1. From the Navigator browse to Site ▶ Utilities ▶ Preference Manager
2. Navigate the tree to Client Customization and expand the entry.
3. Right click on Client Customization, select Set Preference, and set the value to
“Yes”.
4. Refresh your browser.
5. From the Navigator browse to Site and select the Customization icon ( ).
6. Select Tools from the Customization menu.

Note
The direct URL to the menu is: <server>/<webapp>/app/#ptc1/carambola/
tools/list?tab=customization

Customization Source Code Examples


Customization source code examples are available for download from the
following location: http://www.ptc.com/view?im_dbkey=156765

404 Customization Guide


Reports
The following reports are documented in this section.
Report Description
Action Report on page 406 Find an Action
Action Model Report on page 410 Find an Action Model
Application Context Service/Resource Generates a report for the classes,
Properties on page 415 delegates, or resources configured to be
used by services or factories from
service.properties and other xconf files.
Available Attributes Report on page Generates a report on the attributes
413 available for a Windchill Type.

Logical Attributes Report on page 416 Generate a report on the attributes and
their external forms for a given
Windchill type.
Property Report on page 417 The Property Report lists all the
attributes defined for a given object
type and shows whether different types
of configurations exist.
Reload Action on page 418 Reload action configurations
MVC Builder Search on page 419 Finds MVC component builders by ID
MVC Builder Scan Report — Mini on
page 420
MVC Builder Scan Report — Full on
page 421
Modeled Objects on page 422 Finds a Modeled Object

Customizing HTML Clients Using the Windchill JSP Framework 405


Action Report
Action reports provide details on the actions used in the Windchill UI to launch
wizards and execute operations. Such details include the action label, action name,
the Java class used to validate whether the action is available to the user, the file in
which the action is defined, and many others. Action reports also enable you to
modify the label and tool tip of an action.
Reports may be generated for any action managed by the
StandardNmActionService.

Report Location
From the Navigator browse to Customization ▶ Tools ▶ Action

Generating an Action Report


Search for the action whose details you desire using the search criteria on the
Action Report page:

Search supports:
• Multiple search parameters
• Regular expressions
• Case-insensitive matching
Search Examples:
• For Label (aka Description):
○ remove ==> Matches: "remove", "list_delete", "related_delete_described_
part", etc.
• For Action Name :
○ remov.* ==> Matches: "remove", "remove_deliverable", "removeUses",
etc.
○ r[a-z]* ==> Matches: "reply", "REVISEITEMS", "reassignLC", etc.

406 Customization Guide


○ .*move ==> Matches: "remove", "CONTAINERMOVE", "WFMOVE",
etc.
○ .* ==> Matches: everything
• For Hot Key:
○ m ==> Matches: "home"
○ .* ==> Matches: "home", "productStructure", "documentStructure", etc.
• For Action Model File/Action Definition File:
○ Files must be located under <Windchill>\codebase\config\
actions
○ You only need to specify the file name in the search criteria, not the file
path. For example, BaselineClient.* ==> Matches: <Windchill>\
codebase\config\actions\BaselineClient-actions.xml
○ Some matches may be deceiving due to include tags in xml files
Once you have entered your search criteria, click the Search button to display the
matching actions:

Customizing HTML Clients Using the Windchill JSP Framework 407


To display the full action report for one of the displayed actions, click the icon
for it:

If there is no information for an attribute of a particular action, the line is shown


blank.

Features
• New actions can be created from the Actions table by selecting Create Action
from the Actions menu.
• Actions can be copied to Clipboard from the Actions table.
• “Select Required” is added as a column to the action report.
• “Icon Path” is added as a column to the action report.
• “Select Required” is added as a property to the action details page.
Ability to persist the user changes in a new location (coming from wt.
properties) and change in framework to give precedence to these new persisted
files. The modified action changes are saved to xml. Property to be added in
the wt.properties for actions is “com.ptc.netmarkets.util.misc.customActions”.
The value for the property would be complete path to the custom xml along
with the file name. Example entry in wt.properties on Windows: com.ptc.
netmarkets.util.misc.customActions=D\:\\myCustomActions.xml If the
property is not specified, user changes would be persisted in: <wt-codebase>/
config/actions/custom-actions.xml

408 Customization Guide


Troubleshooting
Search returning "No Objects to Display": If the method server is restarted after a
search has already been attempted, another search will return "No Objects to
Display" no matter what you search for. This is due to the fact that the page relies
on a session variable to get the information from the method server. To fix this
problem, simply restart your browser.
Wrong Definition File? Some matches may be deceiving due to include tags in
xml files. Check the included files to find your particular actions.

Customizing HTML Clients Using the Windchill JSP Framework 409


Action Model Report
Action model reports provide details about action sets, such as the set of actions
displayed in a table row for an object of a certain type or the set of actions
displayed on the toolbar of a table. Such details include the action model name
and the name of the file in which the action model is defined.
Reports may be generated for any action managed by the
StandardNmActionService.
From the Navigator browse to Customization ▶ Tools ▶ Action Model
Generating an Action Model Report
Search for the action whose details you desire using the search criteria on the
Action Model Report page:

Search supports:
• Multiple search parameters
• Regular expressions
• Case-insensitive matching
Search Examples
• For Action Model:
○ Default.* ==> Matches: "DefaultWizardButtons",
"DefaultWizardButtons", etc.
○ .*actions ==> Matches: "dti actions", "bookmark actions", "workitem
actions", etc.
○ [a-z]*s ==> Matches: "ScmiWizardButtons", "relatedItems",
"EditWizardButtons", etc.
○ .* ==> Matches: everything
• For Model File:
○ Files must be located under <Windchill>\codebase\config\
actions

410 Customization Guide


○ You only need to specify the file name in the search criteria, not the file
path. For example, Preference.* ==> Matches: <Windchill>\
codebase\config\actions\Preference-
actionModels.xml
○ Some matches may be deceiving due to include tags in xml files
Once you have entered your search criteria, click the Search button to display the
matching action models:

To display the full action model report for one of the displayed action models,
click the icon for it:

The “Description” attribute of the action model represents the text entered for the
“description” subtag of the actionmodel tag, if any.

Customizing HTML Clients Using the Windchill JSP Framework 411


The “Order” attribute of an action is the order of the action within the actionmodel
xml file.
If there is no information for an attribute of a particular action model, the line is
shown blank.

New Features
• Ability to create a new action (prototype) or remove an existing action in
action model table is added.
• Clipboard paste on ActionModel table.
• “Separator” action is added into the action model display.
• Reordering of actions in action model can be done using the drag and drop
functionality.
• Ability to persist the user changes made in an action model to a new location
(coming from wt.properties) and Change in framework to give precedence to
these new persisted files. The modified action models are saved to xml. A
property required to be added in the wt.properties for action models is “com.
ptc.netmarkets.util.misc.customActionModels”. The value for the property
would be complete path to the custom action model xml. Example entry in wt.
properties on Windows: com.ptc.netmarkets.util.misc.customActionModels=
D\:\\myCustomActionModels.xml
• If the property is not specified, user changes would be persisted in <wt-
codebase>/config/actions/custom-actionModels.xml
• Inline actions can be created in an action model. Their scope would be limited
to only that action model.

412 Customization Guide


Available Attributes Report
The Available Attributes Report is a search page that returns the details of
attributes that can be configured for a given object type.
This report can be accessed from any running Windchill installation to find the list
of supported attributes for a given object type (eg: wt.part.WTPart). The report
includes information about the attribute such as the id used to reference the
attribute and the label used for that attribute in the UI, the data utility mapped to
that component, etc.
Note that you must specify a fully qualified type name, including the full package,
to find its attributes. Also note that case is important, “wt.part.wtpart” will not
find “wt.part.WTPart’.
From the Navigator browse to Customization ▶ Tools ▶ Available Attributes
Search Supports
• Any valid, fully qualified class that implements Persistable
Results Table
• JCA ID
• JS ID
• Schema ID
• View Wizard Label
• Table Column Label
• Data Utility
• componentRB Label
• Column Descriptor Factory Label
• Introspected Label

Note
If there is no information for the property of a particular attribute, the cell is
shown blank.

Customizing HTML Clients Using the Windchill JSP Framework 413


414 Customization Guide
Application Context Service/Resource Properties
The Application Context Service/Resource Properties report generates a report for
the classes, delegates, or resources configured to be used by services or factories.
These classes, delegates, or resources are configured from
service.properties and other files. This tool is useful for finding what
actual classes are mapped to a particular id or finding what implementing class is
being used for the different interfaces. For example, it can be useful to find what
validator is registered for an action.
You can use the OOTB views to find commonly used delegates. Or use the table’s
built in search to filter the “All” view to find uncommon ones, for example:

Customizing HTML Clients Using the Windchill JSP Framework 415


Logical Attributes Report
The Logical Attribute Report for a type lists mappings that have already been used
for that type in addition to those used for alias attributes in the Type and Attribute
Management utility.
The creation of logical attributes is a feature of the
LogicalIdentifierFactory. When you pass the
LogicalIdentifierFactory a logical form in the context of a
TypeIdentifier, for example, factory.get("name",
"wt.part.WTPart"), it tries to treat the logical form as an attribute of the
type. It goes through several steps to try and find a mapping for the logical form:
1. First it looks for the logical form in logicalIdentifier.properties.
So if "name" is defined in logicalIdentifier.properties to map to
"MBA|foobar", then "MBA|foobar" will get returned.
2. If there wasn't an entry in logicalIdentifier.properties, it looks
in the /codebase/LogicalAttributes.xml file. This file has the
following format:
....
<Class name="wt.enterprise.RevisionControlled">
<Property>
<LogicalForm>name</LogicalForm>
<ExternalForm>MBA|name</ExternalForm>
</Property>
</Class>
....

The factory looks in this xml file to see if the requested logical form has an
entry specified for the type that was passed in by the user. If there isn't an
entry for the requested type, it sees if there is an entry for any of the type's
supertypes. Multiple inheritance conflicts are resolved by two rules:
a. Parent classes win over parent interfaces
b. Parent interfaces win by alphabetical order (so "java.util.Map" wins
over "java.util.Set"). (more configurable solution is possible).
3. If there wasn't a matching entry in LogicalAttributes.xml, then the
factory does introspection to try and find a match. This works by getting a list
of all AttributeTypeIdentifiers defined for the requested type, and
seeing if the logical form matches any of the attribute names in the list.

Report Output
The report output has four columns. The first two columns map an attribute's
logical form to the external form that the factor will return. The third column
shows where the factory got the external form – either from
logicalIdentifier.properties, LogicalAttributes.xml, or
Introspection. The fourth column shows the business field identifier.

416 Customization Guide


Property Report
The Property Report includes the hard attributes of a type, the logical attributes
listed in the Logical Attributes Report, and the table view attributes listed in the
Available Attributes report. You can click on each attribute to display additional
information about it, including the data utility registered for it, if any. The
DefaultDataUtility will handle many attributes for which there is not a
specific data utility listed.
Not all the attributes in this report are viewable in an attribute panel. In particular,
Calculated attributes cannot typically be used in the UI.

Customizing HTML Clients Using the Windchill JSP Framework 417


Reload Action
http://<your machine name>/<app-name>/app/#ptc1/
carambola/tools/list
This tool reloads the action models from their xml files without having to restart
the method server.

418 Customization Guide


MVC Builder Search
You can search for the implementations of ComponentConfigBuilder and
ComponentDataBuilder registered in the server. The value provided will be
matched against the bean name and we support ant style wildcards for the search.

Customizing HTML Clients Using the Windchill JSP Framework 419


MVC Builder Scan Report — Mini
You can register your component builders using the MVC scan functionality. This
report will give a breakup of the time spend at various activities involved in the
scan. To get the report you need to enable log4j loggers. (update
<Windchill>\codebase\WEB-INF\
log4jMethodServer.properties to add
log4j.logger.com.ptc.mvc.scan=INFO and restart the servers)

420 Customization Guide


MVC Builder Scan Report — Full
Apart from the information captured in the Mini report, this provides some more
additional information like the configuration files scanned, the builders registered,
time spend in each scan etc. This can be used to make sure that the builder
registered using the scan has been really picked up or not. We recommend not
using the scan if the number of builders registered for a base package is less than
10. This report lists the configuration files that are deviating from this
recommendation.
To get the report you need to enable log4j loggers. (update <Windchill>\
codebase\WEB-INF\ log4jMethodServer.properties to add
log4j.logger.com.ptc.mvc.scan=INFO and restart the servers)

Customizing HTML Clients Using the Windchill JSP Framework 421


Modeled Objects
Windchill manages many types of business and administrative concepts. The
concepts are modeled as objects in Java and instances of those objects are stored
in a database. The Modeled Objects page provides information about all modeled
objects on the current system. It provides a report that lists all of the modeled
objects, and then a link to a details page for each one.
The detailed information pages can include information about the meta data for
the object, the persistence mapping between the Java object and a database table,
UML diagrams and links to Javadoc.
Use these pages to learn about the modeled objects, how they are related, and how
they are stored in the database.
Location: Navigator ▶ Browser ▶ Customization ▶ Tools ▶ Modeled Objects
Support
• The report, and corresponding detail pages, are generated dynamically for all
modeled objects installed on the current system, whether they are exposed to
end users or not. This includes custom modeled objects created by customers.

Modeled Objects
• The Modeled_Objects_Index view of Modeled Objects shows a table of all the
modeled objects in the current Windchill system.
Columns:
• Display Name: The name of the object as it is exposed to end users.
• "Link to Detailed Information Page": A link to detailed information page for
the object.
• Class Name: The fully qualified Java class name for the object.
• Java Type: "class" or "interface"
• Table Name: If there is a corresponding database table name for the object,
then it is listed here. Not all modeled objects correspond directly to a database
table.

422 Customization Guide


• Detailed Information Page: The detailed information page for each object has
two tabs, one for the Database Information and one for the Java Information.
Only objects that have a corresponding database table will have a Database
Information tab.
• Database Information: The Database Information tab has four sections of
information about the object's database table
• Table Attributes: A list of single valued attributes that describe the database
table. At the moment, the only value is the Table Name.

Column Descriptors
A table of Column Descriptors. There is one row for each column in the database
table. Within the Windchill meta data, this information is stored in a "Column
Descriptor" class, thus the name "Column Descriptor".
Column Description
Name The generated name of the column
descriptor.
"Link to Detailed Information Page" A link to detailed information page for
the object.
Column Name The database column name
SQL Type The type of the database column

Customizing HTML Clients Using the Windchill JSP Framework 423


Column Description
Length The length of the database column (or 0
if none)
Mapped Property Descriptor Each column is mapped from a
Property Descriptor. This a link to an
information page about that Property
Descriptor.

Composite Unique Indices


A table of composite unique indices on the database table. Each row shows the
index number and the list of columns included in the index.

Java Information
The Java Information tab has seven sections of information about the object's Java
class.

Attributes
A list of single valued attributes that describe the class.
Attribute Description
Display Name The name of the object as it is exposed
to end users.
Icon An image of the icon used to represent
instances of this object in the Windchill
UI
Class Name The fully qualified Java class name
Persistable "Yes" or "No". Only concrete,
persistable classes will have a
corresponding database table.
Parent Class The direct, Java, parent class. This will
be a link to that class's information
page (if the page exists).
Table Name The corresponding database table name
(if any) Java Type "class" or "interface"
Link Class "Yes" or "No" depending on if this is a
Link Class.

424 Customization Guide


• Parent Interfaces: A table of the names of the modeled interfaces implemented
directly by this class.
• Descendents: A table of the modeled descendant classes of this class.
• Property Descriptors: A table of Property Descriptors. Within the Windchill
meta data, this information is stored in a "Property Descriptor" class, thus the
name "Property Descriptor".
Columns
○ Name: The name of the property descriptor.
○ Display Name: The name of the property as it is exposed to end users.
○ "Link to Detailed Information Page": A link to detailed information page
for the property descriptor.
○ Property Type: The Java type of the property
○ Defined As: The fully qualified internal name of this property
• Role Descriptors: A table of Role Descriptors. Within the Windchill meta data,
this information is stored in a "Role Descriptor" class, thus the name "Property
Descriptor". An association in Windchill is between two classes. Each of the
two classes plays a "role" with respect to that association and this is what is
represented by a Role Descriptor.
Columns
○ Name: The name of the property descriptor.
○ Display Name: The name of the Role or Association as it is exposed to end
users.
○ "Link to Detailed Information Page": A link to detailed information page
for the role descriptor.
○ Link Information: A link to the Information Page for the link class
corresponding to this role.

Customizing HTML Clients Using the Windchill JSP Framework 425


○ Valid Class Information: A link to the Information Page for the class that
plays the other side role on the corresponding link class.

• UML Diagram: A UML diagram for the class (not all classes have UML
diagrams).
• Javadoc: A link to the Javadoc for this class. Will only appear if the class itself
is included in the Windchill Supported API.

426 Customization Guide


Column Descriptor Information Page: The Information Page for a Column
Descriptor shows a panel of single valued attributes of the column
• Name - The name of the column descriptor
• Column Name - The name of the corresponding table column
• Java Type - The type of the value represented in Java
• SQL Type - The type of the value represent in the database
• Length - The maximum length of a string column.
• Updateable - "Yes" or "No" – Always "Yes"
• Required - The column is required to be set by the Windchill method server.
• Indexed - "Yes" or "No" depending if the column was designated to be
indexed in the model
• Unique - "Yes" or "No" depending if the model specified that the
corresponding value should be unique across all instances

Customizing HTML Clients Using the Windchill JSP Framework 427


• Property Descriptor - The fully qualified name of the Property Descriptor that
maps to this Column Descriptor
• Mapped Property Descriptor - A link to the corresponding property descriptor

• Property Descriptor Information Page: The Information Page for a Property


Descriptor shows a panel of single valued attributes of the property:
○ Name – The internal name of the property
○ Display name – The name of the property as it is exposed to end users.
○ Property Type – The Java type or they property
○ Bound – (not used)
○ Derived – "true" or "false" depending on if this property was modeled as a
derived attribute or not.
○ Persistent – "true" or "false" depending on if this property is persistent or
transient
○ Query Name – The name used to represent this property in programmatic
queries.
○ String Case – Mixed, Upper or Lower. Default is Mixed.
○ Initial Value – The modeled, initial value – if any.
○ Required – "true" or "false" depending on if this property is required in
order to create a new instance of the corresponding object.
○ Lower Limit – For a string, the minimum number of characters. For
numbers, the minimum value.
○ Upper Limit – For a string, the maximum number of characters. For
numbers, the maximum value.

428 Customization Guide


○ Changeable – One of "Default", "Frozen" or "Via Other Means". (See the
Javadoc for com.ptc.windchill.annotations.metadata.Changeable)
○ Constrained Type – (not used)

• Role Descriptor Information Page: The Information Page for a Role Descriptor
shows a panel of single valued attributes of the role.
○ Name – The internal name of the property
○ Display name – The name of the property as it is exposed to end users.
○ Link Information – A link to the modeled link object
○ Valid Class Info – A link to the modeled class that is the type of this role.
○ Cardinality – (not used)
○ Multiple – (not used)
○ Auto Navigate – "Yes" or "No". (see the Javadoc for com.ptc.windchill.
annotations.metadata.ForeignKeyRole autoNavigate element)
○ Owner – "Yes" or "No" (see the Javadoc for com.ptc.windchill.
annotations.metadata.GeneratedRole owner element)
○ Cascade – "Yes" or "No" (see the Javadoc for com.ptc.windchill.
annotations.metadata.GeneratedRole cascade element)

Customizing HTML Clients Using the Windchill JSP Framework 429


○ Other Role – The name of the other side role descriptor

430 Customization Guide


API Documentation
You can access documentation on how to use the Application Programming
Interfaces for the JCA framework from a running instance of Windchill.
Documentation is available on the following:
• Tags: Several tags and taglibs are delivered as part of the framework. These
taglibs contain a set of handlers for including components and other common
functionality into your pages.
• JavaDoc: Industry standard documentation for the Java classes available for
your use.
• JSDoc: Documentation on the JavaScript functions and objects available for
use. Note that there are substantially more Javascript objects available than in
previous releases.
• Best Practices: A number of the customization best practice topics available in
the Windchill Help Center are listed here.
You can find links to the documentation at the following location: Browser ▶
Customization ▶ Documentation

Customizing HTML Clients Using the Windchill JSP Framework 431


Debugging
This section describes how to activate and use the jcaDebug, jsDebug, Log4j
logging, and log4javascript logging.

Using jcaDebug
To enable the JCA debug feature, simply add “&jcaDebug=true” to the URL
of a Windchill page displayed in the browser’s address field, as described below.
You can enable jcaDebug from Customization ▶ Tools ▶ jcaDebug.

Content Area
To put jcaDebug output on the content area of the page, put the parameter at the
end of the URL, using the ampersand. For example:http://<server>/
Windchill/app/#ptc1/tcomp/
infoPage?typeIdForTypeLoo...&jcaDebug=true

Entire Shell
To put jcaDebug output on the entire Windchill page, including the Navigator and
header, put the jcaDebug parameter before the # token. Use a “?” since it becomes
the first parameter. http://<server>/Windchill/app/?jcaDebug=
true#ptc1/tcomp/...
Once added, the jcaDebug parameter will automatically be applied to all
subsequent Windchill pages. To turn off the feature, remove the jcaDebug
parameter from the URL of the current page.

What information does jcaDebug display?


Add the jcaDebug parameter to the URL to show this kind of information:
• Which Java class is handling data that's displayed in a table cell
• What kind of component is rendering the data in a table cell
• Which Java validator class is responsible for hiding/enabling/disabling an
action
• A link to the action model report for any action model — for example, the
actions menu, table menu bar, table toolbar, info page table of contents menus,
and top tab set of the info page.
• Information about what ComponentConfigBuilder and
ComponentDataBuilder created the table or info page
Some of this information (for example, action validator classes) is displayed

directly on the Windchill page. Ladybug icons ( ) indicate the availability of


other information, which can be displayed by mousing over or clicking the icon.

432 Customization Guide


In addition, the jcaDebug parameter will:
• Log the JavaScript that is executed when you click a toolbar or menu action to
the JavaScript console window
• Turn on the jsDebug feature, so JavaScript can be inspected/debugged as well

Tables
The following information is shown for tables (refer to the picture below):
1. MVC tables will have a ladybug to the right of the table name whose tooltip
shows the component config builder and component data builder for the table.
2. A ladybug shows the action model report for the toolbar actions when clicked.
Menu bar menus will have a similar action as the last action in the menu.
3. The column headers are extended to include the name of the validator class
that enables the column.
4. The table cells have a ladybug icon that you can mouse over to display a
tooltip. The tooltip displays the following information:
Attribute Description
Display Utility: The data utility used to create the gui
component(s) for the cell
Gui Component Type: The gui component returned by the
getDataValue() API of the data utility
Column ID: The ID used to look up the data utility
Row Object: The object whose attributes are being
displayed — this is the datum passed
into the data utility.

Customizing HTML Clients Using the Windchill JSP Framework 433


In some cases, a table that should display this debug information will not show
any data rows at all, even though the object count at the top contains non-zero
values. If this occurs, you should paste the URL into a new browser session.

434 Customization Guide


Information Page
The following information is shown (refer to the picture below).
1. The component config builder and data builder are shown at the top of MVC
info pages. The JSP used for the page is shown at the top of non-MVC info
pages.
2. The action models used for the top tab set and within the 'Customize' table of
contents menu are shown.

Actions Menu
The following information is shown:
1. The object type and action name from the action definition are shown for each
item in the menu. To see more details about the action you can go to the action
report for that type and name. For example http://<server>/Windchill/app/
#ptc1/carambola/tools/actionReport/actionDetails?actionName=
addToBaselineSingle&objectType=baseline
2. The Java validator class for each action
3. For template processor actions only, the URLActionDelegate for the action
4. The name of the action model used for the menu. When clicked this action
opens the action model report. For example http://<server>/Windchillapp/
#/ptc1/carambola/tools/actionReport/actionModelDetails?actionModelName=
epmdocuments+details+page+actions

Customizing HTML Clients Using the Windchill JSP Framework 435


Navigation
The action name, object type and validator for the currently selected tab are
shown. There are also links to the action model report at the bottom of each
expanded navigation node.

436 Customization Guide


JavaScript for Actions
When JCA debug is enabled, the JavaScript executed for a toolbar or menu action
is logged to the console when you click the action. For example, when you click
the 'Copy' action in the toolbar of a table you'd see something like this logged to
the console:
JCA_DEBUG - if(onClickValidation( event, 'list_copy' ))
{JavaScript:noContentAction('list_copy',
'ptc1/object/list_copy', ,,,,,,,,,,,,'portlet', 'poppedup', 'context',
'folder$folderContentTable$OR:wt.pdmlink.PDMLinkProduct:22199$',, ,
'folder$folderContentTable$OR:wt.pdmlink.PDMLinkProduct:22199$', 'none',
'com.ptc.netmarkets.model.NmObjectCommands', 'list_copy', 'height=300,width=300',
'com.ptc.netmarkets.util.utilResource.ADD_CLIP',
'com.ptc.netmarkets.util.utilResource.
NONE_CHECKED', false, 'P4118748557893740', 'component', ,true,
'table__folderbrowser.PDM_TABLE')};

Customizing HTML Clients Using the Windchill JSP Framework 437


Using jsDebug
Windchill JavaScript code is now combined and minified. This is done to improve
download times and execution speed. A whitespace compression is being used to
minify the JavaScript. This means that all the comments and whitespace are taken
out of the JavaScript. Minification is applied to most third party libraries as well
as the Windchill main.js file.

Why Enable jsDebug?


Get debug versions of js files
If you use Firebug, or Internet Explorer's "Developer Tools", you will not be able
to easily debug the combined and minified JavaScript files. jsDebug will give you
access to the original uncompressed versions of the files.

Bust IE's cache


IE caches the responses for any js files loaded via PTC.navigation.loadScript()
API. Without jsDebug enabled, IE browser just returns the cached version of the js
file even if the timestamp of the js file in codebase is newer than that of the
cached file. For active development it can be handy to enable jsDebug so you
aren't working with cached js files in IE.
The Firefox browser loads the modified js file right away as expected.

Note
To ensure patched js files would take effect regardless of browser caching,
PTC.navigation.loadScript() adds a cache buster URL parameter to force
reload of the js files at least every Sunday.

438 Customization Guide


How to Enable jsDebug
jsDebug can be enabled in one of the following ways:

Add the jcaDebug parameter to the url of a Windchill page


• This will:
1. Split and decompress the JavaScript files, using the jsDebug feature, as
documented below.
• If you put jcaDebug at the root of the URL, it will turn on debugging for the
entire shell, including the navigator, header, etc., and the JavaScript files will
be split immediately.
… /Windchill/app/?jcaDebug=true …

• If you put jcaDebug at the end of the URL (after the # token), it will turn on
debugging only for the content area of the page, and the JavaScript files will
only be split if you manually refresh the page (using Ctrl-R or F5 in your
browser)
… /Windchill/app/#ptc1/home/overview?jcaDebug=true

Add the jsDebug parameter to the url of a Windchill page


• This sets a user session variable.
• Any value of jsDebug other than "false" will turn on jsDebug.
• Explicitly setting jsDebug to "false" turns off the feature. Clearing your
browser cookies or restarting the browser will also turn it off.
• If you put jsDebug at the root of the URL, the page will refresh in your
browser automatically, and split the files immediately.
• If you put jsDebug at the end of the URL, after the # token, you will need to
refresh the browser page manually to get the js files to split.

Turn on the jsDebug feature using log4j


Add the following to the log4jMethodServer.properties file:
log4j.logger.com.ptc.jca.js=DEBUG

From the Tool Page


You can enable jsDebug from Customization ▶ Tools ▶ jsDebug.

Customizing HTML Clients Using the Windchill JSP Framework 439


JavaScript Logging
Windchill now includes a JavaScript logging package, called log4javascript,
which is a 3rd party js library from log4javascript.

Putting in Logging Statements


While this package is made to work and act just like log4j, there are a few choices
about how to do things. Windchill provides loggers for navigation and other
components that start with the PTC package name and this is a good practice that
other developers should follow.
See full documentation at: http://log4javascript.org/docs/index.html
Here is one simple example about a typical developer usage:
var mylogger = log4javascript.getLogger("PTC.mypackage");
mylogger.trace("...");
mylogger.debug(...);
myLogger.time("timername");
myLogger.timeEnd("timername");

By default all the messages logged under the PTC top level logger will be pushed
to the browser console (Firefox) or shown in a popup browser window (the
PopUpAppender for IE). Also, the messages will be logged to the server's log4j
file by the Log4JavascriptController's logger (using property log4j.logger.com.ptc.
jca.mvc.controllers.Log4JavascriptController=INFO in \codebase\WEB-INF
\log4jMethodServer.properties).

Turning on Logging
Logging may be turned on in one of the following ways:
• Add a jsLog URL parameter
To turn on global logging, append jsLog=true to the end of a Windchill URL
in the browser’s address field:
http://ah-lisa.ptcnet.ptc.com:1600/Windchill/app/#ptc1/comp/home.overview?
oid=OR%3Awt.org. WTUser%3A21639&u8=1&jsLog=true

This is the same as turning on TRACE level logging on the PTC logger.
• Programmatically (in JavaScript code or in the console)
To programmatically turn on logging, include the following:
var mylogger = log4javascript.getLogger("PTC.mypackage");
mylogger.setLevel(log4javascript.Level.TRACE);

• Using a UI

440 Customization Guide


Enter the URL address “javascript:PTC.log.startLogger()" to
launch a UI that lets you enable logging. Just hit "Ok" to enable all loggers or
enter a logger name to enable a specific logger.
• From the Tools Page
You can enable jsLog from Customization ▶ Tools ▶ jsLog.
See additional information in the javadoc for the PTC.log object JavaScript.

Log4j
Log4j loggers can be enabled from the UI, accessible from the Tools page. Note
that this feature works only for Site Administrators. This and many other site tools
are also available under Site ▶ Utilities ▶ Server Status ▶ Monitoring Tools.

Customizing HTML Clients Using the Windchill JSP Framework 441


Adding Validation Logic for Actions and
Properties
This section provides developers with the information required for implementing a
validation delegate (aka “validator”) to perform validation on a specific action or
UI component.

Objective
The UI Component Validation Service was created to give Windchill clients a
central service to call to perform validation for actions and other components
appearing in the Windchill UI. Calls to the service and interpretation of the results
should be managed by many of the common components developed in release 9.0.
The main responsibility for an application developer would be development of
Validator classes that are called by the validation service to validate a specific
action or UI component. This documentation outlines the process and best
practices for authoring Validator classes.

Applicability
This documentation should be used by a developer who is responsible for
authoring one or more Validators to determine whether or not an action or UI
component is valid on a given page/context/etc. The documentation should walk
through an example of each type of validation operation that a Validator could be
called upon to perform.

Structure
All of the classes in the UI Validation Service (except where noted) are defined in
the com.ptc.core.ui.validation package.
A Validator developer will not need to interact with all of the classes in this
diagram, but many of them are applicable. The various classes will be discussed
throughout this document, but to begin with, a developer writing a Validator
should always define their Validator class to extend
DefaultUIComponentValidator.

Note
It is also important to note that as requirements evolve, these classes may be
updated. To get the latest set of methods and attributes defined in each of the
classes see the Windchill Javadoc.

442 Customization Guide


Participants
The readers of this section should have a general understanding of the Java
programming language, and also some familiarity with the Windchill solution
suite.

Collaborations
Validator developers need to collaborate with common component developers and
other callers of the Validation Service. This collaboration is necessary to ensure
that a caller of the service is passing all of the data to the service that a given
Validator will need to perform validation. It is strongly recommended that
Validator developers include a list of the data required in a given validation
method in that method’s Javadoc. It is also helpful to include a list of Validation
keys (action names) that the method is designed to account for. For example:
public class DefaultWIPValidator extends DefaultUIComponentValidator
{

/**
* This implementation of performLimitedPreValidation will check the checkout
* state of all the Workable objects in the ValidationCriteria's targetObjects
* WTCollection, and base its validation results on whether an object in the
* given state can have the specified action performed on it. (e.g., an object
* in the checked-in state can not have an undo checkout action performed on it)
*
* At a minimum, a caller of this method should provide the targetObjects
* WTCollection in the validationCriteria argument.
*
* The expected validationKey arguments for this method are:
* checkin
* checkout
* undocheckout
*
* <BR><BR><B>Supported API: </B>false
*
* @param validationKey The String identifying the action or component
being validated.
* @param validationCriteria Object holding information required to perform
validation tasks.
* @param locale The user's Locale. If a <i>null</i> value is passed in, the
session locale will be used.
* @return UIValidationResultSet
**/
public UIValidationResultSet performLimitedPreValidation (String validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException

Customizing HTML Clients Using the Windchill JSP Framework 443


{

}

}

Consequences
By using this documentation as a reference, developers should create consistent,
performant Validators. A caller of the validation service should be confident that
whatever action or UI component they are validating will be validated in a
consistent manner.

444 Customization Guide


Implementation

Overview
It is probably helpful to begin with a definition of the term validation. For the
purposes of this discussion, the term validation refers to activities performed to
determine what a user can see or do. For example:
• Should we display the “Create Part” action?
• Should we allow the checkout of this object?
• Is everything the user entered in this create wizard OK?
For the purposes of our discussion, validation can be broken down into three
broad categories:

Pre-Validation
• Attempts to answer the questions: “Should something appear to the user in the
UI? And, if so, should it be editable/selectable?”
• For example, Should we display and enable the “Create Part” action for user A
in container B?
• Pre-Validation can be performed for actions or other UI components (status
glyphs, attributes, tables, etc.)

Post-Select Validation
• Attempts to answer the question: “Should the operation that was just selected
in the UI be allowed to proceed?”
• For example, Can we allow the checkout of parts A, B, and C?

Post-Submit Validation
• Attempts to answer the question: “is the data the user just entered valid?”
• For example, When the user clicks ‘Next’ in the “Create Part” wizard, are we
going to let them go to the next step, or do they need to modify some data (e.
g., name, number) in the current step?
The UI Component (Action) Validation Service exposes one or more APIs for
each of the types of validation listed above.
From a high level, a common component or some other client invokes a validation
API on the Validation Service, passing one or more validation keys (which can be
thought of as an action name, like create, for instance) and a UIValidationCriteria
bean, which contains data known by the client that is required to perform
validation. The Validation Service uses the validation key(s) to perform a lookup
and identify the Validator class(es) that should be called to carry out the validation
activity. The service then passes the key and UIValidationCriteria on to the

Customizing HTML Clients Using the Windchill JSP Framework 445


identified Validator(s) and awaits a (set of) result(s). When the service has the
result(s) from the Validator(s), it (creates a bundle of results and) returns it to the
client.

This documentation will concentrate on the authoring of Validator classes and


methods.

Packaging/Modularization
All of the classes related to the UI Component Validation Service are packaged in
com.ptc.core.ui.validation. Their source is located in the module \Windchill\src
\com\ptc\core\ui\validation. It is strongly recommended that any time a developer
is doing Validator development, they update all of the files in this directory and
compile the latest versions of the Java classes.
Developers writing Validators should put their Validator classes in a package or
module that is meaningful for the action(s)/UI component(s) that the Validator
validates.

Authoring a Validator Class


Action and UI Component owners will be responsible for writing the Validators
that validate those actions and UI components. To create a Validator, you’ll need
to create a subclass of com.ptc.core.ui.validation.DefaultUIComponentValidator.
java. There are currently five public methods defined in
DefaultUIComponentValidator.java. Your subclass can override one to all of them:
performFullPreValidation()

446 Customization Guide


performLimitedPreValidation()
validateFormSubmission()
validateSelectedAction()
validateSelectedMultiSelectAction()

For those methods which you do not override, the default behavior (always
enable/permit) will be inherited from the DefaultUIComponentValidator class.
You will also need to create a properties entry to associate your Validator class
with a particular validation key (action). The validation service uses these entries
to find the right Validator for a given validation key (action). The entry will go in
service.properties, or your application team’s service properties file (ask your
group lead where you should put your entry), and should have this format:
wt.services/rsc/default/com.ptc.core.ui.UIComponentValidator/<validationKey>/
null/0=com.ptc.my.validators.MyValidator

Where <validationKey> is the validation key for your action/component and the
right-side value is the fully-qualified class name of your Validator.
There are three types of checks you should never have to perform in your
Validator implementations. These checks are performed by the validation service
before the Validators are called. They include:
• Role-based checking (visibility of actions based on input into the RBUI
system, which is not to be confused with access control checking, which needs
to be done in the Validators.)
• Install-based checking (should an action or UI component be available given
the set of solutions installed on a given system?)
• Client-based checking (should an action or UI component be available in a
given client, like DTI or PSE?)

Implementing a validateSelectedAction Method


One of the methods you may choose to override in your Validator implementation
is validateSelectedAction. As the method name suggests, this method is called by
a client application wanting to know whether or not an action selected by a user
from the UI can be performed. For example, A user selects “revise” from a list of
actions for a document. Should the revise action proceed?
The method signature for validateSelectedAction looks like this:
public UIValidationResult validateSelectedAction (String validationKey,
UIValidationCriteria validationCriteria, Locale locale)

As you can see, the method takes three arguments:


1. A string indicating the key that was used by the client to identify the action
being validated (think of this as the action name)
2. A UIValidationCriteria object (more on this in a second...), and
3. A Locale

Customizing HTML Clients Using the Windchill JSP Framework 447


The first and third arguments should be fairly self-explanatory. The
UIValidationCriteria object is the validation criteria bean that was previously
mentioned. It holds data that the client set and passed to the validation service
(e.g., user, container, context object(s), etc.). The return type is
UIValidationResult – whose attributes include a status indicating whether or
not the action should be permitted.
Pseudo-code for a validateSelectedAction implementation would look like
this:
import com.ptc.core.ui.validation.*;

public class MyValidator extends DefaultUIComponentValidator{

public UIValidationResult validateSelectedAction (String
a_key,
UIValidationCriteria a_criteria, Locale a_locale)
{
// get required info from UIValidationCriteria
WTContainerRef parentContainer =
a_criteria.getParentContainer();
WTReference contextObject = a_criteria.getContextObject();
WTPrincipalReference userRef = a_criteria.getUser();
// create status and message objects to pass back
UIValidationStatus status = null;
UIValidationFeedbackMsg msg = null;
// perform validation logic

if (we can allow this action to proceed){
status = UIValidationStatus.PERMITTED;
}
else{
status = UIValidationStatus.DENIED;
msg = new UIValidationMsg(localized text,
UIValidationMsgType.INFO)
}
// return a validation result with the calculated status
and message
return new UIValidationResult(a_key, contextObject,
status, msg);
}

}

448 Customization Guide


Implementing a validateSelectedMultiSelectAction Method
Another of the methods that you can override in your Validator implementation is
called validateSelectedMultiSelectAction. It is similar to the
validateSelectedAction method. The only difference is that this method will be
called to validate a multi-select action, and will therefore return multiple results.
For example, A user selects “checkout” from a table header to perform the
checkout of several selected parts in the table. Should we allow all of the parts to
be checked out?
The method signature for validateSelectedMultiSelectAction looks like this:
public UIValidationResultSet validateSelectedAction (String
validationKey, UIValidationCriteria validationCriteria, Locale
locale)

Note that the arguments are identical to those passed to validateSelectedAction.


The only difference is that this method returns an object of type
UIValidationResultSet, which, as the name suggests, is just a set of
UIValidationResult objects.
Pseudo-code for the validateSelectedMultiSelectAction would look like this:
import com.ptc.core.ui.validation.*;

public class MyValidator extends DefaultUIComponentValidator{

public UIValidationResultSet validateSelectedMultiSelectAction
(String
a_key, UIValidationCriteria a_criteria, Locale a_locale){
// get required info from UIValidationCriteria
WTContainerRef parentContainer = a_criteria.getParentContainer();
WTCollection targetObjects = a_criteria.getTargetObjects();
WTPrincipalReference userRef = a_criteria.getUser();
// create result set to return
UIValidationResultSet resultSet = new UIValidationResultSet();
// iterate through target objects
Iterator targetRefIterator = targetObjects.referenceIterator();
while (targetRefIterator.hasNext()){
WTReference targetRef =
(WTReference)targetRefIterator.next();
if (we can allow this action to proceed for this object){
resultSet.addResult(new UIValidationResult(a_key,
targetRef,
UIValidationStatus.PERMITTED, null));
}
else{
resultSet.addResult(new UIValidationResult(a_key,
targetRef,

Customizing HTML Clients Using the Windchill JSP Framework 449


UIValidationStatus.DENIED, new
UIValidationMsg
(localized text,
UIValidationMsgType.INFO)));
}
}
// return the result set
return resultSet
}
}

Implementing a validateFormSubmission Method


A third method you can override in your Validator implementation is
validateFormSubmission. This method would be invoked on the service by a
client wanting to validate whether or not the user-entered data in a form is valid.
For example, A user clicks “next” after entering data on the details step of a
“create part” wizard. Should we allow them to go to the next step, based on what
they’ve entered?
The method arguments and return type for validateFormSubmission are identical
to those for validateSelectedAction:
public UIValidationResult validateFormSubmission (String
validationKey, UIValidationCriteria validationCriteria, Locale
locale)

Similarly, a pseudo-implementation of this method would be similar to what we


provided for validateSelectedAction.

Implementing Pre-Validation Methods


The last two methods you can override in your Validator implementation are
performFullPreValidation and performLimitedPreValidation. The methods
provide similar functionality, as they are both called by clients wanting to know
whether an action (or other UI component) should be enabled, disabled, or hidden
in the UI. The intended usage of performLimitedPreValidation is that a client
would call it when they want to do a quick check of whether or not an action
should appear in the UI. A client calling this method should know that they are not
guaranteed that actions will be accurately hidden in all cases – we are sacrificing
accuracy in favor of performance. On the other hand, a client would call
performFullPreValidation in cases where they want accurate results, at the
potential cost of decreased performance.
Some examples of Pre-Validation include:

450 Customization Guide


Example 1:
We are rendering a table in which each row could have action icons for check-out,
check-in, revise, or delete. Given the objects in the table, which actions should be
enabled in which row?

Note
In this case, we would probably want to perform limited pre-validation for
performance reasons.

Example 2:
We are rendering a dropdown list of actions on a doc details page. Given a list of
several actions, which ones should be available for this particular doc?

Note
In this case, we would probably want to perform full pre-validation, since
performance is not as much of an issue (only one object, as opposed to several
in the first example), and accuracy is more important.

The argument list and return types for each Pre-Validation method are identical:
public UIValidationResultSet performFullPreValidation (String
validationKey, UIValidationCriteria validationCriteria,
Locale locale)

public UIValidationResultSet performLimitedPreValidation


(String validationKey, UIValidationCriteria
validationCriteria, Locale locale)

A pseudo-implementation of performFullPreValidation would take the following


form:
import com.ptc.core.ui.validation.*;

public class MyValidator extends DefaultUIComponentValidator{

public UIValidationResultSet performFullPreValidation (String
a_key,
UIValidationCriteria a_criteria, Locale a_locale){
// get required info from UIValidationCriteria
WTContainerRef parentContainer =
a_criteria.getParentContainer();

Customizing HTML Clients Using the Windchill JSP Framework 451


WTCollection targetObjects = a_criteria.getTargetObjects();
WTPrincipalReference userRef = a_criteria.getUser();
// create result set to return
UIValidationResultSet resultSet = new
UIValidationResultSet();
// iterate through target objects
Iterator targetRefIterator =
targetObjects.referenceIterator();
while (targetRefIterator.hasNext()){
WTReference targetRef =
(WTReference)targetRefIterator.next();
if (we can allow this action to proceed for this object){
resultSet.addResult(new UIValidationResult(a_key,
targetRef,
UIValidationStatus.PERMITTED, null));
}
else{
resultSet.addResult(new UIValidationResult(a_key,
targetRef,
UIValidationStatus.DENIED, new
UIValidationMsg
(localized text,
UIValidationMsgType.INFO)));
}
}
// return the result set
return resultSet
}
}

Pseudo-code for a performLimitedPreValidation would look identical to the


example above for performFullPreValidation. The only difference in the actual
implementation is that the level of scrutiny used to determine validity may be
higher (and less performant) in the full pre-validation example. However, it’s
important to note that in practice it’s possible that the limited pre-validation and
the full pre-validation checks to be identical (in this case, we would likely be
saying that there are no significant performance impacts of performing full pre-
validation all the time).

452 Customization Guide


Sample Code

Example Validator – DefaultWIPValidator.java

Note
This source code can be found at the following location: <Windchill>\
src\com\ptc\windchill\enterprise\ wip\
DefaultWIPValidator.java

/* bcwti
*
* Copyright (c) 2004 Parametric Technology Corporation (PTC). All Rights
* Reserved.
*
* This software is the confidential and proprietary information of PTC.
* You shall not disclose such confidential information and shall use it
* only in accordance with the terms of the license agreement.
*
* ecwti
*/

package com.ptc.windchill.enterprise.wip;

import com.ptc.core.ui.validation.*;

import java.lang.ClassNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;

import org.apache.log4j.Logger;

import wt.access.AccessPermission;
import wt.access.AccessControlHelper;
import wt.epm.workspaces.EPMWorkspaceHelper;
import wt.fc.Persistable;
import wt.fc.ReferenceFactory;
import wt.fc.WTReference;
import wt.fc.collections.WTArrayList;
import wt.fc.collections.WTCollection;
import wt.folder.CabinetBased;
import wt.folder.CabinetMember;
import wt.folder.Foldered;
import wt.folder.FolderHelper;
import wt.inf.container.WTContained;
import wt.inf.container.WTContainerHelper;
import wt.log4j.LogR;

Customizing HTML Clients Using the Windchill JSP Framework 453


import wt.org.WTUser;
import wt.sandbox.SandboxHelper;
import wt.session.SessionHelper;
import wt.util.WTException;
import wt.vc.Iterated;
import wt.vc.VersionControlHelper;
import wt.vc.wip.Workable;
import wt.vc.wip.WorkInProgressHelper;
import wt.vc.wip.WorkInProgressState;

public class DefaultWIPValidator extends DefaultUIComponentValidator


{
private Logger
logger = LogR.getLogger("wt.method.server.httpgw");
private ReferenceFactory refFactory = null;

private static final String FULL = "full";


private static final String LIMITED = "limited";
private static final String SELECTED = "selected";

/**
* This implementation of performLimitedPreValidation will
* check the checkout state of all the Workable objects
* in the ValidationCriteria's targetObjects
* WTCollection, and base its validation results on whether
* an object in the given state can have the specified
* action performed on it. (e.g., an object
* in the checked-in state can not have an undo checkout
* action performed on it)
*
* At a minimum, a caller of this method should provide the
* targetObjects
* WTCollection in the validationCriteria argument.
*
* The expected validationKey arguments for this method are:
* checkin
* checkout
* undocheckout
*
* <BR><BR><B>Supported API: </B>false
*
* @param validationKey The String identifying the action
* or component being validated.
* @param validationCriteria Object holding information required
* to perform validation tasks.
* @param locale The user's Locale. If a null value is passed in,
* the session locale will be used.
* @return UIValidationResultSet
**/
public UIValidationResultSet performLimitedPreValidation (String valida
tionKey,

454 Customization Guide


UIValidationCriteria validationCriteria, Locale loc
ale)
throws WTException
{
logger.debug("ENTERING DefaultWIPValidator.performLimitedPreValidati
on");
logger.trace(" validtionKey -> " + validationKey);
logger.trace(" validationCriteria -> " + validationCriteria.toStrin
g());

UIValidationResultSet resultSet = performWIPValidation(validationKey,


validationCriteria, locale, LIMITED);

logger.trace("RETURNING " + resultSet.toString());


logger.debug("EXITING DefaultWIPValidator.performLimitedPreValidat
ion");
return resultSet;
}

public UIValidationResultSet performFullPreValidation (String validation


Key,
UIValidationCriteria validationCriteria, Locale loca
le)
throws WTException
{
logger.debug("ENTERING DefaultWIPValidator.performFullPreValidation");
logger.trace(" validtionKey -> " + validationKey);
logger.trace(" validationCriteria -> " + validationCriteria.toString(
));

UIValidationResultSet resultSet = performWIPValidation(validationKey,


validationCriteria, locale, FULL);

logger.trace("RETURNING " + resultSet.toString());


logger.debug("EXITING DefaultWIPValidator.
performFullPreValidation");
return resultSet;
}

public UIValidationResult validateSelectedAction (String


validation
Key,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException
{
logger.debug("ENTERING DefaultWIPValidator.validateSelectedAction");
logger.trace(" validtionKey -> " + validationKey);
logger.trace(" validationCriteria -> " + validationCriteria.toString(
));

Customizing HTML Clients Using the Windchill JSP Framework 455


UIValidationResult result = null;
WTReference wtRef = validationCriteria.getContextObject();
Persistable persistable = wtRef.getObject();

if (!(persistable instanceof Workable)){


return new UIValidationResult(validationKey, wtRef, UIValidat
ion
Status.DENIED, null);
}

Workable workable = (Workable)persistable;

if (validationKey.equalsIgnoreCase("checkin") || validationKey.
equals
IgnoreCase("undocheckout")){
result = performCheckinValidation(validationKey, workable, SELE
CTED,
(WTUser)(validationCriteria.getUser().getPrincipal()));
}
else if (validationKey.equalsIgnoreCase("checkout")){
result = performCheckoutValidation(validationKey, workable, SELE
CTED);
}

logger.trace("RETURNING " + result.toString());


logger.debug("EXITING DefaultWIPValidator.
validateSelectedAction");
return result;
}

public UIValidationResultSet validateSelectedMultiSelectAction


(String validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException
{
logger.debug("ENTERING DefaultWIPValidator.
validateSelectedMultiSelectAction");
logger.trace(" validtionKey ->
" + validationKey);
logger.trace(" validationCriteria ->
" + validationCriteria.toString());

UIValidationResultSet resultSet =
performWIPValidation(validationKey,
validationCriteria, locale, SELECTED);

logger.trace("RETURNING " + resultSet.toString());


logger.debug("EXITING DefaultWIPValidator.
validateSelectedMultiSelect
Action");

456 Customization Guide


return resultSet;
}

// ***NOTE:
// There is no post-submit validation for the WIP actions
// (checkin, checkout, undocheckout), since there is
// no wizard launched when one of the actions
// is performed. Therefore, there is no need to define a
// validateFormSubmission method in this class.
//
// public UIValidationResult validateFormSubmission (String validationKey,
UIValidaitonCriteria
// validationCriteria, Locale locale)

private UIValidationResultSet performWIPValidation(String validationKey,


UIValidationCriteria validationCriteria, Locale locale, String
validationType)
throws WTException
{
UIValidationResultSet resultSet = new UIValidationResultSet();
WTCollection targetObjects = new WTArrayList(validationCriteria.
get
TargetObjects());
Iterator workableIter = getWorkableIterator(targetObjects);
Workable workable = null;

while (workableIter.hasNext()){
workable = (Workable)workableIter.next();
if (validationKey.equalsIgnoreCase("checkin") || validationKey.
equal
sIgnoreCase("undocheckout")){
resultSet.addResult(performCheckinValidation(validationKey, worka
ble, validationType,
(WTUser)(validationCriteria.getUser().getPrincipal())));
}
else if (validationKey.equalsIgnoreCase("checkout")){
resultSet.addResult(performCheckoutValidation(validationKey, worka
ble, validationType));
}
}
resultSet.appendResults(processNonWorkables(targetObjects,
validationKey,
validationType));
return resultSet;
}

private UIValidationResult performCheckinValidation(String


validationKey,
Workable workable,
String validationType, WTUser user)

Customizing HTML Clients Using the Windchill JSP Framework 457


throws WTException
{
WTReference wtRef = getWTReference(workable);

if (validationType.equals(LIMITED)){
WorkInProgressState state = workable.getCheckoutInfo().getState();
if (state.equals(WorkInProgressState.CHECKED_OUT) || state.equals(
WorkInProgressState.
CHECKED_OUT_TO_SANDBOX)){
return new UIValidationResult(validationKey, wtRef, UIValidation
Status.ENABLED, null);
}
else{
return new UIValidationResult(validationKey, wtRef, UIValidation
Status.DISABLED, null);
}
}

else if (validationType.equals(FULL) || validationType.equals


(SELECTED)){
UIValidationStatus goodStatus = null;
UIValidationStatus badStatus = null;

if (validationType.equals(FULL)){
goodStatus = UIValidationStatus.ENABLED;
badStatus = UIValidationStatus.DISABLED;
}
else{
goodStatus = UIValidationStatus.PERMITTED;
badStatus = UIValidationStatus.DENIED;
}

if (workable instanceof CabinetBased){


CabinetBased orig;
if (WorkInProgressHelper.isWorkingCopy(workable)) {
orig = (CabinetBased)WorkInProgressHelper.service.originalCopyOf
(workable);
}
else {
orig = (CabinetBased)workable;
}

if (isNewInWorkspace(orig)){
return new UIValidationResult(validationKey, wtRef, badStatus,
null);
}
}
if (WorkInProgressHelper.isCheckedOut(workable, user) ||
(WorkInProgressHelper.isCheckedOut(workable) &&
WTContainerHelper.service.isAdministrator(((WTContained)
workable).

458 Customization Guide


getContainerReference(), user))){
return new UIValidationResult(validationKey, wtRef, goodStatus,
null);
}
else{
return new UIValidationResult(validationKey, wtRef, badStatus,
null);
}
}
return new UIValidationResult(validationKey, wtRef,
UIValidationStatus.
ENABLED, null);
}

private UIValidationResult performCheckoutValidation(String


validationKey,
Workable workable,
String validationType)
throws WTException
{
WTReference wtRef = getWTReference(workable);

if (validationType.equals(LIMITED)){
WorkInProgressState state = workable.getCheckoutInfo().getState();
if (state.equals(WorkInProgressState.CHECKED_OUT) || state.equals(
WorkInProgress
State.CHECKED_OUT_TO_SANDBOX)){
return new UIValidationResult(validationKey, wtRef, UIValidation
Status.DISABLED,null);
}
else{
return new UIValidationResult(validationKey, wtRef, UIValidation
Status.ENABLED, null);
}
}

else if (validationType.equals(FULL) || validationType.equals


(SELECTED)){
UIValidationStatus goodStatus = null;
UIValidationStatus badStatus = null;

if (validationType.equals(FULL)){
goodStatus = UIValidationStatus.ENABLED;
badStatus = UIValidationStatus.DISABLED;
}
else{
goodStatus = UIValidationStatus.PERMITTED;
badStatus = UIValidationStatus.DENIED;
}

Customizing HTML Clients Using the Windchill JSP Framework 459


if (isNewInWorkspace(workable)){
return new UIValidationResult(validationKey, wtRef, badStatus,
null);
}

if ((AccessControlHelper.manager.hasAccess(workable, AccessPermis
sion.MODIFY)) &&
(!WorkInProgressHelper.isCheckedOut(workable) &&
(VersionControlHelper.isLatestIteration((Iterated)workable)) &&
(!SandboxHelper.isCheckedOutToSandbox(workable)))){
return new UIValidationResult(validationKey, wtRef, goodStatus,
null);
}
else{
return new UIValidationResult(validationKey, wtRef, badStatus,
null);
}
}
return new UIValidationResult(validationKey, wtRef,
UIValidationStat
us.ENABLED, null);
}

private Iterator getWorkableIterator(WTCollection targetObjects)


{
try{
return targetObjects.persistableIterator(Class.forName("wt.vc.wip.
Workable"), true);
}
catch(Exception e){
return (new ArrayList(0)).iterator();
}
}

private WTReference getWTReference(Workable workable)


{
if (refFactory == null){
refFactory = new ReferenceFactory();
}

try{
return refFactory.getReference(workable);
}
catch(WTException wte){
return null;
}
}

460 Customization Guide


private static boolean isNewInWorkspace(Object object)
throws WTException
{
if(object instanceof Foldered || object instanceof CabinetMember) {
WTArrayList objArray = new WTArrayList();
objArray.add(object);
if(FolderHelper.service.getObjsInPersonalCabinets(objArray).size()
> 0) {
if(EPMWorkspaceHelper.manager.getNewObjects(objArray).size() >
0) {
return true;
}
}
}
return false;
}

private UIValidationResultSet processNonWorkables(WTCollection


targetObjects, String validationKey, String validationType)
{
UIValidationResultSet resultSet = new UIValidationResultSet();
UIValidationStatus status = null;

if (validationType.equals(SELECTED))
status = UIValidationStatus.DENIED;
else
status = UIValidationStatus.HIDDEN;

try{
targetObjects.removeAll(Class.forName("wt.vc.wip.Workable"),
true);
}
catch(ClassNotFoundException cnfe){
// do nothing
}
Iterator nonWorkableIter = targetObjects.referenceIterator();
WTReference wtRef = null;
while(nonWorkableIter.hasNext()){
wtRef = (WTReference)nonWorkableIter.next();
resultSet.addResult(new UIValidationResult(validationKey, wtRef,
status,
null));
}

return resultSet;
}
}

Customizing HTML Clients Using the Windchill JSP Framework 461


Known Uses
This documentation should be used by any developer responsible for writing a
Validator for an action or UI component.

462 Customization Guide


Split Pane / Two Pane
You want to display information from two different pages in one logical UI
component.

Background
The two pane component is a way to present the data from two JSP’s into one
logical UI component. The panes can be laid out horizontally or vertically. There’s
a separator between the two panes (left/right or top/bottom) that allows the user to
dynamically change the size of the panes.

Scope/Applicability/Assumptions
This information should be applied by a developer or customizer who is
responsible for laying out the two pane component for their functional area in
Windchill.
This documentation assumes that :
• You have some service method to provide data for the two pane component.

Intended Outcome
• Two Pane - Horizontal

Customizing HTML Clients Using the Windchill JSP Framework 463


• Two Pane - Vertical

Solution
Use the two pane common component tag, renderTwoPanes. This is included in
the JCA common components library (http://www.ptc.com/windchill/taglib/
components).

Prerequisite knowledge
To use the two pane component, you need to have an understanding of the
following:
• JSPs, tag libraries, and JSTL
• The JSP-based client architecture framework in Windchill

Solution Elements
Using this component, a developer needs to configure the left and right pane JSP,
while the layout of the page is provided by the renderTwoPanes taglib.
Element Type Description
RenderTwoPanesTag.java Java class The tag that renders out
the two pane component
in a JSP
navigation.jsfrag JavaScript Fragment Renders the component to
the DOM
<your_left_pane>.jsp JSP The JSP to have
displayed in the left or top
pane, depending on the

464 Customization Guide


Element Type Description
orientation value
(horizontal|vertical).
<your_right_pane>.jsp JSP The JSP to have
displayed in the right or
bottom pane, depending
on the orientation value
(horizontal|vertical).
<your_header_pane>.jsp JSP The JSP to have
displayed in the top pane
when orientation is set to
horizontal.
<your_javascript_file>.js JavaScript file Contains your click
handler function (if
specified). The click
handler is a Javascript
function that will be
called for every click
event fired from either
pane (left/right or top/
bottom). The click handle
will most likely make an
AJAX call to get the data
to display. Typically,
when something is
clicked in one pane you’ll
want to have something
happen in the other pane.

Two pane in wizard step


This component can also be used in wizard step but the following pieces are
required. Place the following fragments in the wizard step JSP where the two pane
component will be used:
1. Create an empty DIV element. The two pane component will render itself to
this DIV: <div id="twoPaneExample"></div>
2. Override the viewport object. The two pane component will be added to the
viewport. By default, the wizard does not create a viewport object, thus we

Customizing HTML Clients Using the Windchill JSP Framework 465


need to define the PTC.navigation.loadViewPort JavaScript
function.

Note
Ensure the value for the “renderTo” attribute matches the id given to the
DIV element in previous step.

PTC.navigation.loadViewPort = function(pageItems){

var verticalPanel = new PTC.Panel({


layout:'fit',
id: 'jca_viewport',
renderTo: 'twoPaneExample',
width : 800,
height: 600,
items: pageItems
});
}
3. Load the pop-up shell by calling the following JavaScript function:
PTC.navigation.loadShell (PTC.navigation.POPUP_SHELL);
4. If the wizard step is not the first step, then you may need to add this JavaScript
code snippet so that your split pane component will be visible when the step is
rendered:
PTC.wizard.on(‘wizardStepReady’, function(stepId) {
if (stepId === “thisWizardStepId”) {
PTC.wizard.showSplitPaneOnWizardStep(“jca_viewport”,
{left:20, right: 80}, “vertical”);
}
});
In the above code example, you would substitute “thisWizardStepId” for
the actual Id of your wizard step. The left and right parameters correspond to the
leftPaneSize and rightPaneSize that you configured using the
renderTwoPanes tag, as does the orientation (“vertical” in this example).
For wizard references, please see Constructing Wizards on page 837.

466 Customization Guide


Customization Points
renderTwoPanes tag attributes
The renderTwoPanes tag is a custom JSP tag that you insert in the JSP.
Parameter Default Possible Req? Description
Value Values
orientation horizontal horizontal, No Lays out the
vertical inner panels
either side by
side or stacked
leftPane Relative or Yes URI to the file
absolute path to be rendered
to a JSP page in the left/top
pane
rightPane Relative or Yes URI to the file
absolute path to be rendered
to a JSP page in the right/
bottom pane
headerPane Relative or No JSP file to be
absolute path rendered in the
to a JSP top pane. This
is only used
when
orientation is
set to
“horizontal”.
onClick Name of a No Function
valid called for
JavaScript every click
function event fired
from either
pane (left/right
or top/bottom).
The click
handle will
most likely
make an
AJAX call to
get the data to
display.
Typically,

Customizing HTML Clients Using the Windchill JSP Framework 467


Parameter Default Possible Req? Description
Value Values
when
something is
clicked in one
pane you’ll
want to have
something
happen in the
other pane.
leftPaneSize 25 0-100 No Specifies the
(Percentage) width/height
(depending on
the orientation
value) of the
panel.
rightPaneSize 75 0-100 No Specifies the
(Percentage) width/height
(depending on
the orientation
value) of the
panel.
headerPane- 0 Absolute Pixel No Specifies the
Height size height of the
panel.
Specified as an
absolute pixel
size (i.e. 150)

468 Customization Guide


Limitations
When the left or right pane is resized, some of the components within that pane
may not get resized properly.
The underlying framework manages the layout of the components it knows about
in its component hierarchy, so that (among other things) it can recalculate the
layout on resize events. For example, when a resize event happens, it would
recalculate the layout of its children, and those children’s children, and so on.
Because the two pane component simply renders its contents to the DIV
corresponding to the pane, and does not actually add its contents as a child of the
pane’s panel, nesting components (especially those components that are containers
to house other components) within a pane may not behave as expected.

Sample Code
The following snippet can be inserted to your JSP to display two pages in the Two
Pane component.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
<jca:renderTwoPanes
headerPane="/netmarkets/jsp/carambola/customization/examples/twoPanePanels
/headerPane.jsp?dynamicUpdate=true"
headerPaneHeight="150"leftPane="/netmarkets/jsp/carambola/customization/
examples/twoPanePanels
/leftOrTopPane.jsp?
dynamicUpdate=true "leftPaneSize="30"r
ightPane="/netmarkets/jsp/carambola/customization/examples/twoPanePanels/
rightOrBottomPane.jsp?dynamicUpdate=true "rightPaneSize=”70”
orientation="horizontal"onClick=
"PTC.carambola.twoPane.onClickHandler"/>

The following is an example “onClick” javascript handler. This example handles


the click event in the left/top pane and will render the response to the right/bottom
pane.
PTC.carambola.twoPane.onClickHandler = function(evt) {

var button = PTC.carambola.twoPane.getChildNodeByTag(evt.target,


'BUTTON');

if(button != undefined) {
var cp = PTC.getCmp(PTC.navigation.cardManager);
var contentPanel;
var renderToDiv = 'twoPanes_RIGHTPANE2';

// get the content pane that corresponds how


// the two pane component is laid out
// (i.e. right or bottom pane)

Customizing HTML Clients Using the Windchill JSP Framework 469


if(cp.layout.activeItem.CONTENT_DIV === renderToDiv) {
contentPanel = PTC.getCmp
(PTC.navigation.contentTabID + '_twoPanes_center');
} else {
renderToDiv = 'twoPanes_BOTTOMPANE';
contentPanel = PTC.getCmp
(PTC.navigation.contentTabID + '_twoPanes_bottom');
}

// make an AJAX call to get the HTML to render in the right/bottom pane
if(contentPanel !== undefined) {
contentPanel.clearCardContents();

var options = {
asynchronous: false,
method: 'get',
parameters: {
buttonId: button.innerHTML,
dynamicUpdate: true
}
};
var transport = requestHandler.doRequest(getBaseHref() +
'netmarkets/jsp/carambola/customization/examples/two
PanePanels/rightOrBottomPane.jsp', options);

// render the HTML returned from the AJAX response to the


right/bottom DIV
var panel = new PTC.Panel ({
id: 'test',
renderTo: renderToDiv,
html: transport.responseText
});
}

// render out the new right/bottom pane


panel.doLayout();
}
}

470 Customization Guide


Examples of Usage in Windchill Code
Folders Page for Product/Project/Library
The Folders page for Product/Project/Library use the Two Pane component to
layout the data horizontally

Publish Monitor
The WVS Job Monitor (available under Site ▶ Utilities or Organizations ▶ Utilities),
uses the Two Pane component to layout the data vertically.

Customizing HTML Clients Using the Windchill JSP Framework 471


Packaged Samples
There is a Carambola example that is available under the Customization tab. The
Two Pane carambola example shows the component rendered horizontally and
vertically.

Two Pane Example


• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\twoPanePanels\
horizontalSplitPaneExample.jsp
• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\twoPanePanels\
verticalSplitPaneExample.jsp

Two Pane Wizard Example


• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\wizard\
twoPaneWizardExample.jsp
• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\wizard\
twoPaneWizardExampleTwo.jsp

472 Customization Guide


• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\wizard\setStepOneWizStep.jsp
• <Windchill>\codebase\netmarkets\jsp\carambola\
customization\examples\wizard\setStepTwoWizStep.jsp

Customizing HTML Clients Using the Windchill JSP Framework 473


Defining Layouts in a Type Load File
1. How many default layout exists on a type?
Every type has one and only one default layout which doesn’t associate with
any Profile or Screen.
2. How can subtype inherit layouts?
Layouts are automatically inherited by the subtypes. That means, it’s
unnecessary to redefine the same layout in the subtypes (that actually could
cause unexpected result — see point 4). If subtypes share the same layout, you
should consider to move up the layout on the type hierarchy tree.
3. Can inherited layouts be updated by subtypes?
Yes, by defining the layout with the <csvtypeContext>Parent-Type-
Name</csvtypeContext> tag in the subtype, you are overriding the
layout in the subtype. Overriding means that you can add new groups to the
existing layout, or add new attributes (inherited or non-inherited) to the
existing groups, or redefine group/group members’ properties, e.g.
coordinates.
4. Can subtypes create their own layouts?
Yes, by leaving the <csvtypeContext/> tag empty or setting it to the
subtype name, you are creating a layout within the subtype context. Please
note that once a subtype creates its own layout, even defining the same
inherited layout but within its own context, it no longer inherits any layout
from its parent type, being dissected from all inherited layouts.
5. How to add new attributes to a layout on a subtype?
Whether inherited or not, attributes defined as group members have to exist on
that type first. That means if you want to add a new(non-inherited) attribute on
a layout on the subtype, you have to first create the attribute on the subtype.
6. How to create a dynamic group to load batch attributes?
By setting “isStatic” to false, you create a dynamic group which could
have 0-1 group member. This group member must be an attribute of
LWCAttributeSetAttribute class which may have a “mapping”
property that points to a batch attribute, e.g. SCA|ALL_IBAS.

474 Customization Guide


Load File Example
The following example adds a layout and its meta data to the
wt.change2.WTChangeOrder2 type.
!-- beginning to define a new layout -->
csvBeginLayoutDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader.
beginProcessLayoutDefinition">
csvname>mini_info_page_layout/csvname> !-- name of the layout -->
csvisDefault>false/csvisDefault> !-- whether this is the default layout to use -->
csvtypeContext>/csvtypeContext> !-- By default, it's the current type.
It is a must have to indicate an inherited layout -->
csvdefaultGroup>groupA/csvdefaultGroup> !-- the default group of the layout,
has to be one of the groups defined below -->
csvprofiles>/csvprofiles> !-- a combination of typeContext, profiles, and screens
uniquely identifies a layout -->
csvscreens>Mini_Info_Page/csvscreens> !-- available screens must have been
defined in the BaseDefinitionLoader.xml -->
/csvBeginLayoutDefView>

!-- beginning of defining a group within the layout -->


csvBeginGroupDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader.
beginProcessGroupDefinition">
csvname>groupA/csvname> !-- name of the group, uniquely identify a
group within a layout -->
csvisStatic>true/csvisStatic> !-- in most cases, it's true -->
csvstyle>List/csvstyle> !-- available group styles must have been defined in the
BaseDefinitionLoader.xml -->
/csvBeginGroupDefView>

!-- defining properties of the group: 3 in total -->


csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.
processGroupPropertyValue">
csvname>displayName/csvname> !-- name of the property -->
csvvalue>groupA/csvvalue> !-- value -->
csvlocale_en_us>EN_US groupA/csvlocale_en_us> !--
the following are localized values -->
csvlocale_en_gb>EN_GB groupA/csvlocale_en_gb>
csvlocale_fr>FR groupA/csvlocale_fr>
csvlocale_de>DE groupA/csvlocale_de>
csvlocale_es>ES groupA/csvlocale_es>
csvlocale_ja>JA groupA/csvlocale_ja>
csvlocale_it>IT groupA/csvlocale_it>
csvlocale_ko>KO groupA/csvlocale_ko>
csvlocale_zh_cn>ZH_CN groupA/csvlocale_zh_cn>
csvlocale_zh_tw>ZH_TW groupA/csvlocale_zh_tw>
/csvPropertyValue>
csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.
processGroupPropertyValue">csvname>description/csvname>
csvvalue>groupA/csvvalue>

Customizing HTML Clients Using the Windchill JSP Framework 475


csvlocale_en_us>EN_US groupA/csvlocale_en_us>
csvlocale_en_gb>EN_GB groupA/csvlocale_en_gb>
csvlocale_fr>FR groupA/csvlocale_fr>
csvlocale_de>DE groupA/csvlocale_de>
csvlocale_es>ES groupA/csvlocale_es>
csvlocale_ja>JA groupA/csvlocale_ja>
csvlocale_it>IT groupA/csvlocale_it>
csvlocale_ko>KO groupA/csvlocale_ko>
csvlocale_zh_cn>ZH_CN groupA/csvlocale_zh_cn>
csvlocale_zh_tw>ZH_TW groupA/csvlocale_zh_tw>
/csvPropertyValue>
csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.
processGroupPropertyValue">
csvname>sort_order/csvname>
csvvalue>1/csvvalue>
/csvPropertyValue>

!-- beginning of defining a membership of the group: -->


csvBeginGroupMemberView handler="com.ptc.core.lwc.server.TypeDefinitionLoader
.beginProcessGroupMembership">
csvname>number/csvname>
/csvBeginGroupMemberView>

!-- beginning of defining properties (coordinates) of the membership -->


csvPropertyValue handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.process GroupMembershipPropertyValue">
csvname>col_coord/csvname>
csvvalue>1/csvvalue>
/csvPropertyValue>
csvPropertyValue handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.process GroupMembershipPropertyValue">
csvname>row_coord/csvname>
csvvalue>1/csvvalue>
/csvPropertyValue>
csvPropertyValue handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.process GroupMembershipPropertyValue">
csvname>col_span/csvname>
csvvalue>1/csvvalue>
/csvPropertyValue>
csvPropertyValue handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.process GroupMembershipPropertyValue">
csvname>row_span/csvname>
csvvalue>1/csvvalue>
/csvPropertyValue>

!-- ending of defining a membership of the group -->


csvEndGroupMemberView handler="com.ptc.core.lwc.server.
TypeDefinitionLoader. endProcessGroupMembership"/>

476 Customization Guide


!-- more memberships can be defined here -->
!-- ending of defining a group within the layout -->
csvEndGroupDefView handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.end ProcessGroupDefinition"/>
!-- more groups can be defined here -->
!-- ending of defining a new layout -->
csvEndLayoutDefView handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.end ProcessLayoutDefinition"/>
!-- more layouts can be defined here -->
!-- ending of defining a type -->
csvEndTypeDefView handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.end ProcessTypeDefinition"/>

Customizing HTML Clients Using the Windchill JSP Framework 477


Configuring the Drag and Drop Zone
This section details how to configure an HTML5 drag and Drop zone. This
example uses the New Package wizard.
The New Package wizard contains two tables; Attachments and Delivery
Attachments. This example shows how to make both the tables different drag and
drop zones.

This is the jsp for the New Package wizard.


<jsp:include page="/netmarkets/jsp/attachments/attachments_step.jsp"
flush="true" />

<jsp:include page="/netmarkets/jsp/wp/wp_exp_attachments.jsp"
flush="true" />

478 Customization Guide


Solution Elements
To make the two tables as different drag and drop zones, you must add the
following attributes:
• class="dropZone" : Identifies that this div is used as a drop zone.
• targetTableId="<<Table id>>" : ID of the table where the files are
dropped.
• <br><br> : Make sure that there is spacing of at least two <br> tags between
the two jsp includes as dragging file between the two tables creates a scenario
that both the tables are highlighted.

Results
After adding the required attributes, the jsp looks like this:
<div class="dropZone" targetTableId="table_attachments.list.editable_TABLE">
<jsp:include page="/netmarkets/jsp/attachments/attachments_step.jsp"
flush="true" />
</div>
<br><br>
<div class="dropZone targetTableId="wp.attachments.list.editable">
<jsp:include page="/netmarkets/jsp/wp/wp_exp_attachments.jsp"
flush="true" />
</div>
The New Package wizard now looks like this:

Customizing HTML Clients Using the Windchill JSP Framework 479


480 Customization Guide
13
Generic UI Customizations
Customizing Role-Based UI Functions - Attribute Visibility .......................................... 482
Customizing Role-Based UI Functions — Action Visibility ........................................... 494
Preference Framework ............................................................................................ 495
Constructing URLs .................................................................................................. 501
Offline Package Customization................................................................................. 502
System Banner Alert Message ................................................................................. 506
Adding a Status Glyph ............................................................................................. 508

This chapter describes user interface customizations that are independent of any
particular Windchill client technology.

481
Customizing Role-Based UI Functions -
Attribute Visibility
Objective
You want to customize the set of UI components (actions or other UI elements)
that the administrators of the site, organization or containers can manage using the
role-based visibility feature.

Background
The role-based UI functionality enables administrators to optimize the number of
actions presented to users, so as not to confuse users by seeing actions they don’t
need or use for their role. Initially this support was just for container managers (in
particular, project managers). It has been extended to a concept called profiles
which sets action visibility at the site or organization level.
A site administrator, organization administrator or container administrator can
specify which users have visibility to the actions defined. For site and organization
administrators this can be done through profiles. Profiles can be created at Site-
>Profiles or Org->Profiles. The actions defined will be presented with their
default settings, and the administrator can choose to hide those actions. The
administrator can then specify which participants (users, groups, orgs) belong to
the profile. All members of the profile will have that visibility. If a member is in
multiple profiles, the greatest visibility is provided.
At the container level, the administrator can specify the visibility based on user
roles. Anyone in those roles will have the visibility specified. Container-level role
visibility will override any profile in which the member might be a participant.
See the Windchill Business Administrator's Guide for more details about profile
and role-based visibility administration.

Scope/Applicability/Assumptions
• The role-based visibility administration capability is turned on, that is, the
preference com.ptc.netmarkets.roleAccess.enabled is set to
true. The customization can be performed while the capability is turned off,
but the results will not appear in the UI until the capability is turned on.
• The customizer can manage both OOTB UI components and customized UI
components with this capability.

482 Customization Guide


Intended Outcome
When configuring visibility by roles and configuring profiles, the administrator is
presented with a list of UI components that can be managed. The administrator is
unable to manage the visibility for any UI components that are not included in this
list.
As a customizer, you have the ability to customize the list of UI components
available to administrators. You can:
• add UI components to the list,
• remove UI components from the list,
• specify default visibility settings for UI components,
• change the order that UI components appear in the list, and
• change the labels for the UI components on the list.
At the site or organization level your intention is to manage the list presented
when creating profiles:

Generic UI Customizations 483


At the container level, you are managing the equivalent list presented when
configuring visibility by roles:

484 Customization Guide


Solution
Modify the roleaccessprefs.xml file (and associated files as needed).

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of the following:
• The behavior of user roles in Windchill
• The administration of ad hoc access control policies in Windchill
• The actions framework in the Windchill client architecture
• The navigation framework in the Windchill client architecture
• The management of XML file customizations
• The management of RBINFO file customizations

Note
The Additional Resources section below includes references to many or all of
these subjects.

Solution Elements
Element Type Description
*actionModels.xml XML Files which define the models where
actions are used. If an action is not already
defined in a model, one will need to be
created for the validation code to find the
action and properly set visibility.
actionmodels.xml is located in
<Windchills>/codebase; other
*actionmodels.xml files are generally in
<Windchill>/codebase /config/actions
*actions.xml XML Files where actions and other UI
components are defined. Actions are
optionally given a uicomponent value.
actions.xml is located in <Windchill>/
codebase /config/actions along
with other *actions.xml files.

Generic UI Customizations 485


Element Type Description
roleaccessprefs.xml XML File for assigning default visibility to UI
components. Setting items in this file can
make them not appear at all for the site or
containers. Whether or not the container
manager can override the default value can
also be changed here.
Located in <Windchill>/codebase.
roleAccessResource. XML Defines the labels to provide in the Uis for
rbInfo the actions or UI components.
Located in <Windchill>/wtCustom/ com/
ptc/netmarkets/roleAccess/.

In actions.xml (and all *actions.xml files), an action can be assigned a


uicomponent attribute value. The uicomponent attribute provides a name for a
UI component that can be referenced from the roleaccessprefs.xml and
roleAccessResource.rbInfo files. Multiple actions can use the same uicomponent
value; this provides the ability to manage those actions as a single UI component.
If an action does not have a uicomponent, then the action name can be used to
reference it as a UI component instead. However, in this case it cannot be grouped
with other actions into a single UI component.
The roleaccessprefs.xml file consists of a <uics> element containing several
elements (or sections) that correspond to the primary tabs in the Windchill user
interface. For example, the <project> section corresponds to the Project tab. Each
section contains zero or more <uic> elements, each representing a UI component
whose visibility within that tab can be administered. Each UI component,
specified with the name attribute of the <uic> element, can appear in one or more
sections. This allows the default visibility settings for that UI component to be
assigned independently for different tabs.
The roleaccessprefs.xml file applies to the UI component lists for visibility
administration based both on profiles (at the site and organization levels) and on
roles (at the container levels). However, the <global> section applies only to
visibility administration using profiles. If a UI component is not tied to a specific
tab (such as is the case with the Search link in the Windchill UI header) or the UI
component is a first-level tab itself, it should be listed in the <global> section of
roleaccessprefs.xml.
Each UI component must have an entry in roleAccessResource.rbInfo that
provides a user-friendly label for that UI component. These labels are used for the
UI components in the lists that are presented to the administrator when
configuring visibility. In this file the resource entry constant identifies the UI
component; it must match either the uicomponent from the action definition or the
action name if the action has no uicomponent. The resource entry value provides
the user-friendly label.

486 Customization Guide


Note
Your UI component label should be a verb phrase. If your action/UI
component name is not already a verb phrase, place ‘View’ in front, for
example “View Team Page.”

Procedure – Making an Action Available to Visibility Administration


In this example, you provide the administrator with the ability to manage the
visibility of the Create Folder action in the Project, Program, Product, and Library
tabs.

Note
This example assumes that the Create Folder action is not already available for
role-based visibility management; in the actual product, it is available out of
the box.

1. Add a new <uic> to the roleaccessprefs.xml under the sections <project>,


<program>, <product>, and <library>:
<uic name=”PROJECT_CREATE_FOLDERS” order=”00” enabled=”true” defaultAll=
”true”
defaultManager=”true” defaultGuest=”false” managerEnabled=”true” guestEn
abled=”false”/>

Note
See the section on the uic element below for attribute descriptions.

Note
For actions that are valid for multiple tab types, put the entry under all the
sections you want it to affect.

2. In roleAccessResource.rbInfo, add a new resource entry for the action display


name:
31.value=Create Folders
31.constant=PROJECT_CREATE_FOLDERS

Generic UI Customizations 487


Regenerate your bundles. The name of the uic should be the same as the
constant for the entry in the resource bundle.
3. In <Windchill>/codebase/config/actions/actions.xml, modify the create folder
action by: adding the attribute uicomponent=”PROJECT_CREATE_
FOLDERS”
<action name=” folder_create” checkaccess=”true”
uicomponent=”PROJECT_CREATE_ FOLDERS”>

Caution
Follow best practices in backing up your XML files when customizing
them.

4. Restart the servlet engine and the method server.


Steps 1 through 3 above can be performed in any order. Note that “PROJECT_
CREATE_FOLDERS” is used for the uic name, the resource entry constant (but
without the quotes), and the action uicomponent. It is necessary for all three of
these items to share the same value in order to tie the customized behavior
together.
Upon completion of this procedure, an administrator can now configure the
visibility to the Create Folder action under the Project, Program, Product, and
Library tabs, based on profiles defined at the site or organization level, and based
on roles at the container level.

488 Customization Guide


Customization Points

uic Element
Each UIC in roleaccessprefs.xml represents a UIComponent or action to be
controlled.
Parameter Default Possible Req? Description
Value Values
name n/a string Y The name of the UI component.
This must match the value of
the uicomponent (or name)
attribute on an action element in
actions.xml. This must also
match the value of a resource
entry constant in the resource
bundle.
order n/a Integer N The position of this UI
component in the wizard. UI
components with lower
numbers are placed before those
with higher numbers.
enabled true true | false N Whether or not this
uicomponent will be shown in
the wizard and utilized by the
system.
defaultAll true true | false N The default visibility value for
All Members.
defaultMan- true true | false N The default visibility value for
ager Project Managers.
Note
The permissions are a union
of all permissions across all
roles; if you set
defaultManager to false; you
should also defaultAll to
false, otherwise managers
will still have access
through the ALL_
MEMBERS role.
defaultGuest true true | false N The default visibility value for
people in the Guest role.

Generic UI Customizations 489


Parameter Default Possible Req? Description
Value Values

Note
Guests are not technically
members of the Project;
they are not unioned with
the ALL_MEMBERS role.
managerEna- true true | false N Whether or not this
bled uicomponent can affect the
manager role. Do not change
this value in out-of-the-box
UICs. For customized UICs,
you may choose your own
setting.
guestEnabled true true | false N Whether or not this
uicomponent can affect the
guest role. Do not change this
value in out-of-the-box UICs.
For customized UICs, you may
choose your own setting.

490 Customization Guide


Making a Customized Tab Available to Visibility Administration
Making a customized action available to visibility administration is essentially the
same procedure as making an out of the box action available. A tab, however,
cannot be managed by container administrators (configuring role-based visibility).
Therefore you can only make a customized tab available to site and organization
administrators for configuring visibility profiles. This means you can add a <uic>
element for the tab only to the <global> section of roleaccessprefs.xml. For
example, assume that you have already created a customized tab, and have an
associated <MyTab>actions.xml file. You can add the tab to the list for profile-
based visibility administration as follows:
1. Add a new uic element to roleaccessprefs.xml under the <global> section with
a unique name, for example, CUSTOMIZED_TAB.
<uic name=”CUSTOMIZED_TAB” order=”190” enabled=”true” defaultAll=”true”/>
2. Associate the appropriate actions in action.xml with the UIComponent.
<ooleanpe name=”customization” >

<action name=”list2” uicomponent=”CUSTOMIZED_TAB”>


<command windowType=”page”/>
</action>
3. Add a new entry to roleAccessResource.rbInfo with a constant that is the same
as the uic name. The value is what will be displayed in the profile actions UI.
40.value=View Customized Tab

40.constant=CUSTOMIZED_TAB

Regenerate your bundles.


4. Restart the servlet engine and the MethodServer.

Assigning One uicomponent to Multiple Actions


If you want to tie one UI component to multiple actions, you need to specify the
uicomponent attribute for each of those actions, using the same value. For
example, the procedure described in theProcedure – Making an Action Available
to Visibility Administration on page 487 creates a UI component called
PROJECT_CREATE_FOLDERS associated with the folder_create action. You
can assign the list_create_folder action to the same UI component by specifying
the uicomponent attribute for that action in actions.xml as follows:
<action name=”list_create_folder”
uicomponent=”PROJECT_CREATE_FOLDERS” ajax=”row”>

As a result, the “Create Folders” entry in the Configure Roles and Create Profile
pages will affect the visibility for both folder_create and list_create_folder actions.

Generic UI Customizations 491


Changing the Labels for a UI Component
You can alter the label used for a UI component in the Configure Roles or Create
Profile pages, without making any other changes to that UI component. Simply
change the associated resource entry value in the roleAccessResource.rbInfo file,
and regenerate your bundles. For example:
31.value=Create Folders - My New Label

31.constant=PROJECT_CREATE_FOLDERS

492 Customization Guide


Sample Code

Examples of Usage in OOTB Code


Example of multiple actions using the same uicomponent: The Team pages in
Product/Project/Library share the same code, but each action is defined separately
for each object. Each action has the same uicomponent of “PROJECT_TEAM”.
This allows the same resource (rbInfo) entry to be used, and helps to minimize the
size of the action display table in the Create Profile page. PROJECT_TEAM still
needs to be defined in roleaccessprefs.xml for each tab type in which it is used,
and different defaults can be set for each.

Additional Resources

Related Customization Documentation


• Managing Customizations on page 100

Other Related Windchill Documentation


• Windchill Business Administrator's Guide — Role-Based Visibility
Administration
• Windchill Business Administrator's Guide — Access Control (ad hoc policies)

Generic UI Customizations 493


Customizing Role-Based UI Functions —
Action Visibility
Role-based action visibility in Windchill is implemented only in JSP pages. See
the Customizing Role-based Visibility on page 549 section in Adding Actions and
Hooking Them Up in the UI on page 511 for more information.

494 Customization Guide


Preference Framework
The Preferences Framework is based on the principle that a unique preference
consists of the following attributes:
• Parent Node (or root node if at the top of the hierarchy)
• Preference Node (usually associated as a group of similar preferences)
• Preference Key
Together these attributes form a unique key structure of parent/node/key. This
unique key structure will be referred to as the fully qualified preference key. To
separate individual user and group preferences for the same fully qualified
preference key, a context is applied to the preference.
The context consists of the following elements:
• Macro — a constant defining the type of context (see below)
• (optionally) Descriptor — text defining the name of the context.
These elements are placed together with a ’:’ to form the Preference Context.
The fully qualified preference key when placed together with a context will
form a unique row in the database table, allowing users, and other divisions to
have individual preferences.

Preference Macros
The wt.prefs.WTPreferences class defines the following types of Preference
Context Macros:
• USER_CONTEXT - the context for individual users
• DEFAULT_CONTEXT - the context for the system default (shipping) values
• CONTAINER_CONTEXT - a context used in the container hierarchy
• CONTAINER_POLICY_CONTEXT - a container context that is enforced as a
policy
• DIVISION_CONTEXT - the context used for any scopes defined in addition
to the default, container, and user scopes
• DIVISION_POLICY_CONTEXT - a division context that is enforced as a
policy

Generic UI Customizations 495


Setting the Hierarchy
The delegates.properties value
wt.prefs.delegates.DelegateOrder controls the hierarchy in which
delegates are called. For each level in the hierarchy there should be an entry in this
property. The customized entries should appear as DIVISION_CONTEXT. For
example, in the out-of-the-box hierarchy, there is a division scope called
Windchill Enterprise, and the out-of-the-box
wt.prefs.delegates.DelegateOrder property value is:
$DEFAULT,$CONTAINER,$DIVISION:WindchillEnterprise,$USER
In this value, there is no DIVISION_POLICY_CONTEXT defined since
DIVISION_POLICY_CONTEXT and DIVISION_CONTEXT are related and are
at the same level in the preference hierarchy. Similarly, the CONTAINER_
POLICY_CONTEXT need not be included. Entries are designated differently only
when storing and retrieving preferences internally. For more details on correctly
naming delegates, see the delegates.properties file.
If wt.prefs.delegates.DelegateOrder has been removed from the
delegates.properties file, Windchill uses the following:
$DEFAULT,$CONTAINER,$USERSetting Preferences
Edit the file Windchill/loadFiles/preferences.txt. This file is used
to put the system values into the database. Note that you don’t put quotes around
the strings unless you actually want quotes persisted as part of the preference.
Syntax:
PrefEntry~keyName~default value~fullyQualifiedNodePath

Example:
PrefEntry~fileOperationType~ASK~/wt/content

Getting Preferences
You can get a preference by first navigating the preferences tree to the proper
node, then setting the context for that particular user, then getting the value for
that key.
Example:
// returns an instance of the top node in the Windchill preference
"tree"
Preferences root = WTPreferences.root();
// returns the preference node at that path
Preferences myPrefs = root.node( "/wt/content" );
((WTPreferences)myPrefs).setContextMask
(PreferenceHelper.createContextMask() );
// get( ), gets the value for that
// preference key

496 Customization Guide


String prefValue = myPrefs.get( "fileOperationType", "SAVE" );

Clearing a Preference
There is a big difference between "clear" and "remove". Assuming there are no
division-level defaults or policies, if you "clear" a user preference by setting the
value to be the empty string "", then the value returned will be ""; but if you
"remove" the user-level preference, then the value returned would be system
default value. In most cases you will want to remove the user-level preference and
not clear it, giving the user the upper hierarchical preference as their default.
Example:
Preferences root = WTPreferences.root();
Preferences myPrefs = root.node( "/wt/content" );
((WTPreferences)myPrefs).setEditContext
(PreferenceHelper.createEditMask());
((WTPreferences)myPrefs).setContextMask
(PreferenceHelper.createContextMask());
String prevValue = myPrefs.remove("fileOperationType");

Preference Registry
The preference registry is a way to take a cryptic name like a preference and
provide a localized series of data about it. This registry is in the form of rbInfo
files. Anyone adding preferences to the system will have the option of adding this
localized information to the Preference Registry.

Adding a preference to the preference registry


To add a Preference to the Preference Registry, you need to edit the file
<Windchill>src/wt/prefs/registry/prefRegistry.rbInfo and for the Preference you
want to add, add at least:
DISPLAY_NAME
DESCRIPTION
DEFAULT

The format is as follows:


/node-name/key-name% [ ]tag.value=

Where /node-name is the name of the node (for example /wt/workflow), /key-
name is the name of the key under the node (SortOrder) and % [ ]tag is one of the
tags mentioned above (% [ ]DISPLAY_NAME).

Generic UI Customizations 497


Creating a Preference
The creation of a preference is done through an XML load file. When creating a
preference the following pieces of information need to be determined:
• Unique preference name
• Visibility: if the preference will appear in the preference manager UI and
visible at what contexts: SITE, ORGANIZATION, CONTAINER or USER.
○ Preference category: The category the new preference will appear under in
the Preference Management utility.
○ Display name: This is the Name column in the Preference Management
utility – string in the form <RBINFO>:< RBINFO key>
○ Description: This is the Description column in the Preference Management
utility – string in the form:
<RBINFO>:<RBINFO key>
○ Long Description: This description is displayed in the Edit Preference UI,
gives a more detailed description including the expected values.
◆ string in the form <RBINFO>:<RBINFO key>
• Default value
• Value header
In the example below, we will create a new preference named /com/
mycompany/MyNewPreference along with an associated preference
category to appear in the Preference Manager UI.
1. Create a resource bundle for labels used for your new preference. Labels are
needed for display name and description of preference category which the new
preference will be visible under in Preference Management UI. Labels are also
needed for the display name, description and long description of your
preference. Create the file mycompanyPreferenceResource.rbInfo in package
com.mycompany.pref. In this example, this file would be added to the
<Windchill>/src/mycompany/pref directory.
ResourceInfo.class=wt.tools.resource.StringResourceInfo
ResourceInfo.customizable=true
ResourceInfo.deprecated=false

# Preference Category labels


MyNewPreferenceCategory.displayName.value=My Preference Category
MyNewPreferenceCategory.description.value=Preference Category for my
custom preferences.

# Preference Definition labels


MyNewPreference.displayName.value=Display name of preference /com/my
company/
MyNewPreference

498 Customization Guide


MyNewPreference.description.value=Description of preference /com/myc
ompany/
MyNewPreference.
MyNewPreference.longDescription.value=Long description of preference
/com/mycompany/MyNewPreference.
2. Build the resource bundle by executing the following command from a
windchill shell:
ResourceBuild com.mycompany.pref.mycompanyPreferenceResource
3. Restart the servlet engine and the MethodServer.
4. Create Preference load file: createMyNewPreference.xml. It will
contain a definition for the new preference category and new preference
definition.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd">
<NmLoader>

<csvPreferenceCategory handler="wt.preference.LoadPreference.createPref
erenceCategory">
<csvname>CUSTOM_PREFERENCE_CATEGORY</csvname>
<csvparentName></csvparentName>
<csvdisplayName>
com.mycompany.pref.mycompanyPreferenceResource:
MyNewPreferenceCategory.displayName
</csvdisplayName>
<csvdescription>
com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceCategory.
description
</csvdescription>
</csvPreferenceCategory>

<csvPreferenceDefinition handler="wt.preference.LoadPreference.createPref
erence
Definition">
<csvname>/com/mycompany/MyNewPreference</csvname>
<csvvisibility>USER</csvvisibility>

<csvcategoryName>CUSTOM_PREFERENCE_CATEGORY</csvcategoryName>

<csvdisplayName>com.mycompany.pref.mycompanyPreferenceResource:MyNew
Preference.displayName</csvdisplayName>

<csvdescription>com.mycompany.pref.mycompanyPreferenceResource:MyNew
Preference.description</csvdescription>

<csvlongDescription>com.mycompany.pref.mycompanyPreferenceResource:

Generic UI Customizations 499


MyNewPreference.longDescription</csvlongDescription>
<csvdefaultValue>Default Value</csvdefaultValue>

<csvhandler>com.ptc.windchill.enterprise.preference.handler.
StringPreferenceValue
Handler:4000</csvhandler>
</csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.set
ClientDefinitionLink">
<csvname>/com/mycompany/MyNewPreference</csvname>
<csvclientName>WINDCHILL</csvclientName>
</csvLinkPreferenceClientDefinition>

</NmLoader>
5. Load the preference category and preference definition using the following
command:
windchill wt.load.LoadFromFile -d <full
path>/createMyNewPreference.xml

Deleting a Preference
The deletion of a preference is also done through the use of an XML load file.
Using the example from the Creating a Preference section on page 9–20, we will
delete the preference /com/mycompany/MyNewPreference. The deletion of the
preference will also remove any preference instances which may have been set for
this preference in the UI.
1. Create an XML file, deleteMyNewPreference.xml, containing the
following definition to specify the deletion of the preference.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM
"standardX10.dtd">
<NmLoader>

<csvDeletePreferenceDefinition
handler="wt.preference.LoadPreference.deletePreferenceDefinition">
<csvname>/com/mycompany/MyNewPreference</csvname>
</csvDeletePreferenceDefinition>

</NmLoader>
2. Delete the preference definition using the following command:
windchill wt.load.LoadFromFile -d <full
path>/deleteMyNewPreference.xml

500 Customization Guide


Constructing URLs
Information on constructing URLs is contained within the sections on specific
components.
• MVC Components on page 257
• Action Framework for Windchill Client Architecture on page 512
• Constructing Wizards on page 837
• Defining Menus on page 562
• To add a link to the navigator see the “Creating a Link” topic in the Windchill
Help Center.

Generic UI Customizations 501


Offline Package Customization
Objective
You want offline packages exported fromWindchill to display your company's
brand identity.

Background
Offline packages exported from Windchill are zip files containing the exported
files. Along with the exported content, an offline viewer is provided which allows
users to browse the contents in their web browser.
By default, offline packages exported from Windchill display the Windchill logo
and brand in the header of the offline view. This document describes how to
update certain files on your installation server to have the exported packages
display your company’s brand identity.

Scope/Applicability/Assumptions
Utilizing this solution will change the format of all packages exported from the
server. It will affect all users and organizations that make packages from that
server.

Intended Outcome
The offline view in exported packages display updated brand identity information
for your company.

Solution
Update the CSS in the static resources zip file to style the header of the offline
view.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Cascading Style Sheets. This guide assumes a good knowledge of how to
specify and write new CSS styles, without going into the specifics of how to
write correct CSS.
• Knowledge and access to the Brand Identity standards for your company.

502 Customization Guide


Solution Elements
Element Type Description
resources.zip Zip file This zip file contains the static elements
provided in the resources folder in every
package generated from the installation
server. This file is located in the
<Windchill>\codebase\com\ptc\netmarkets
\wp\ixb directory of your server.
wpofflinestyles.css CSS Style Contained within the resources.zip file, this
Sheet CSS style sheet contains the rules which
control the look and feel of the offline
view.
head.html HTML File The HTML file which is loaded at the top
of every page.
header.gif GIF graphics The background image of the header
file
logoWC.gif GIF graphics Transparent GIF of the Windchill logo.
file

Procedure – update the CSS Styles of the Header


1. Locate the resources.zip file. It is located in the \codebase\com\ptc\netmarkets
\wp\ixb directory, relative to the root of your Windchill installation. Normally,
you can discover the root by using the environment variable WT_ROOT.
2. Make a backup copy of the original resources.zip before you begin.
3. Unzip the resources.zip to an empty folder on your hard drive.
4. Inside the “resources” folder, you will find a file named “wpofflinestyles.css”.
Open this file in your favorite CSS editor, or text editor.
5. Edit the styles to customize the look of the brand identity header, using the
style rules listed below in the Customization Points on page 504 section.
6. You may need to add updated graphic files or other resources to the resources
directory to support your updated styles.
7. You may add links to external resources in the “pageHeaderActions” div.
These links by default appear in the upper right corner of the page. For
example, a link to your corporate website.
8. To test your CSS styles, load the “resources/head.html” file in your browser.
Windchill supports Internet Explorer 6, and Firefox 2, be sure to test in both to
ensure your styles will work. Note that the “generateTabs()” JavaScript
function will not work correctly while testing in this manner, and errors related
to it can be ignored.

Generic UI Customizations 503


9. Once you are satisfied with the look of the header, update the resources.zip file
with the updated resources folder and files from your working folder. Make
sure the file paths are correct inside the zip file – all files should have the path
“resources\”.
10. Test to be sure packages are generated correctly by making some experimental
packages from the running server and viewing them offline.

Customization Points
CSS rule Default Value Description
.pageHeader Dark teal background Defines the border,
with Windchill background image and
background image color of the header.
(header.gif) and a dark
green bottom border.
.wncApplLogo logoWC.gif Defines logo graphics
file.
.applLogo Height: 55 pixels. Defines the height of the
logo div, normally shown
in the upper left corner of
the page.
.pageHeaderActions(CSS White text links. Defines the style of links
rule in wpofflinestyles. and text normally in the
css) upper right corner of the
page.
pageHeaderActions(div in Delivered empty Links can be added to this
head.html) div.

Limitations
Updating the resources.zip file in this manner affects every offline package
created by the system. It is not currently possible to apply these changes to one
package and not to another. Modification of packages after they are created is not
possible on the server.

504 Customization Guide


Sample Code
.pageHeader {
border-bottom: 1px solid #20313d;
background-image: url(header.gif);
background-color: #40637A;
background-repeat: no-repeat;
… }

.wncApplLogo {
background-image: url(logoWC.gif);
}

.applLogo {
background-repeat: no-repeat;
height: 55px;
background-position:34px;}

Generic UI Customizations 505


System Banner Alert Message
You can create a system wide banner message that will display on all the pages
within the Windchill application.

Turning on the alert banner feature


1. Put the following line code into <Windchill>\codebase\
netmarkets\jsp\util\begin_custom.jspf
<%@ include file="/netmarkets/jsp/util/banner_custom.jspf"%>

2. Restart the Embedded Servlet Engine.

Displaying the alert message on the top of Windchill


UI pages
Write the alert message with html format into the following file:
<Windchill>\codebase\netmarkets\jsp\util\banner.txt
For example:
<div
style="float:left;
clear: both;
position: absolute;
margin: 2px 170px;
padding: 3px;
border: 1px solid #000;
background-color: #fff;
top: 3px;
color: #006600;
font-weight: bold;
font-size: 12px;
z-index: 1000">

<font face="verdana">
<!-- Banner begins here -->
Windchill server will be down 1/1 for maintenance
<!-- Banner ends here -->
</font>
</div>

Removing the alert message from Windchill UI page


Set <Windchill>\codebase\netmarkets\jsp\util\banner.txt
as empty file.

506 Customization Guide


Turning off the alert banner feature
1. Set <Windchill>\codebase\netmarkets\jsp\util\begin_
custom.jspf as an empty file
2. Restart the Embedded Servlet Engine.

Generic UI Customizations 507


Adding a Status Glyph
Users want a visual way to quickly see the state of an object. This section
describes the different out of the box status glyphs and how to display them for a
given object.

Terminology
The following specialized terms are used in this section:
• Component Builder : A Java class used to “build” a UI component, i.e. a UI
widget. These builders define properties of your component to tell the
infrastructure how to display them.
• Status Family ID : A string used to reference a status glyph.

Solution
Developers can include status glyphs in their tables and information pages directly
from a ComponentBuilder class.

Prerequisite Knowledge
To achieve this goal, you need to have an understanding of the following:
• Java Programming
• General understanding of MVC builders
Default Icon Glyph Name Status Family ID Known Usages
General statusFamily • Locked
_General • Checked out by you
• Checked out by you in
another workspace
• Checked-out by you in
this workspace
• New
• Checked out by other
• Checked-out to a
project
• Out of date
Share statusFamily • Shared to a project
_Share • Shared from PDM
• Checked-out from
PDM

508 Customization Guide


Default Icon Glyph Name Status Family ID Known Usages
Message statusFamily • System Excluded
_Message Message exists
• Error Messages exists
• Warning Messages
exists
• Info message exists
Task statusFamily • Reassigned
_Task
Change statusFamily • Pending Change
_Change • Hanging Change
• New Hanging Change
AML/AVL statusFamily • No AML
_AML_AVL • Preferred
• Do not use
• Approved
Security statusFamily • Restricted
_Security

The OOTB glyphs can easily be included in an info page or table by using its
corresponding Status family id. The naming convention for these glyphs is:
statusFamily_<family name>

Adding a Status Glyph to an Information Page

The following snippet shows how you can add a status glyph to the information
page for a particular business object type. In the builder for that business object
type, override the buildInfoConfig() method to add the glyph component
to the info page component. For example:
public static InfoConfig buildInfoConfig(InfoComponentConfigFactory factory)
throws WTException {
InfoConfig infoConfig = factory.newInfoConfig();
...
PropertyConfig statusFamilySecurity = factory.newPropertyConfig
("statusFamily_Security");
statusFamilySecurity.setStatusGlyph(true);

Generic UI Customizations 509


infoConfig.addComponent(statusFamilySecurity);
...
return infoConfig;
}

See Customizing Information Page Components on page 972 for more


information.

Adding a Status Glyph to a Table

The following snippet shows how you can add a status glyph to a table for a
particular business object type. In the builder for that table, override the
buildComponentConfig () method to add the glyph component to the table
component. For example:
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig tableConfig = factory.newTableConfig();
...
ColumnConfig col1 = factory.newColumnConfig("statusFamily_Share", false);
tableConfig.addComponent(col1);
...
return tableConfig;
}

See Constructing and Rendering a Table Using the JSP Framework on page 606
for more information on tables.

Additional Resources
• Constructing and Rendering a Table Using the JSP Framework on page 606
• Customizing Information Page Components on page 972
• Icon Delegates on page 742

510 Customization Guide


14
Adding Actions and Hooking Them
Up in the UI
Action Framework for Windchill Client Architecture .................................................... 512
Tab Models ............................................................................................................. 539
Customizing Role-based Visibility ............................................................................. 549
User Interface Stickiness ......................................................................................... 561
Defining Menus ....................................................................................................... 562
Adding Custom Content to the Home Page ............................................................... 578

This chapter describes how to customize actions and add them to the user
interface.

511
Action Framework for Windchill Client
Architecture
The action framework for the Windchill client architecture supports the ability to
configure new actions and action models in the system.
This section describes the action framework for the Windchill Client Architecture.
It does not include information on how to control the display of the actions. For
more information on controlling the display, see Related Documentation on page
512.

Intended Outcome and Objectives


When you are finished reading this, you should understand how the action
framework works, and how to register actions and action models into the action
framework. You should also be familiar with the tools and debug settings that can
help in your development.
These topics cover the following objectives:
• You want to add a new action that will be exposed in the user interface.
• You want to add a new action model to the system.
• You want to remove an action from an action model.

Prerequisite knowledge
• XML file structures

Related Documentation
• Windchill Client Architecture Wizard on page 838
• Constructing and Rendering a Table Using the JSP Framework on page 606
• Windchill Client Architecture Tree on page 642
• Information Pages on page 971
• Customization Tools Overview on page 404

512 Customization Guide


Solution Elements
Element Type Description
Stand- .java The StandardNmActionService manages the actions and
ardNmAc- action models in the system.
tionService Runtime location:
(and
corre- <Windchill>\codebase\com \ptc\
netmarkets\util\misc
sponding
helper and
forwarder)
actions. .xml Default system XML file for defining actions in the
xml system.
Runtime location:
<Windchill>\codebase\config \actions
actionmo- *.xml Default system XML file for defining action models ins the
dels.xml system.
Runtime location:
<Windchill>\codebase\config \actions
actions.dtd .xml Default system DTD file for defining structure of an
actions*.xml
Runtime location:
<Windchill>\codebase\config \actions
actionmo- *.xml Default system DTD file for defining structure of an
dels.dtd actionmodels*.xml
Runtime location:
<Windchill>\codebase\config \actions

The action framework provides a way to define actions and action models within
the system:
• StandardNmActionService manages the set of actions and action
models in the system.
In general, as a developer, you would not directly make calls to the
StandardNmActionService. These calls are done through the
components that support action and action model display (for example tables,
trees, and information pages).
• Actions and action models are defined using the XML files referred to as
actions*.xml and actionmodels*.xml.

Adding Actions and Hooking Them Up in the UI 513


• There is one default actions.xml and actionmodels.xml file that are
delivered with the system. They contain commonly used actions, such as copy,
cut, and common action models such as window buttons. These files are
located in the <Windchill>/codebase/config/actions directory.
• Each functional area can also have its own XML file, which is also managed
by the action service.
• For customization purposes, a custom-actions.xml and custom-
actionmodels.xml file are delivered with the product and are found in
<Windchill>/codebase/config/actions.
Additional actions*.xml and actionmodels*.xml files contain actions
and action models related to their functional areas. For
example,ChangeManagement-actions.xml contains actions related to
change management; PartManagement-actions.xml contains actions
related to part management.
For details about how to configure the action model to use for a component, see
related sections:
• See Constructing Wizards on page 837 for more detailed information on action
windows.
• See Presenting Information in the UI on page 603 for information on tables
and trees.
• See Information Pages on page 971 for information on object details pages.

Action Customization Guidelines


It is important to note the following:
• If you have an <objecttype> element in the custom-actions.xml
file, and that type exists within another actions.xml file, then actions from
your custom file will be added to the full set of actions supported for that type
(defined in the actions.xml file).
• This custom-actions.xml is read last of all the actions.xml files, so
if action names are duplicated, the one in this file will be used

Caution
If you have a <model> element in the custom-actionmodels.xml file,
and a model by that name already exists, your model will completely override
the ones processed before your custom action models file. Be very careful in
the naming of your models so that you do not wipe out others from files read
in prior unless that is the intent.

514 Customization Guide


Defining a New Action
Actions in the system are uniquely identified by the name of the action and the
object type. They should be defined in an XML file that follows the structure
based on codebase/config/actions/actions.dtd.
Here is an example of an action definition for the New Document window.
<objecttype name="document" class="wt.doc.WTDocument"
resourceBundle="com.ptc.windchill.enterprise.doc.documentResource">
<action name="create" uicomponent="CREATE_DOC" dtiUpload="true">
<command
class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor"
method="execute" windowType="popup" onClick="validateCreateLocation(event)"/>
<includeFilter name="projectM4D" />
<nonSupportedTypes value="wt.part.WTPart"/>
<supportedTypes value="wt.doc.WTDocument"/>
</action>
</objecttype>

objecttype Tag
The objecttype is a way to create a name space as well as packaging for
actions related to a specific object or functional area. In the above example, the
name “document” creates a unique name space for actions that apply to
wt.doc.WTDocuments.
Naming conventions for the name of an objecttype can be any combination of
alpha-numeric characters. Most objecttypes are an alias for the persistable
object to which the actions relate. Actions that apply to any object type, such as
copy, can be put within the objecttype of “object”.

Note
PTC recommends that all custom objecttypes have a prefix specific to the
company to prevent collisions with object types delivered with the product.

Adding Actions and Hooking Them Up in the UI 515


The table below describes the valid parameters for objecttype. Details about
these parameters can also be found in codebase/config/actions/
actions.dtd.
Parame- De- Possible Values Re- Description
ter fault q?
Value
name any combination Yes The name used to reference this
of alpha-numeric object type.
characters
class A valid Java class Yes Object class for the enclosed
actions
resource- Any valid resource No Class name for the default
Bundle bundle class name resource bundle to use for the
properties of the actions that are
to be localized

action Tag
The action name is a unique identifier for an action within the context of the
object type. The object type in conjunction with the action name make the action
unique within the system.
By default, the action name corresponds to the name of a JSP within the package
named for the object type. The packaging is relative to codebase/
netmarkets/jsp. For example, the action name in the XML example above is
“create.” Within the document object type, this corresponds to codebase/
netmarkets/jsp/document/create.jsp.
Naming conventions for the name of an action can be any combination of alpha-
numeric characters.

Note
PTC recommends that all your custom actions have a prefix specific to your
company to prevent collisions with names of actions delivered with the
product.

516 Customization Guide


The table below describes the valid parameters for action. Details about these
parameters can also be found in codebase/config/actions/
actions.dtd:
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
na- Yes This is the name by which the action is referenced
me
cad false true No Indicates if this action is only valid within the Creo
embedded browser
in- WI- No Applicable actions based on the installed components.
stall- ND- This is for legacy purposes only.
Typ- CH-
e ILL
PD-
M
PD-
M
PJL
PD-
M
mul- false false No Used to indicate that multi-selection of row data can be
tise- / used for this action. This is true only if the
lect true selectRequired attribute is also set to true for such an
action.
se- false false No Determines if the user interface should allow the action
lec- / to proceed if nothing has been selected. Otherwise, an
tRe- true error message appears.
qui-
red Note
If an onClick action handler is defined, the
onClick function must check if items are
selected. To do this, call the JavaScript function
table.getSelectionModel().hasSelec
tion()
af- No JavaScript function name to invoke on the client side
terJ- validation for an action window step after the step is
S completed.
be- No JavaScript function name to invoke on the client side
fore- validation for an action window step after the step is
JS loaded

Adding Actions and Hooking Them Up in the UI 517


Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
af- No Server validator name to invoke client side validation
ter- for an action window step after it is finished.
VK
be- No Server validator name to invoke client side validation
fore- for an action window step when the step is loaded.
VK
id ob- No Overrides the ID of the action window step.
ject-
type
.
ac-
tion
pre- true false No Specifies that the action window step is to be
loa- downloaded when the action window is launched
dW- true
izar-
d
Page
hid- false false No An action window step to be hidden first, or that an
den action is rendered as non-clickable
true
re- false false No Used for an action that represents a complete step in the
qui- action window. Specifies that the step is required.
red true
re- No Class name for the resource bundle to use for the
sou- properties of the actions that are to be localized
rce-
Bun-
dle
ren- PD- No Default
der- M
Typ- http://<host> /<webapp>
e General:
http://<host> /<webapp> <command.method>
General with context:
http://<host> /<webapp> <command.method> ?oid=...
PDM: URL generated by URLactionDelegate; used for
template processing
No References an entry in roleaccessprefs.xml

518 Customization Guide


Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
ui- (uic.name) to specify role-based access.
com-
po-
nent
pre- No The JavaScript function executed before an action
loa- window step is loaded or displayed.
dJS
post- No The JavaScript function is executed after an action
loa- window step is loaded into memory, but before it is
dJS displayed to the user.

Command and Component Attributes


If necessary, place a <command> or <component> tag in the body of the
<action> tag to define the processing aspects of the action.
<command
class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor"
method="execute" windowType="popup" onClick="validateCreateLocation(event)"/>
Or:
<component name="my.component.id" windowType="page" />
• The class attribute defines what class to use for processing.
• The method attribute defines what method to execute in the class.
• The windowType attribute determines what window action to take.
In the example above, the command is for the New Document action, which is an
action window (a wizard). Therefore, the windowType is “popup.” The
framework adds JavaScript that launches this action in a new window. The
specified class and method are executed upon submission.

Command Parameters

Pa- De- Po- Re- Description


ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
class No The class to use for processing.
met- No The method in the class to execute.
hod

Adding Actions and Hooking Them Up in the UI 519


Command Parameters (continued)
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
url No Used to override the generated URL
This attribute can be used to specify the location of the
JSP associated with the action. The value should be the
path of the JSP relative to <Windchill>/
codebase.
on- No Specifies an additional onClick function to call. This
Clic- is useful for confirming with the user whether to
k execute a special action.
For certain places where actions are used (such as a
menu bar or the toolbar on a table), onClick needs to
be a valid expression for an “if” statement. Therefore,
onClick should just be a call to a function.
The following are in scope variables that the onClick
function can pass as arguments:
• event — The browser event
• target — The object representing the user
interface component that was ‘clicked’
• table — The table that contains the action. This is
null if the action is not contained within a table.
onClick should not contain semi-colons or return
statements. For example:
• Correct:
onClick="doFoo()"
onClick="doFoo(event)"

520 Customization Guide


Command Parameters (continued)
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
• Incorrect:
onClick="doFoo();doBar();"
onclick="doFoo();Event.stop(event);"

Note
The use of the HTML-encoded character "'" to use a
single quote is not necessary; just use a regular
single quote instead.
When the actions are parsed, the action framework tries
to repair troublesome definitions. If they cannot be
repaired, then the onClick function is replaced with
an alert. Warnings are logged if the action was repaired;
otherwise errors are logged.
If the selectRequired attribute is set on the action,
then the onClick handler is called before any other
handlers. Thus, the onClick handler must check if
there are items selected in the table.
win- page new No new—Looks similar to other windows, but is launched
do- no_ differently. All of the form data is submitted to the
wT- con- popup window, making more information available.
ype tent However, the extra form data might overlap with form
nor- data already in the popup. It might be easier to override
mal the action URL to add additional information.
pop- no_content—The browser ignores the response
up from the server from this request. This value is not
recommended, rather create and Ajax request manually
wiz- through a JavaScript function.
ard_
step normal—Submits the form.
page —Display a new page.
popup—Create a non-modal popup action window.
wizard_step—Displays the action as a step in an
action window.

Adding Actions and Hooking Them Up in the UI 521


Component attributes are very similar to the command attributes. But instead of
providing a direct URL, the URL is generated given the MVC component ID. The
MVC component can determine the correct URL in the MVC delegate. See MVC
Components on page 257 for more information.

Component Parameters

Pa- De- Po- Re- Description


ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
na- Yes The MVC component id that should be used to display
me when this action is clicked.
com- IN- No The componentType affects whether objects
po- FO rendered on the resulting page are editable, read-only,
nen- or validated out. Values are from
PIC-
tTy- KER com.ptc.core.ui.resources.Component
pe Type
SE-
AR- The component type can change the URL to
CH typeBased under certain conditions such as INFO.
Some actions are only available under certain
TA- component types.
BLE
WI-
ZA-
RD
WI-
ZA-
RD_
TA-
BLE
WI-
ZA-
RD_
AT-
TRI-
BU-
TE-
S_
TA-
BLE

522 Customization Guide


Component Parameters (continued)
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
IN-
FO_
AT-
TRI-
BU-
TE-
S_
TA-
BLE
SI-
MP-
LE
MI-
NI_
IN-
FO
PRI-
MA-
RY_
AT-
TRI-
BU-
TES
url- URL parameters that are added to the generated MVC
Par- URL each time the action is rendered
ams
type- false Determines if the MVC delegate lookup should include
Bas- true the type of object being acted upon. The MVC URL
ed that is generated is /tcomp/ instead of /comp/ for
type-based components.

Adding Actions and Hooking Them Up in the UI 523


Component Parameters (continued)
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
on- No Specifies an additional onClick function to call. This
Clic- is useful for confirming with the user whether to
k execute a special action.
For certain places where actions are used (such as a
menu bar or the toolbar on a table), onClick needs to
be a valid expression for an “if” statement. Therefore,
onClick should just be a call to a function.
The following are in scope variables that the onClick
function can pass as arguments:
• event — The browser event
• target — The object representing the user
interface component that was ‘clicked’
• table — The table that contains the action. This is
null if the action is not contained within a table.
onClick should not contain semi-colons or return
statements. For example:
• Correct:
onClick="doFoo()"
onClick="doFoo(event)"

524 Customization Guide


Component Parameters (continued)
Pa- De- Po- Re- Description
ra- fau- ssi- q?
me- lt ble
ter Val- Val-
ue ues
• Incorrect:
onClick="doFoo();doBar();"
onclick="doFoo();Event.stop(event);"

Note
The use of the HTML-encoded character "'" to use a
single quote is not necessary; just use a regular
single quote instead.
When the actions are parsed, the action framework tries
to repair troublesome definitions. If they cannot be
repaired, then the onClick function is replaced with
an alert. Warnings are logged if the action was repaired;
otherwise errors are logged.
If the selectRequired attribute is set on the action,
then the onClick handler is called before any other
handlers. Thus, the onClick handler must check if
there are items selected in the table.
win- page new No new—Looks similar to other windows, but is launched
dow- no_ differently. All of the form data is submitted to the
Type con- popup window, making more information available.
tent However, the extra form data might overlap with form
nor- data already in the popup. It might be easier to override
mal the action URL to add additional information.
pop- no_content—The browser ignores the response
up from the server from this request. This value is not
recommended, rather create and Ajax request manually
wiz- through a JavaScript function.
ard_
step normal—Submits the form.
page —Display a new page.
popup—Create a non-modal popup action window.
wizard_step—Displays the action as a step in an
action window.

Adding Actions and Hooking Them Up in the UI 525


Adding Validation Logic for Your Actions
When creating a new action, there might be logic that you want executed to
determine if that action should be enabled, disabled, or hidden in the user
interface. You can write this logic in a class called a validator. See UI Validation
on page 770 for details about the validation service, writing a validator, and
registering the validator for your action.

nonSupportedTypes and supportedTypes Attributes


By specifying supportedTypes or nonSupportedTypes, the action
framework either enables or disables the action depending on the object types
mentioned. This filtering is applied only for a customized menu.
The supportedTypes or nonSupportedTypes filtering is applied before
any other validation service class defined by application developers. In other
words, it is a universal filter.
• If an action is disabled using the nonSupportedTypes attribute, then any
custom validators that have been written are not executed.
• If an action is enabled through the supportedTypes attribute, then any
custom validators that have been written are invoked.
For example:
<objecttype name="object" class="java.lang.Object" >
<action name="reports" enabledwhensuspended="true">
<command
url="netmarkets/jsp/carambola/customization/reports/base.jsp"/>
<nonSupportedTypes
value="wt.doc.WTDocument,wt.part.WTPart"/>
</action>
</objecttype>

Alternatively you can also use:


<objecttype name="object" class="java.lang.Object" >
<action name="reports" enabledwhensuspended="true">
<command
url="netmarkets/jsp/carambola/customization/reports/base.jsp"/>
<nonSupportedTypes>
<type value="wt.doc.WTDocument" />
<type value=" wt.part.WTPart " />
</nonSupportedTypes>
</action>
</objecttype>

526 Customization Guide


You can specify whether this filtering is applied to subtypes of an object. By
default, subtypes inherit this attribute. You can control this functionality by adding
the additional attribute applyToDescendants:
<supportedTypes>
<type value="wt.foo.Bar" applyToDescendants=”false” />
</supportedTypes>

Note
Supported and non-supported types can also be added using xconf properties
See Defining Non-Supported and Support Types in XConf on page 527 for
more information.

Pa- D- Po- R- Description


rame- ef- ssi- e-
ter a- ble q?
ult Val-
V- ues
al-
ue
value Any Y- Enables or disables the action for the listed object types.
ob- es Actions are enabled or disabled for third level
ject navigation and row level actions. No filtering is done for
typ- menu bar and toolbar actions.
es.
Sep-
arate
us-
ing
co-
mm-
as.
apply- tr- true No Whether you want the type to apply to inherited
ToDes- ue false subtypes. If true, then all subtypes are supported or non-
cen- supported as well. If false, then only the types specified
dants are supported or non-supported.

Defining Non-Supported and Support Types in XConf


The nonSupportedTypes and supportedTypes filtering can also be
added using xconf properties. There is a type-based xconf action filter that looks
through the typeBasedActionFilter.properties file.

Adding Actions and Hooking Them Up in the UI 527


Specify the property in the following format:
<Property name="<action object>.<action name>.
<supportedTypes or nonSupportedTypes>" value="com.foo.Bar" />

For example:
<Property name="annotation.annotationSets.nonSupportedTypes"
value="wt.part.WTPart" target="codebase/typeBasedActionFilter.properties"/>

Defining a New Action Model


Action models are defined in an XML file that follows the structure based on
codebase/config/actions/actionsmodels.dtd.
Here is a simple example of an action model definition used for the folder browser
toolbar:
<!-- default toolbar for the Folder page -->
<model name="folder_list_toolbar">
<action name="list_cut" type="object"/>
<action name="list_copy" type="object"/>
<action name="fbpaste" type="object"/>
<action name="pasteAsCopy" type="saveas"/>
<action name="list_paste_sharing" type="folder"/>
<action name="list_delete" type="object"/>
<action name="CONTAINERMOVE" type="pdmObject"/>
<action name="PAGERELOADINGMULTICHECKOUT" type="folder"/>
<action name="WFADDTOWORKSPACE" type="folder"/>
<action name="separator" type="separator"/>
<action name="create" type="folder"/>
<action name="create" type="document"/>
<action name="createMulti" type="document"/>
<action name="createPartWizard" type="part"/>
<action name="createMultiPart" type="part"/>
<action name="add_link" type="bookmark"/>
<action name="create" type="problemReport"/>
<action name="create" type="changeRequest"/>
<action name="create" type="changeNotice"/>
<action name="separator" type="separator"/>
</model>

The objecttype name is a way to create a name space as well as packaging for
actions related to a specific object or functional area. In the above example, the
name “document” creates a unique name space for actions that apply to
wt.doc.WTDocument.

528 Customization Guide


It is also possible to create an action model which itself references another action
model. The folder browser Actions menu contains a submodel for the New group
of actions. For example, the action model for the New group of actions might be
defined as follows:
<model name="folder_file_new" resourceBundle="com.ptc.core.ui.tableRB">
<action name="create" type="document" resourceBundle="com.ptc.core.ui.tableRB" />
<!-- More actions here --!>
</model>

Then, in the action model for the Actions menu, include the submodel “folder_
file_new”:
<model name="folder_file">
<submodel name="folder_file_new"/>
<action name="create" type="document"/>
<!-- More actions here --!>
</model>

See the figure below for how this appears in the user interface:

Model Attributes
Details about these parameters can also be found in the codebase/config/
actions/actionsmodels.dtd.
Pa- Default Possi- R- Description
rame- Value ble e-
ter values q?
name Y- This is the name by which the action model is
es referenced
menu- Any No Specifies which action should be highlighted
for valid by default. This is only applicable if the
class model is used as a third-level navigation
name. menu.
First Action Specifies which action should be highlighted

Adding Actions and Hooking Them Up in the UI 529


Pa- Default Possi- R- Description
rame- Value ble e-
ter values q?
de- action in name for by default. This is only applicable if the
faul- the model one of model is used as a third-level navigation
tAc- is used the menu.
tion- by actions in
Name default the
model.
de- First Object
faul- action in type of
tAc- the model one of
tion- is used the
Type by actions in
default the
model.
re- Class name for the resource bundle to use for
sour- the properties of the action models that are to
ce- be localized
Bun-
dle

530 Customization Guide


Action Attributes
Details about these parameters can also be found in codebase/config/
actions/actionsmodels.dtd.
Pa- De- Possible Req? Description
ra- fault Values
me- Value
ter
na- Name of Yes This is the name of an action defined in an
me any actions.xml file
action
defined in
an
ac
tions.x
ml file
type Name of Yes This is the name of an object type defined
any in an actions.xml file.
object
type
defined in
an
aac
tions.x
ml file
sho- true No This determines whether an action is
rtc- false displayed as a shortcut icon in the toolbar.
ut
Naming conventions for the name of an action model can be any combination of
alpha-numeric characters. Most action models are names include the component
that they are used in. Your action models should have a prefix specific to your
company to prevent collisions with other action models delivered with the
product.

Adding Actions and Hooking Them Up in the UI 531


Note
The action service is designed to hide the icons in the actions menu (or menu
bar menus) for any icon which is not contained in a toolbar somewhere else in
the system. The StandardNmActionService builds and keeps a list of
all known toolbar icons on server startup.
The StandardNmActionService is relying on the name of the model to
know whether it is a toolbar. Therefore, the name of a model used as a toolbar
should contain “toolbar.”
If the toolbar model naming convention is not followed, then the action
service cannot show icons as designed. However, no functionality breaks if the
naming convention is not followed.

"
Commonly used shortcut actions (recommended maximum up to five) can be
configured to appear on a toolbar shortcut area using a shortcut attribute.
Example configuration for folder browser table:
<model name="folder_list_toolbar">
………………………………………..
<action name="CONTAINERMOVE"
type="pdmObject" shortcut = "true"/>
<action name="PAGERELOADINGMULTICHECKOUT"
type="folder" shortcut = "true"/>
<action name="WFADDTOWORKSPACE"
type="folder" shortcut = "true"/>
…………………………….
<action name="create"
type="folder" shortcut = "true"/>
<action name="create"
type="document" shortcut = "true"/>
…………………………………
</model>

An action is a shortcut action only in the context of that specific model. Note that
icons for actions in the menus are be displayed for actions that also display in the
toolbar.

532 Customization Guide


SubModel Attributes
Details about these parameters can also be found in codebase/config/
actions/actionsmodels.dtd.
Pa- Default Possible Req? Description
rame- Value Values
ter
name Name of Yes This is the name of an action
any action model defined in an
model actionmodels.xml file. An
defined in example of where an action model
an with submodels is used is for the
action Actions ▶ New menu on the Folder
mod Contents table.
els.xm
l file

Sample Code
The following is sample code for an action model that configures a subtype:
<!-- Copied from ChangeManagement-actionModels.xml -->
<!-- Originally copied from menu for wt.change2.WTChangeRequest2 -->
<model name="sample change request actions" menufor="WCTYPE|
wt.change2.WTChangeRequest2|org.default.www.SampleChangeRequest">
<action name="view" type="object"/>
<action name="SETLIFECYCLESTATE" type="pdmObject"/>
<action name="createSubscription" type="subscription"/>
<action name="separator" type="separator"/>
<action name="reviseChangeItems" type="change"/>
<action name="editCapabilityPackage" type="capabilityPackage"/>
<action name="create" type="approach" />
<action name="create" type="capabilityImplementationProject" />
<action name="separator" type="separator"/>
<action name="sandboxAddToProject" type="object"/>
<action name="SBAddToPrj" type="sandbox"/>
<action name="removeShare" type="object"/>
<action name="separator" type="separator"/>
<action name="ManageSecurity" type="accessPermission"/>
<action name="renameObjectWizard" type="object"/>
<action name="delete" type="object"/>
<action name="separator" type="separator"/>
<action name="separator" type="separator"/>
<action name="discuss" type="forum"/>
<action name="copy" type="object"/>
</model>

Adding Actions and Hooking Them Up in the UI 533


Where org.default.www.SampleChangeRequest is the name of the
subtype entered in the Type and Attribute Management utility.

Localizing Actions and Action Models


Use .rbInfo files to localize the properties for your action and action models.
For more information see the Resource Info (.rbInfo) Files on page 2071 section
of Internationalization and Localization on page 2063.

Localize Actions
The format for entries in the .rbInfo is:
<objecttype name>.<action name>.<purpose>.value=<value>

Element Possible Description


Values
objecttype name Corresponds to the name value for
objecttype in the actions.xml file.
action name Corresponds to the name value for
action in the actions.xml file.

534 Customization Guide


Element Possible Description
Values
purpose title title—Localizable text for the title bar if
description the action appears in an action window.
description—Localizable text for the
tooltip
label of the action.
icon
tooltip—Localizable text shown when
morurlinfo hovering over the action.
hotkey icon: An image file, relative to
codebase/netmarkets/images
moreurlinfo: Parameters used to size
the window for this actions
hotkey: The alphanumeric key to trigger
this action.
value The actual value for the entry.

For example:
<objecttype name="document" class="wt.doc.WTDocument"
resourceBundle="com.ptc.windchill.enterprise.doc.documentResource">
<action name="create" uicomponent="CREATE_DOC" dtiUpload="true">
<command
class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor"
method="execute" windowType="popup"
onClick="validateCreateLocation(event)"/>
<includeFilter name="projectM4D" />
</action>
</objecttype>

The documentResource.rbinfo file contains an entry as follows:


document.create.title.value=New Document
document.create.description.value=New Document
document.create.tooltip.value=Add a new document with or without attached
content
document.create.icon.value=newdoc.gif
document.create.moreurlinfo.value=height=1000,width=820

Icon and tooltip are shown here in the toolbar and also in the menus. Note that
icons for actions in the menus are only displayed for actions that also display in
the toolbar:
document.create.title.value=New Document

Adding Actions and Hooking Them Up in the UI 535


document.create.description.value=New Document

Title:

Icon and description:


document.create.description.value=New Document
document.create.icon.value=newdoc.gif

536 Customization Guide


You can also specify a resourceBundle property on the on the <objecttype>
element. If an <action> element does not specify a resourceBundle property,
the resourceBundle property specified on the <objecttype> element for that
action is used.

Localize Action Models


Some action models need a display label (for example, third-level navigation
action models or menu bar action models). You can specify the rbInfo to use on
your action model:
<model name="relatedItems"
resourceBundle="com.ptc.core.ui.navigationRB">

The entries follow the same format as that of the actions:


object.relatedItems.description.value=
<U class="mnemonic">R</U>elated Objects
object.relatedItems.description.comment=Used for the
text on the Related Objects third level navigation menu.
object.relatedItems.hotkey.value=r
object.relatedItems.hotkey.comment=Mnemonic

The <U class="mnemonic > </U> tag should be put around the character that
is the access key (“R” in the example above).

Reporting Tools for Actions and Action Models


PTC supports modularized actions and actionmodels within the system, so
to find what file an action is defined in, or what action models the action is used
in, there is a reporting tool that can be used.
See the Customization Tools Overview on page 404 section for more information
on the Action Report and the Action Model Report.

Action Report
http://<your machine name>/<app-name>/app/#ptc1/
carambola/tools/actionReport/action
The Action Report allows you to search for actions managed by the
StandardNmActionService. You can search by several properties for the action
including the label (the description), action name, and object type name.
The search supports multiple search parameters, regular expressions, and case-
insensitive matching. See Action Report on page 406 for more information.

Action Model Report


http://<your machine name>/<app-name>/app/#ptc1/
carambola/tools/actionReport/actionModel

Adding Actions and Hooking Them Up in the UI 537


The Action Model Report allows you to search for action models managed by the
StandardNmActionService. You can search by action model name, description and
model file. The search supports multiple search parameters, regular expressions
and case-insensitive matching. See Action Model Report on page 410 for more
information.

Debug Tool
There is also a debug mode that can be enabled in the user interface to find
information about a particular action on a page. See Debugging on page 432 for
information on enabling and using this tool.

Reload Actions
http://<your machine name>/<app-name>/app/#ptc1/
carambola/tools/list
This tool reloads the action models from their XML files without having to restart
the method server. See Reload Action on page 418 for more information.

538 Customization Guide


Tab Models
Objective
You want to change something in the navigator section of the page. For example,
you want to add or remove tabs in the navigator.

Background
The tabs rendered in navigator are nothing but actions in action lists just like any
other actions in the system. Adding tabs and tabs under them is very much like
adding any other action into the system, but there are some additional special
considerations.

Scope/Applicability/Assumptions
• Assume you need to add a new tab to the main navigation of the navigator.
• Assume you need to remove an existing tab from the main navigation of the
navigator.
• Assume you need to add/remove links in the second level navigation.

Solution
Create new actions, an action model, and JSPs for the tab and sub tabs to be
added.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving CSS, JSP and XML.
• The actions framework in the Windchill client architecture. For more
information see, Action Framework for Windchill Client Architecture on page
512
The management of RBINFO file customizations. For more information see,
Localizing Actions and Action Models on page 534.

Solution Elements
Element Type Description
codebase\config\actions XML This file contains the action
\navigation-actions.xml definitions for the actions that
represent the tabs and sub tabs
in the Windchill system
codebase\config\actions XML This file is used for adding

Adding Actions and Hooking Them Up in the UI 539


Element Type Description
\custom-actions.xml custom actions and customizing
existing actions.
codebase\config\actions XML This file contains the action
\navigation-actionModels.xml model definitions used in the
navigation. Including the main
tab list, the sub tab list, the
recent lists, and the header
actions lists.
codebase\config\actions XML This file is used for adding
\custom-actionModels.xml custom action models and
updating existing action models.
codebase\action.properties or an rbinfo Preference files
rbinfo file
<mytab>/<list>.jsp JSP This is the JSP file you will
create as the default content for
the tab you are adding. You can
create as many additional JSPs
to associate with sub tabs as you
need.

Procedure - Adding Tabs in the Navigator at Different Levels


The tabs in the red circle are the navigator tabs, the tabs in the blue circle are the
first level navigation tabs, and the items in the green circle are the second level
navigation. The following sections will detail how to add tabs at different levels.

540 Customization Guide


Adding navigator tab
The following sections detail how to add custom navigator tab.

Adding navigator tab - Create an action in custom-actions.xml


Create an action for your new tab in custom-actions.xml. You can create
any type of action for a first level tab. In this example we will create an action that
maps to the JSP. See Action Framework for Windchill Client Architecture on page
512 for further details.
<objecttype name=" myType " class="com.ptc.myTabClass">
<action name=" myNavigatorTabAction1" >
<command windowType="page"/>
</action>
<action name=" myNavigatorTabAction2" >
<command windowType="page"/>
</action>

</objecttype>

Create an entry in resource file


Create localization strings for your action in your own resource file. See the
Action Framework for Windchill Client Architecture on page 512 for more
detailed information.

Adding Actions and Hooking Them Up in the UI 541


Create and define action model
Create an action model using newly defined actions as below in custom-
actionModels.xml. Define rbinfo entries for this action model.
<model name=”myNavigatorTab navigation”>
<action name=”myNavigatorTabAction1” type=”myType” />
<action name=”myNavigatorTabAction2” type=”myType” />
</model>

Add action model to navigator action model


Copy definition of navigator tab action model (model name= “navigator”)
from navigation-actionModels.xml <model name=”navigator”>
to custom-actionModels.xml. Add the new action model entry to it.
<submodel name=”search navigation” />
<submodel name=”main navigation” />
<submodel name=” myNavigatorTab navigation” />
</model>

Adding first level tab in navigator


This section details how to add custom first level tab in navigator.

Create an action in custom-actions.xml


Create an action for your new tab in custom-actions.xml. If your action
requires stickiness you should use the navigation servlet for your action.
<objecttype name="navigation" class="">
<action name="mytab" renderType="GENERAL">
<command class="netmarkets" method="servlet/Navigation?tab=mytab"
windowType="page"/>
</action>

</objecttype>

Add your action to the main navigation action model in custom-


actionModels.xml
Copy the “main navigation” action model from navigation-
actionModels.xml to custom-actionModels.xml.
Add above created action “mytab” to the action model.
<!-- Main navigation -->
<model name="main navigation">
<action name="home" type="navigation"/>
<action name="product" type="navigation"/>
<action name="project" type="navigation"/>
<action name="change" type="navigation"/>
<action name="library" type="navigation"/>
<action name=”mytab” type=”navigation”/>
<action name="org" type="navigation"/>
<action name="site" type="navigation"/>

542 Customization Guide


</model>

Create an entry in a rbinfo file


Create localization strings for your action in action.properties or your
own rbInfo file. See Action Framework for Windchill Client Architecture on page
512 for more detailed information.

Adding second level navigation links in navigator


This section details how to add custom second level navigation link in navigator.

Create a new sub model for your tab in custom-actionModels.xml


Your new first level tab will need a sub model to define second level navigation.
In order for the navigation to find the sub model it must be named after the main
tab that it belongs to. For sub models the parameters defaultActionType and
defaultActionName are required. These parameters tell the system which
action is the default when the user has never visited this tab before.
In our example we will need to create a new action model called “mytab
navigation” like this:
<model name="mytab navigation" defaultActionType="mytab"
defaultActionName="list">
</model>
You can now add second level navigation links to your new action model
following the instructions in Adding second level navigation links in navigator on
page 543. You must create at least one second level navigation link whose name
and type match the defaults specified in the action model tag.

Customization Points
See Action Framework for Windchill Client Architecture on page 512 for more
information.

Procedure - Removing a Main Tab


Copy the “main navigation” action model from navigation-
actionModels.xml to custom-actionModels.xml. Remove the
required action model.
<!-- Main navigation -->
<model name="main navigation">
<action name="home" type="navigation"/>
<action name="product" type="navigation"/>
<action name="project" type="navigation"/>
<action name="change" type="navigation"/>
<action name="library" type="navigation"/>
<action name=”mytab” type=”navigation”/>
<action name="org" type="navigation"/>

Adding Actions and Hooking Them Up in the UI 543


<action name="site" type="navigation"/>
</model>
After removing the “change” tab from the main navigation action model above.
The list will look like this:
<!-- Main navigation -->
<model name="main navigation">
<action name="home" type="navigation"/>
<action name="product" type="navigation"/>
<action name="project" type="navigation"/>
<action name="library" type="navigation"/>
<action name=”mytab” type=”navigation”/>
<action name="org" type="navigation"/>
<action name="site" type="navigation"/>
</model>

Procedure — Removing a Second Level Navigation Link


Copy the action model definition which needs to be updated to custom-
actionModels.xml from navigation-actionModels.xml. Update the
action model definition by removing the action definition from it.
Original definition of product navigation action model :
<model name="product navigation">
<action name="list" type="product"/>
<action name="separator" type="separator"/>
<action name="view" type="object"/>
<action name="listFiles" type="product"/>
<action name="listTeam" type="product"/>
<action name="listProduct" type="work"/>
<action name="changeMonitor" type="product"/>
<action name="view_forum" type="project"/>
<action name="MyWorkspace" type="product"/>
<action name="listTemplates" type="product"/>
<action name="listUtilities" type="product"/>
</model>

After removing the Change Monitor action from the product action list above, the
list will look like this:
<model name="product navigation">
<action name="list" type="product"/>
<action name="separator" type="separator"/>
<action name="view" type="object"/>
<action name="listFiles" type="product"/>
<action name="listTeam" type="product"/>
<action name="listProduct" type="work"/>
<action name="view_forum" type="project"/>
<action name="MyWorkspace" type="product"/>

544 Customization Guide


<action name="listTemplates" type="product"/>
<action name="listUtilities" type="product"/>
</model>

Procedure — Customize a Navigator


If required, there is a way to override default navigation behavior in the navigator.
This can be achieved by implementing
com.ptc.windchill.enterprise.navigation.NavigationList
Delegate and providing a custom behavior. For example, there is a requirement
that a particular first level navigation tab should show all the nodes instead of
showing only recently accessed nodes.
The following section will illustrate an example of showing all the context nodes
instead of default behavior of showing only recently accessed ones.

Create a Custom Navigation List Delegate


In general it is not recommended to implement the interface
NavigationListDelegate directly. You should subclass one of the existing
out of the box implementations like
com.ptc.windchill.enterprise.navigation.delegates.De
faultNavigationListDelegate.
Example:
public class MyTabNavigationListDelegate extends DefaultNavigationListDelegate {
/**
* Returns list of all the c.
*/
@Override
public Vector<ObjectVisitedInfo> getRecentStack(String node,
Vector<ObjectVisitedInfo> recent)
throws WTException {
// Specific code for getting all the contexts for that particular tab
return recent;
}
}

There are also other methods that you may wish to override but
getRecentStack() is the only one required for this particular use case.

Register MyTabNavigationListDelegate
To register this custom delegate, the property should be added to a specific
customized service.properties.xconf file or site.xconf.
In the above example you would register it something like the following:
<Service name="com.ptc.jca.navigation.NavigationListDelegate">
<Option serviceClass="com.ptc.myTab.navigation.MyTabNavigationListDelegate"

Adding Actions and Hooking Them Up in the UI 545


requestor="java.lang.Object" selector="MyTab"/>
</Service>

After registering you will need to run xconfmanager -p from a windchill shell
and restart the method server.

Adding Multiple Levels in the Navigation Tree


Out of the box, “browse” tab in navigator has a tree with two levels. More levels
can be added by adding a sub-model to existing action model.
Example: Original tree

To add a new navigation hierarchy:


1. Create a model in custom-actionModels.xml.
<model name="productNav1">
<action name="info" type="product"/>
<action name="listFiles" type="product"/>
</model>
2. Copy the existing action model in navigation-actionModels.xml to
custom-actionModels.xml. Add above model as a submodel to this
action model definition.
<model name="product navigation" defaultActionName="list"
defaultActionType="product">
<description>
Sub tabs under the product main tab
</description>
<action name="info" type="product"/>
<action name="aspsStructure" type="asps" />

546 Customization Guide


<action name="listPubStructures" type="arbortext"/>
<action name="listFiles" type="product"/>
<action name="structureSubTab" type="product"/>
<action name="MyWorkspace" type="workspaces"/>
<action name="listNetwork" type="network"/>
<action name="list" type="wp"/>
<action name="listTeam" type="product"/>
<action name="listProductAssignments" type="work"/>
<action name="changeMonitor" type="change"/>
<action name="view_forum" type="project"/>
<action name="listTemplates" type="product"/>
<action name="reports" type="product"/>
<action name="listAgreements" type="agreements"/>
<action name="listUtilities" type="product"/>
<submodel name="productNav1" />
</model>

The new Navigation tree will look like:

The sub-model can be nested into other submodel to add multiple levels of
navigation
Example:
The above model can have more submodels as
<model name="productNav1">
<action name="info" type="product"/>

Adding Actions and Hooking Them Up in the UI 547


<action name="listFiles" type="product"/>
<submodel name="productNav2" />
</model>

Where
<model name="productNav2">
<action name="someAction" type="object"/>
<action name="someMoreAction" type="object"/>
….
</model>

Limitations
In order to get your tab to display and highlight correctly you must follow the
following conventions
• You must place your JSPs in a directory that exactly matches the name you
gave to your main tab in Adding navigator tab on page 541. In that example
the main tab name is “mytab”.
• You must create a JSP whose name exactly matches the defaultActionName
and whose directory exactly matches the defaultActionType you
specified on the action model in Adding second level navigation links in
navigator on page 543. In this example the JSP would be “mytab\
list.jsp”.
• You must name your JSP exactly the same as your action. In this example both
are named “list”.

Additional Resources
• Action Framework for Windchill Client Architecture on page 512

548 Customization Guide


Customizing Role-based Visibility
Objective
You want to customize the set of UI components (actions or other UI elements)
that the administrators of the site, organization or containers can manage using the
role-based visibility feature.

Background
The role-based UI functionality enables administrators to optimize the number of
actions presented to users, so as not to confuse users by seeing actions they don't
need or use for their role. Initially this support was just for container managers (in
particular, project managers). It has been extended to a concept called profiles
which sets action visibility at the site or organization level.
A site administrator, organization administrator or container administrator can
specify which users have visibility to the actions defined. For site and organization
administrators this can be done through profiles. Profiles can be created at Site-
>Profiles or Org->Profiles. The actions defined will be presented with their
default settings, and the administrator can choose to hide those actions. The
administrator can then specify which participants (users, groups, orgs) belong to
the profile. All members of the profile will have that visibility. If a member is in
multiple profiles, the greatest visibility is provided.
At the container level, the administrator can specify the visibility based on user
roles. Anyone in those roles will have the visibility specified. Container-level role
visibility will override any profile in which the member might be a participant.
See theWindchill Business Administrator's Guide for more details about profile-
and role-based visibility administration.

Scope/Applicability/Assumptions
• The role-based visibility administration capability is turned on, that is, the
preference com.ptc.netmarkets.roleAccess.enabled is set to true. The
customization can be performed while the capability is turned off, but the
results will not appear in the UI until the capability is turned on.
• The customizer can manage both out-of-the-box UI components and
customized UI components with this capability.

Intended Outcome
When configuring visibility by roles and configuring profiles, the administrator is
presented with a list of UI components that can be managed. The administrator is
unable to manage the visibility for any UI components that are not included in this
list.

Adding Actions and Hooking Them Up in the UI 549


As a customizer, you have the ability to customize the list of UI components
available to administrators. You can:
• add UI components to the list,
• remove UI components from the list,
• specify default visibility settings for UI components,
• change the order that UI components appear in the list, and
• change the labels for the UI components on the list.
At the site or organization level your intention is to manage the list presented
when creating profiles:

550 Customization Guide


At the container level, you are managing the equivalent list presented when
configuring visibility by roles:

Solution
Modify the roleaccessprefs.xml file (and associated files as needed).

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• The behavior of user roles in Windchill
• The administration of ad hoc access control policies in Windchill
• The actions framework in the Windchill client architecture
• The navigation framework in the Windchill client architecture
• The management of XML file customizations
• The management of RBINFO file customizations

Adding Actions and Hooking Them Up in the UI 551


Solution Elements
Element Type
Description
*actions.xml XML
Files where actions and other UI
components are defined. Actions are
optionally given a uicomponent value.
Actions.xml is located in <Windchill>/
codebase/config/actions along with
other *actions.xml files.
Roleaccessprefs.xml XML File for assigning default visibility to
UI components. Setting items in this
file can make them not appear at all for
the site or containers. Whether or not
the container manager can override the
default value can also be changed here.
Located in <Windchill>/codebase.
RoleAccessResource.rbInfo RBINFO Defines the labels to provide in the Uis
for the actions or UI components.
Located in <Windchill>/wtCustom/
com/ptc/netmar kets/roleAccess/.

In actions.xml (and all *actions.xml files), an action can be assigned a


uicomponent attribute value. The uicomponent attribute provides a name for a UI
component that can be referenced from the roleaccessprefs.xml and
roleAccessResource.rbInfo files. Multiple actions can use the same uicomponent
value; this provides the ability to manage those actions as a single UI component.
If an action does not have a uicomponent, then the action “name” can be used to
reference it as a UI component instead. However, in this case it cannot be grouped
with other actions into a single UI component.
The roleaccessprefs.xml file consists of a <uics> element containing several
elements (or sections) that correspond to the primary tabs in the Windchill user
interface. For example, the <project> section corresponds to the Project tab. Each
section contains zero or more <uic> elements, each representing a UI component
whose visibility within that tab can be administered. Each UI component,
specified with the “name” attribute of the <uic> element, can appear in one or
more sections. This allows the default visibility settings for that UI component to
be assigned independently for different tabs.
The roleaccessprefs.xml file applies to the UI component lists for visibility
administration based both on profiles (at the site and organization levels) and on
roles (at the container levels). However, the <global> section applies only to
visibility administration using profiles. If a UI component is not tied to a specific
tab (such as is the case with the Search link in the Windchill UI header) or the UI
component is a first-level tab itself, it should be listed in the <global> section of
roleaccessprefs.xml.

552 Customization Guide


Each UI component must have an entry in roleAccessResource.rbInfo that
provides a user-friendly label for that UI component. These labels are used for the
UI components in the lists that are presented to the administrator when
configuring visibility. In this file the resource entry “constant” identifies the UI
component; it must match either the uicomponent from the action definition or the
action name if the action has no uicomponent. The resource entry “value”
provides the user-friendly label.

Note
Your UI component label should be a verb phrase. If your action/UI
component name is not already a verb phrase, place 'View' in front, for
example "View Team Page."

Procedure - Making an Action Available to Visibility Administration


In this example, you provide the administrator with the ability to manage the
visibility of the Create Folder action in the Project, Program, Product, and Library
tabs.

Note
This example assumes that the Create Folder action is not already available for
role-based visibility management; in the actual product, it is available out of
the box.

1. Add a new <uic> to the roleaccessprefs.xml under the sections <project>,


<program>, <product>, and <library>:
<uic name="PROJECT_CREATE_FOLDERS" order="00" enabled="true"
defaultAll="true" defaultManager="true" defaultGuest="false"
managerEnabled="true" guestEnabled="false"/>

See the section on The uic Element on page 555 for attribute descriptions.

Note
For actions that are valid for multiple tab types, put the entry under all the
section you want it to affect.

2. In roleAccessResource.rbInfo, add a new resource entry for the action display


name:
31.value=Create Folders

Adding Actions and Hooking Them Up in the UI 553


31.constant=PROJECT_CREATE_FOLDERS

Regenerate your bundles. The name of the uic should be the same as the
constant for the entry in the resource bundle.
3. In <Windchill>/codebase/config/actions/actions.xml, modify the create folder
action by: adding the attribute uicomponent="PROJECT_CREATE_
FOLDERS"
<action name=" folder_create" checkaccess="true"
uicomponent="PROJECT_CREATE_FOLDERS">

Caution
Follow best practices in backing up your XML files when customizing
them.

4. Restart the servlet engine and the method server.


Steps 1 through 3 above can be performed in any order. Note that "PROJECT_
CREATE_FOLDERS" is used for the uic name, the resource entry constant (but
without the quotes), and the action uicomponent. It is necessary for all three of
these items to share the same value in order to tie the customized behavior
together.
Upon completion of this procedure, an administrator can now configure the
visibility to the Create Folder action under the Project, Program, Product, and
Library tabs, based on profiles defined at the site or organization level, and based
on roles at the container level.

554 Customization Guide


Customization Points

The uic Element


Each UIC in roleaccessprefs.xml represents a UIComponent or action to be
controlled.
Parameter Default Possible values Req? Description
Value
name n/a string Y The name of the UI
component. This
must match the
value of the
uicomponent (or
name) attribute on
an action element in
actions.xml. This
must also match the
value of a resource
entry constant in the
resource bundle.
Order ? Non-negative? N The position of this
Integer UI component in the
wizard. UI
components with
lower numbers are
placed before those
with higher
numbers.
Enabled true true | false N Whether or not this
uicomponent will be
shown in the wizard
and utilized by the
system.
DefaultAll true true | false N The default visibility
value for All
Members.
DefaultManager true true | false N The default visibility
value for Project
Managers.
The permissions are
a union of all
permissions across
all roles; if you set
defaultManager to
false; you should

Adding Actions and Hooking Them Up in the UI 555


Parameter Default Possible values Req? Description
Value
also defaultAll to
false, otherwise
managers will still
have access through
the ALL_
MEMBERS role.
DefaultGuest true true | false N The default visibility
value for people in
the Guest role.
Guests are not
technically members
of the Project; they
are not unioned with
the ALL_
MEMBERS role.
ManagerEnabled true true | false N Whether or not this
uicomponent can
affect the manager
role. Do not change
this value in out-of-
the-box UICs. For
customized UICs,
you may choose
your own setting.
GuestEnabled true true | false N Whether or not this
uicomponent can
affect the guest role.
Do not change this
value in out-of-the-
box UICs. For
customized UICs,
you may choose
your own setting.

556 Customization Guide


Parameter Default Possible values Req? Description
Value
RunClass — Java class name N The class on which
runMethod exists
runMethod — Java method name N The method to run
when the UIAccess
is changed.
This represents the
name of a method
that will be run when
a UIAccess element
associated with this
UIComponent is
updated.
The signature of this
method must be:
void foo
(WTPrincipal
principal,
WTContainer
container, boolean
isRender)
The principal passed
in will be the group
or user on which to
operate. The boolean
isRender is the
updated value for the
UIAccess.

Adding Actions and Hooking Them Up in the UI 557


Making a Customized Tab Available to Visibility
Administration
Making a customized action available to visibility administration is essentially the
same procedure as making an out of the box action available. A tab, however,
cannot be managed by container administrators (configuring role-based visibility).
Therefore you can only make a customized tab available to site and organization
administrators for configuring visibility profiles. This means you can add a <uic>
element for the tab only to the <global> section of roleaccessprefs.xml. For
example, assume that you have already created a customized tab, and have an
associated <MyTab>actions.xml file. You can add the tab to the list for profile-
based visibility administration as follows:
1. Add a new uic element to roleaccessprefs.xml under the <global> section with
a unique name, for example, CUSTOMIZED_TAB.
<uic name="CUSTOMIZED_TAB" order="190" enabled="true"
defaultAll="true"/>
2. Associate the appropriate actions in actions.xml with the UIComponent.
< oolean pe name="customization" >
<action name="list2" uicomponent="CUSTOMIZED_TAB">
<command windowType="page"/>
</action>
3. Add a new entry to roleAccessResource.rbInfo with a constant that is the same
as the uic name. The value is what will be displayed in the profile actions UI.
40.value=View Customized Tab
40.constant=CUSTOMIZED_TAB
4. Restart the servlet engine and the MethodServer.

Assigning One uicomponent to Multiple Actions


If you want to tie one UI component to multiple actions, you need to specify the
uicomponent attribute for each of those actions, using the same value. For
example, the procedure described in theProcedure - Making an Action Available
to Visibility Administration on page 553 creates a UI component called
PROJECT_CREATE_FOLDERS associated with the folder_create action. You
can assign the list_create_folder action to the same UI component by specifying
the uicomponent attribute for that action in actions.xml as follows:
<action name="list_create_folder"
uicomponent="PROJECT_CREATE_FOLDERS" ajax="row">

As a result, the "Create Folders" entry in the Configure Roles and Create Profile
pages will affect the visibility for both folder_create and list_create_folder actions.

558 Customization Guide


Changing the Labels for a UI Component
You can alter the label used for a UI component in the Configure Roles or Create
Profile pages, without making any other changes to that UI component. Simply
change the associated resource entry value in the roleAccessResource.rbInfo file,
and regenerate your bundles. For example:
31.value=Create Folders - My New Label
31.constant=PROJECT_CREATE_FOLDERS

Updating Access Control (Advanced Role-Based UI)


It is possible to extend user permissions using Role-Based UI. This can be used
for updating real access control (in the form of ad hoc or policy access control
lists), or for doing potentially anything else.
This is accomplished by specifying a class/method combination on the uic in the
configuration file. The method will be called when the UIComponent it is
associated with is updated. For example, part of the Role-Based UI feature
includes the ability to extend Modify Team permissions. The uic element in the
configuration file includes two additional attributes that identify the class and
method to call:
<uic name="PROJECT_MODIFY_TEAM" order="30" enabled="true"
defaultAll="false"
defaultManager="true" defaultGuest="false"
managerEnabled="false" guestEnabled="false"

runClass="com.ptc.netmarkets.roleAccess.StandardNmRoleAccessService"
runMethod="modifyTeamPermissions"/>

The only restriction on runClass is that it needs to be accessible from the


MethodServer. Given runMethod="myRunMethod", then myRunMethod must
have the following signature:
public static void myRunMethod(WTPrincipal principal, WTContainer
container, boolean isRender)
throws WTException

The principal passed in will be the group or user on which to operate. The boolean
isRender is what the field in the UIAccess table was just set to for the passed in
principal.

Adding Actions and Hooking Them Up in the UI 559


Sample Code

Examples of Usage in out-of-the-box Code


An example of multiple actions using the same uicomponent is the Team pages in
Product/Project/Library share the same code, but each action is defined separately
for each object. Each action has the same uicomponent of "PROJECT_TEAM".
This allows the same resource (rbInfo) entry to be used, and helps to minimize the
size of the action display table in the Create Profile page. PROJECT_TEAM still
needs to be defined in roleaccessprefs.xml for each tab type in which it is used,
and different defaults can be set for each.

Additional Resources

Related Customization Documentation


• Managing Customizations on page 100.

Other Related Windchill Documentation


• Windchill Business Administrator's Guide — Role-Based Visibility
Administration
• Windchill Business Administrator's Guide — Access Control (ad hoc policies)

560 Customization Guide


User Interface Stickiness
When the page is refreshed, the current state of the page is not kept intact. HTTP
cookies could be used to maintain some state, but they are limited in size, and are
transmitted back to the server with each request. Some client state information
should also be restored when the user logs in on different machines.

Background
As a user navigates within Windchill, they may make changes that affect the user
interface display, such as selecting a tab on the information page (for example,
selecting My Tab). If the browser is refreshed, the user may expect to remain on
their last active tab. To retain this information, some sort of persistence
mechanism is required to refresh the page to the correct state .
There are two persistence mechanisms available for use. The Client State Provider
will store information in the browser and will be specific to that particular browser
on that particular machine. The Server State Provider will store information in the
database and will make the information available for that user on any browser and
any machine.

Resetting Stickiness
If user interface stickiness is causing issues or acting strangely, you may need to
reset the stickiness. Server state stickiness and client state stickiness are reset
differently, and you don’t necessarily need to reset both, depending on what is
acting strangely.
To reset the server state stickiness, navigate to http://<host>/<webapp>/app/
netmarkets/jsp/user/utilitiesList.jsp and click “Reset Server Stickiness”. This
action will popup a confirmation box and by clicking OK all your server state
stickiness will be reset to the default state. This includes both Information Page
tab order and Information Page table order.
Various actions may clear the client state provider stickiness information
depending upon your browser. To ensure that all client stickiness is removed,
delete all your temporary internet files (usually in the Tools menu), close all
browser windows, and restart the browser.

Adding Actions and Hooking Them Up in the UI 561


Defining Menus
You want to have a set of actions be displayed in one of the following areas:
• Actions column in a table
• Toolbar actions for a table
• Menu bar actions for a table
• Actions menu on an information page

Background
There are several documents that describe certain aspects of the Action Model
framework. This documentation is intended to provide concrete examples for a
few of the main uses of action models within the Windchill application.

Scope/Applicability/Assumptions
This documentation is intended to be used as a starting point for developers
wanting to configure an actions menu to be rendered in the UI using the JCA
framework. This information has references to other sources of information which
will cover specific topics in greater detail.

Intended Outcome
The following sections provide a screenshot for the main areas where action
models are used.

562 Customization Guide


Actions Column in a Table
By default the actions column is not displayed, and users cannot see it through
configuration. Users can get to those actions by right-clicking anywhere within the
row.

Toolbar Actions for a Table

Adding Actions and Hooking Them Up in the UI 563


Menu Bar Actions for a Table

Actions Menu on an Information Page

564 Customization Guide


Displaying Actions
You want to have a set of actions be displayed in one of the following areas:
• Actions column in a table
• Toolbar actions for a table
• Menu bar actions for a table
• Actions menu on an information page

Displaying Actions Column in a Table

Note
You can no longer add the actions column to tables. The actions column is in
the data store, but not available in the UI. The actions menu is only available
by right-clicking each row

1. Define the actions in an actions.xml file (see Defining a New Action


Model on page 528)
2. Add the actions to an action model (see Defining a New Action Model on
page 528). There are multiple levels where the action model can be set for a
particular table. They are listed below in ascending order of complexity:
a. Define a “menufor” a business object type.
In the action model definition (in the XML file), set the attribute
“menufor” for the object type that you are defining the actions for.
<model name="part actions" menufor="wt.part.WTPart">
<action name="view" type="object"/>
.....
</model>

Adding Actions and Hooking Them Up in the UI 565


To get a menu to fly out from the main menu, add a submenu to the action
model.

<model name="part actions" menufor="wt.part.WTPart">


<action name="action_1" type="object"/>
<submodel name="submenu_new"/>
</model>

<model name="submenu_new">
<action name="newViewVersion" type="part"/>
</model>
b. Set action model in a Builder.
There can only be one action model per type with the menufor attribute. If
you would like to override the default action model for your table you can
specify a different model in your table builder. See MVC Components on
page 257 for information on creating a table builder class.
public ComponentConfig buildComponentConfig (ComponentParams params) {
ComponentConfigFactory factory = getComponentConfigFactory ();
JcaTableConfig table = (JcaTableConfig) factory.newTableConfig ();

ColumnConfig actionsMenu = setComponentConfigFactory().


newColumnConfig(DescriptorConstants.ColumnIdentifiers.NM_ACTIONS, true);

566 Customization Guide


(JcaColumnConfig)actionsMenu).setDescriptorProperty
(DescriptorConstants.ActionProperties.ACTION_MODEL,
"model_name_here");
table.addComponent(actionsMenu);
....
return table;
}

c. Create a custom Data Utility.


If you can’t rely on a “menufor” action model for your table because you
need to calculate which action model to use dynamically, then you’ll need
to create a data utility for the actions column. You will need to extend
NmActionDataUtility and override the getDataValue() method. Set the
property DescriptorConstants.ActionProperties.ACTION_MODEL on the
component descriptor to the name of the action model you want to use:
public class CustomNmActionDataUtility extends NmActionDataUtility {

@Override
public Object getDataValue(String component_id, Object datum,
ModelContext mc) throws WTException {
String modelName = "foo";
if(...) {
modelName = "bar";
} else {
modelName = "baz";
}

mc.getDescriptor().setProperty( DescriptorConstants.
ActionProperties.ACTION_MODEL, modelName);
return super.getDataValue(component_id, datum, mc);
}
}
You can specify different action models for different types of datums (row
objects) or use other logic based on information in the model context to
determine the action model to use.

Adding Actions and Hooking Them Up in the UI 567


Note
If you don’t want to display any actions in the actions column you can
set the action model to EMPTY_ACTION_MODEL. When you do
that, the text “No Actions to Display” will appear in the actions
column.

After creating your data utility, add a column to the table in the builder.
Use a custom column id (i.e “customNmActions”) instead of
DescriptorConstants.ColumnIdentifiers.NM_ACTIONS:
public ComponentConfig buildComponentConfig (ComponentParams params) {
ComponentConfigFactory factory = getComponentConfigFactory ();
JcaTableConfig table = (JcaTableConfig) factory.newTableConfig ();

ColumnConfig actionsMenu = setComponentConfigFactory().


newColumnConfig(“customNmActions”, true);

....

table.addComponent(actionsMenu);
....
return table;
}

Finally, you’ll need to register your data utility for the custom column id in
an *.xconf entry, e.g:
<!-- Sample XCONF Entry -->
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.ptc.windchill.dataUtilities.
CustomNmActionDataUtility" requestor="java.lang.Object"
selector="customNmActions" cardinality="singleton"/></Service>

Trouble Shooting
Problem Solution
Description
Action Column does By default, the actions column is not displayed. Users are
not appear in Table not allowed to see it. Right-clicking a row is the only way
to see the row actions.
Icons for some To follow UI standards, the action service is designed to
actions are missing only show the icons in the actions menu if those icons
also appear in some toolbar anywhere in the system. If

568 Customization Guide


Problem Solution
Description
you need to workaround this for some action that doesn’t
belong in any toolbar, you could create a dummy model
with your action such as:
<model name=”toolbarModelNotUsedAnywhere”>
<action name=”myAction” type=”myActionType”/>
</model>
Then the action service will show the icon defined for that
action in the actions menu.

Adding Actions and Hooking Them Up in the UI 569


Problem Solution
Description
User right clicks and • Ensure “menufor” attribute is defined on the action
gets the following model (in the XML file) for your type: menufor=
error message: No ”your.type.Here”
Actions to Display
(Or you can define which model should be used in the
builder when you add the column to the table config)
• Add the NmActions column identifier to the table
config in the MVC builder:
public ComponentConfig buildComponentConfig
(ComponentParams params) {
ComponentConfigFactory factory
= getComponentConfigFactory ();
JcaTableConfig table =
(JcaTableConfig) factory.newTableConfig ();

table.addComponent (factory.newColumnConfig
(DescriptorConstants.ColumnIdentifiers.NM_ACTIONS
, true));
....

return table;
}

• Using fiddler/firebug, check what the oid parameter is


on the servlet/ActionsMenu request that is made when
you right click. If its not the oid you expected, or if
there is no oid at all, the infrastructure was not able to
make the correct NmOid from the backing objects
used for the table. See the NmObjectUtility
documentation for more details of how to control what
oid will be used for actions in the table.
• If you are defining the action model to be used for the
table/column (as described in Actions Column in a
Table on page 563). Using fiddler/firebug check what
the “actions” parameter is on the servlet/ActionsMenu
request made when you click to get the menu. Is the
“actions” param the model name you defined? If
actions=EMPTY_ACTION_MODEL it means the
action column is not defined in the current table view.
The actions column is required for the right click
menu to work. Try using the “View”->”Customize…”
option to add the actions column to the current table
view. Change the table builder to make the actions
column one of the default columns.

570 Customization Guide


Problem Solution
Description

Check the validators defined on the actions in the
model. Did all the actions get validated as hidden? If
that was the case, then adding jcaDebug=true as a
URL param should show the list of actions that were
hidden as disabled actions in the menu.
User right clicks and This message is ok if the user really does not have access
gets the following to the row object.
error message: You If the user should have access (for example they are able
do not have access to
to get to the information page and see the actions menu
this object or it does
not exist there) Then using fiddler/firebug, check what the oid
parameter is on the servlet/ActionsMenu request that is
made when you right click. If its not the oid you expected,
or if there is no oid at all, the infrastructure was not able
to make the correct NmOid from the backing objects used
for the table. See the NmObjectUtility documentation for
more details of how to control what oid will be used for
actions in the table.
Some actions don’t There may be a validator configured on it which may hide
appear in the list in the action in certain conditions. See Action Framework
the UI for Windchill Client Architecture on page 512 for
information on configuring an action with a validator.
Add jcaDebug=true to the url to see even the hidden
actions. With the jcaDebug option enabled, you’ll see
more information in the menu, and there will be an action
at the end of the list that takes you to the action model
report for that menu.

Wrong set of actions Add jcaDebug=true and check what vaildators are on the
is showing. actions in the menu. Check that the validators are working
as you’d expect.

Adding Actions and Hooking Them Up in the UI 571


Problem Solution
Description
1. If you expect the action model to be found by type
(described in Actions Column in a Table on page 563)
, is ‘menuFor’ defined on the action model for the
object type?
To see what the action service is finding for the type
of object in the row, turn on log4j logger :
com.ptc.netmarkets.util.misc.
StandardNmActionService
2. If the model to use is defined on the table/column
(described in Actions Column in a Table on page
563):
To see what action model the default data utility is
returning turn on log4j logger: com.ptc.core.
components.factory.dataUtilities.
NmActionDataUtility
The jcaDebug param will also produce a link to the
action model report at the bottom of the menu. The
action model report will have the model name, the set
of actions in that model, where the model is defined,
whether the model overrides any other models, etc.
Make sure the model is defined as you’d expect.
If you made a custom data utility for the column,
make sure the correct column is getting used. Set
jcaDebug=true on the URL and inspect the column
header DOM element to make sure the column id is as
you’d expect. Each column will have header text that
starts with the column id, for example the default
actions column would have header text like:
“nmActions validated by: …”.

Displaying Toolbar Actions for a Table


1. Define the actions in an actions.xml file. See Defining a New Action on page
515 for more information.
2. Add the actions to an action model . See Defining a New Action on page 515
for more information. Action models that used in the toolbar need to contain
“toolbar” in the name of the action model.
<model name="part toolbar actions">

572 Customization Guide


<action name="create" type="Part"/>
<action name="create" type="Document"/>

</model>

3. Add the action model to your table by calling the setActionModel(action_


model_name) in your MVC builder:
public ComponentConfig buildComponentConfig (ComponentParams params) {
ComponentConfigFactory factory = getComponentConfigFactory ();
JcaTableConfig table = (JcaTableConfig) factory.newTableConfig ();
// add the toolbar action model to the table
table.setActionModel (“part toolbar actions”);
....
return table;
}

Trouble Shooting
Problem Description Solution
Some actions don’t appear in There may be a validator configured on it which
the list in the UI may hide the action in certain conditions. See
Action Framework for Windchill Client
Architecture on page 512 for information on
configuring an action with a validator.
Add jcaDebug=true to the url to see even the
hidden actions. With the jcaDebug option
enabled, you’ll see more information in the
menu, and there will be an action at the end of
the list that takes you to the action model report
for that menu.

Displaying Menu Bar Actions for a Table


1. Define the actions in an actions.xml file. See Defining a New Action on page
515 for more information.
2. Add the actions to an action model. See Defining a New Action on page 515
for more information. Action models that are used in the menu bar need to

Adding Actions and Hooking Them Up in the UI 573


contain “menubar” in the name of the action model. To get a menu to fly out
from the main menu, add a submenu to the action model:

<!-- Menu Bar Action Model for the Folders table -->
<model name="folders table menubar">
<submodel name="folder file menu"/>
<submodel name="folder edit menu"/>

</model>

<!-- File Menu Action Model for the Folders table -->
<model name=" folder file menu">
<submodel name="submenu file new"/>
<action name="action1" type="folder"/>

</model>

<!-- Edit Menu Action Model for the Folders table -->
<model name=" folder edit menu">
<action name="copy" type="Object"/>
<action name="paste" type="Object"/>

</model>

574 Customization Guide


<!-- File -> New Menu Action Model for the Folders table -->
<model name=" submenu file new ">
<action name="create" type="part"/>
<action name="create" type="document"/>

</model>

3. Add the action model to your table by calling the


setMenubarName(action_model_name) in your MVC builder.
public ComponentConfig buildComponentConfig (ComponentParams params) {
ComponentConfigFactory factory = getComponentConfigFactory ();
JcaTableConfig table = (JcaTableConfig) factory.newTableConfig ();
// add the menu bar action model to the table
table.setMenubarName (“folders table menubar”);
....
return table;
}

Trouble Shooting
Problem Description Solution
Icons for some actions are missing Only the actions that are displayed in a
table toolbar have icons in the actions
menu.
Some actions don’t appear in the list in There may be a validator configured on
the UI it which may hide the action in certain
conditions. See Action Framework for
Windchill Client Architecture on page
512 for information on configuring an
action with a validator.
Add jcaDebug=true to the url to see
even the hidden actions. With the
jcaDebug option enabled, you’ll see
more information in the menu, and
there will be an action at the end of the
list that takes you to the action model
report for that menu.

Adding Actions and Hooking Them Up in the UI 575


Displaying Actions Menu on an Information Page
1. Define the actions in an actions.xml file. See Defining a New Action on page
515 for more information.
2. Add the actions to an action model. See Defining a New Action on page 515
for more information. When defining the action model, you will need to add
the attribute “menufor” for the object type that you are defining the actions for.
<model name="part actions" menufor="wt.part.WTPart">
<action name="view" type="object"/>
.....
</model>

To get a menu to fly out from the main menu, add a submenu to the action
model.

<model name="part actions" menufor="wt.part.WTPart">


<action name="action_1" type="object"/>
<submodel name="submenu_new"/>
</model>

<model name="submenu_new">
<action name="newViewVersion" type="part"/>

576 Customization Guide


</model>

3. If you don’t want to rely on the “menufor” action model, you can specify an
action model by calling setActionListName(action_model_name)
in your info page builder:
public InfoConfig buildInfoConfig(ComponentParams params) throws WTException {
InfoComponentConfigFactory factory = getComponentConfigFactory();
InfoConfig infoConfig = factory.newInfoConfig();

// override the “menufor” action model with a different Action Model


infoConfig.setActionListName("my type infopage actions");
....

return infoConfig;
}

Note
Your builder should extend DefaultInfoComponentBuilder or
AbstractInfoComponentBuilder.

Trouble Shooting
Problem Description Solution

Icons for some actions are missing Only the actions that are displayed in a
table toolbar have icons in the actions
menu.
Some actions don’t appear in the list in There may be a validator configured on
the UI it which may hide the action in certain
conditions. See Action Framework for
Windchill Client Architecture on page
512 for information on configuring an
action with a validator.
Add jcaDebug=true to the url to see
even the hidden actions. With the
jcaDebug option enabled, you’ll see
more information in the menu, and
there will be an action at the end of the
list that takes you to the action model
report for that menu.

Adding Actions and Hooking Them Up in the UI 577


Adding Custom Content to the Home
Page
Out of the box, the Home page comes with a small set of components available for
users and administrators to add to the page. You can pick from these thirteen
tables:
• Tasks,
• Updates
• Checked-Out Work
• Packages
• Workspaces
• Meetings
• Notebook
• Subscriptions
• Reports
• Saved Reports
• Data Monitors
• Discussions
• Actions
However, there is a customization point that allows you to put more components
into this list.

Intended Outcome
This documentation describes the process for adding a custom option to the
customize list on the Home page. This new item appears in the customize action
on the Home page and when selected its content renders in the page along with the
selected out of the box components.

578 Customization Guide


You can configure an action to add new content to the customize menu on the
Home page.

Prerequisite Knowledge
To achieve the intended result you need to have an understanding of the following:
• Action Framework for Windchill Client Architecture on page 512
• Defining Menus on page 562

Solution Elements
The default out of the box action model is:
<model name="home customization">
<description>Used for the customization options on the homepage</description>
<action name="listAssignments" type="work"/>
<action name="listUpdates" type="report"/>
<action name="listCheckedOutWork" type="user"/>
<action name="homeList" type="wp"/>
<action name="MyWorkspace" type="workspaces"/>
<action name="list_mine" type="meeting"/>
<action name="userNotebook" type="user"/>
<action name="listSubscriptions" type="subscription"/>
<action name="reports" type="user"/>
<action name="savedReports" type="user"/>
<action name="dataMonitors" type="user"/>

Adding Actions and Hooking Them Up in the UI 579


<action name="assignedClashesNav" type="clashReport"/>
<action name="participationView" type="forumTopic"/>
<action name="actionGroup" type="user"/>
</model>
File Description
codebase/actions/navigation- Location of the original home page
actionModels.xml customization menu action model
which will be copied.
codebase/actions/custom-actionmodels. Location for the customized copy of the
xml action menu which contains the added
component.
codebase/actions/ custom-actions.xml Location for the new action for the
added component.

Procedure – Adding Custom Content to the Home Page


1. Create a custom copy of the out of the box Home page action model.
Above is an example of what the Home page action model might look like on
your system. This action model is found in codebase/actions/
navigation-actionModels.xml.
From your system copy this model to the custom-actionmodels.xml
file. For more details on creating custom action model files and custom action
models see Action Framework for Windchill Client Architecture on page 512.
2. Create a new action for your custom component in codebase/actions/
custom-actions.xml.
For example, if your new component is defined in a jsp located in
codebase/netmarkets/jsp/myCompany/
customHomePageAction.jsp then you would define your action like
this.
<objecttype name="myCompany" class="org.rnd.myCompany">
<action name="customHomePageAction">
<label>Custom Component</label>
</action>
</objecttype>

Note
This is a simple example action that ignores localization.

580 Customization Guide


Note
There are many different types of actions that you can create beyond this
simple JSP example. For more details on creating custom action files and
custom actions see Action Framework for Windchill Client Architecture
on page 512.

3. Add the action to the custom copy of the home page action model in
custom-actionmodels.xml.
<model name="home customization">
<description>Used for the customization options on the homepage</description
<action name="listAssignments" type="work"/>
<action name="listUpdates" type="report"/>
<action name="listCheckedOutWork" type="user"/>
<action name="homeList" type="wp"/>
<action name="MyWorkspace" type="workspaces"/>
<action name="list_mine" type="meeting"/>
<action name="userNotebook" type="user"/>
<action name="listSubscriptions" type="subscription"/>
<action name="reports" type="user"/>
<action name="savedReports" type="user"/>
<action name="dataMonitors" type="user"/>
<action name="assignedClashesNav" type="clashReport"/>
<action name="participationView" type="forumTopic"/>
<action name="actionGroup" type="user"/>
<action name="customHomePageAction" type="myCompany"/>
</model>

Limitations
Only components for which an action can be created can be added to the Home
page. This is not very limiting as most things can be wrapped in a JSP.

Adding Actions and Hooking Them Up in the UI 581


15
Gathering the Data for the UI
Acquiring Data via Info*Engine ................................................................................. 584
NmObject Utilities.................................................................................................... 590
File Download ......................................................................................................... 596

This chapter describes how to gather data to be used in the user interface.

583
Acquiring Data via Info*Engine
Objective
You want to use an Info*Engine task to get the data for a Windchill Client
Architecture table component.

Background
The Windchill Client Architecture provides IeTaskInfo to be returned from its
ComponentDataBuilder for retrieving data using the Info*Engine task. Its
action maps to an Info*Engine task, which will be executed to get the data for the
component.

Intended Outcome
A Windchill Client Architecture table that has its data populated by an
Info*Engine task.

Solution
Return an IeTaskInfo from a Windchill Client Architecture table’s component
data builder.

Prerequisite Knowledge
Readers should be familiar with Info*Engine as well as with the basic Windchill
Client Architecture data acquisition concepts.

Solution Elements
Element Type Description
ComponentDataBuilder Java interface Creates the
data model for
the component
IeTaskInfo Java class Encapsulates
information
about the
Info*Engine
task and the
parameters that
can be passed
to the task

584 Customization Guide


Procedure – Implementing the Component Data Builder
Your ComponentDataBuilder should return a well populated IeTaskInfo
object. It takes the action name as the constructor which gives information of the
task that need to be executed to get the data For example, the following code
snippet demonstrates the use of the “jca-Search” task .
public class MyDataBuilderWithIETask implements ComponentDataBuilder {

@Override
public Object buildComponentData(ComponentConfig config,
ComponentParams params) throws WTException {

//pass the task name as constructor


IeTaskInfo taskInfo = new IeTaskInfo("jca-Search");
……..
return taskInfo;
}
}

You can provide parameters to the “Get-Model” webject using the


setParam(Param param) method on the IeTaskInfo. In addition if you
want to pass parameters to the underlying task using FORM group, can use
addFormParam(String name, Object data) method.

Configuring task selection


Internally, it uses Info*Engine’s Dispatch-Tasks webject to look up the task
implementation for the action task name that is provided in the IeTaskInfo.
Several parameters which are passed on to the Dispatch-Tasks are exposed,
using which it’s possible to choose the right implementation task.
Refer to “Dispatch-Tasks” in the “Management Webjects” section of the
Info*Engine User's Guide for more information on how these parameters work:
//pass the taskName as constructor
IeTaskInfo taskInfo = new IeTaskInfo("jca-Search");
//parameter passed on to the Dispatch-Tasks
taskInfo.setParam(new Param("GROUP_IN", "<groupInName>"));
taskInfo.setParam(new Param("TYPE", "<typeName>"));
taskInfo.setParam(new Param("CLIMBER", "<climberName>"));
return taskInfo;

Supplying form data to the task


By default, any request parameters in your JSP page will be supplied as part of the
form data to your task. So, if the page’s URL ends with something like
“/somePage.jsp?foo=bar”, then in your task implementation,
“@FORM[]foo[]” will map to “bar”.

Gathering the Data for the UI 585


If you want to explicitly configure the form data for your task, then you can do
this by creating the form group and then specifying the name of the group as
follows:
//pass the taskName as constructor
IeTaskInfo taskInfo = new IeTaskInfo("jca-Search");
//create your FORM group
Group groupIn = new Group("FORM");
taskInfo.setGroupIn(groupIn);
return taskInfo;

Using Information Supplied to the Task by the Windchill Client Architecture


Windchill Client Architecture supplies information to your task about the
attributes displayed by the requesting component and current table view (if the
component uses configurable tables). Your task can then use this information to
query for the right resulting data. The additional parameters supplied to your task
map to a subset of those accepted by the Query-Objects webject:
• ATTRIBUTE: This contains the list of attributes the component wants to
display
• SORTBY: What attributes to sort by
• SORTED: The sort direction for each attribute
• WHERE: Filter criteria
• TYPE: The type or types to search for.
• VERSION: Whether LATEST or ALL versions should be returned.
• ITERATION: Whether LATEST or ALL iterations should be returned
• ATTRIBUTE_TYPE_CONTEXT: When multiple types are supplied, the type
that should be used as a context to look up attribute definitions
• PAGE_LIMIT: The number of results per page (Not a customization point as
paging is not supported in Tables in Windchill Release 10.0)
• PAGE_OFFSET: The first result row to return from the paging session, if any
(Not a customization point as paging is not supported in Tables in Windchill
Release 10.0)
• PAGING_SESSION_ID: The current paging session id, if any
Most of these parameter names can be reconfigured to some other value using
setParam(Param param). See Customizations Points on page 587 for details.

586 Customization Guide


Customizations Points
Parameter Default Possible API Req? Descrip-
Value Values tion
action None Any valid Constructor Yes The name
task name of of the task
IeTaskInfo to execute
form The current Name of a setGroupIn No A group
request valid group (Group that
parameters in the page groupIn) contains
VDB form data
for the task

setParam(Param param) customization points


The following are all parameters that can be specified using setParam(Param
param)
Parameter Default Possible Req? Description
Value Values
GROUP_OUT output Any No The name of
the resulting
group
GROUP_IN None Any No The name of
the group in to
supply to
Dispatch-
Tasks
TYPE None Any No The name of
the type to
supply to
Dispatch-
Tasks
CLIMBER None Any No The name of
the climber to
supply to
Dispatch-
Tasks
ATTRIBUTE_ “ATTRIB- Any No The name of
PARAM_ UTE” the attribute to
NAME put the
requested
attribute list in
SORTBY_ “SORTBY” Any No The name of
PARAM_ the attribute to
NAME put the sort

Gathering the Data for the UI 587


Parameter Default Possible Req? Description
Value Values
criteria in
SORTED_ “SORTED” Any No The name of
PARAM_ the attribute to
NAME put the sort
direction
criteria in
WHERE_ “WHERE” Any No The name of
PARAM_ the attribute to
NAME put the filter
criteria in
TYPE_ “TYPE” Any No The name of
PARAM_ the attribute to
NAME put the type
criteria in
VERSION_ “VERSION” Any No The name of
PARAM_ the attribute to
NAME put the version
criterion in
ITERATION_ “ITERATION” Any No The name of
PARAM_ the attribute to
NAME put the
iteration
criterion in
ATTRIBUTE_ “ATTRIB- Any No The name of
TYPE_ UTE_TYPE_ the attribute to
CONTEXT_ CONTEXT” put the
PARAM_ attribute type
NAME context
criterion in
addFormParam(java.lang.String, java.lang.Object) can be
used to pass parameters using the FORM group, which can be readily accessed
from your task.

Limitations
None.

588 Customization Guide


Sample Code
Look for the builder examples available in carambola
• com.ptc.mvc.builders.carambola.table.MvcTableBuilderWithIETask
• com.ptc.mvc.builders.carambola.table.
DataSourceASyncTableBuilderWithIETask
• com.ptc.mvc.builders.carambola.table.
DataSourceSyncTableBuilderWithIETask

Examples of Usage in Windchill Code


Few Change tables.

Related Documentation
• Info*Engine User's Guide
• Windchill Adapter Guide (Info*Engine)

Gathering the Data for the UI 589


NmObject Utilities
The value of an attribute in an attribute panel or table/tree cell needs to be
extracted from a different object than the datum object for the panel or table/tree
row.
Problem: The object identifier used to identify a selected table/tree row or
construct the actions menu for a table/tree row cannot or should not be that of the
row datum object.

Background
Each attribute panel and each row in a JCA table or tree has a datum object from
which the data for the attribute or table cell values is extracted and the object
identifier for row actions and for row selections is obtained. The datum object is
provided by the buildComponent() method of a Java builder class or by a
getModel() or getIEModel() JSP tag. Datum objects are typically
Persistable objects or, in the case of create and edit wizards, TypeInstances
representing Persistable objects. However, other types of Java objects (for
example, a HashMap) can be used.

Retrieving Attribute Values from Datum Objects


JCA provides ways to configure how datum objects are processed by data utilities
to extract the attribute values that are displayed in the UI. Without additional
configuration, JCA handles datum objects in the same way that the JSP EL
handles Java beans, meaning that you can refer to a property name and the
infrastructure will look for a corresponding getter on your object. For example, if
you have described a table that has a column with the name “foo”, the
infrastructure will look for a "getFoo" method on the datum object. If the
method isn't found, the infrastructure does not fail but instead will simply return a
null value for the UI component to process in whatever way it chooses. By
default, the UI components just render a blank in this case.
You are not limited to simple properties of the datum object. In fact, anything you
can do with the JSP EL can also be accomplished with JCA. For example, you can
use the dot notation to refer to nested properties. In addition, JCA treats Map
objects as beans, so if your API returns a Map or has a nested Map property, you
can refer to it just as if it had getter methods. For complete information on what
you can specify in bean notation, refer to the documentation for beanutils, the core
package that JCA uses to process bean properties.
More examples:
• bar[0]: get the first value of the bar property. This works if bar maps to a
List or an Array.
• foo.bar: get the nested "bar" property of a "foo" property. If getFoo()
returns a Map, then this would correspond to getFoo().get("bar")

590 Customization Guide


In addition to bean-style properties, JCA is able to look up the values for global
attributes if the datum object is a Persistable or TypeInstance. Also, JCA
provides a number of data utilities that are able to create values for attribute ids
that are not properties of the datum object. Some of these do additional data
acquisition to find necessary information that does not exist in the datum object.

Retrieving Row Identifiers from Datum Objects


Without additional configuration, the JCA table and tree framework assumes that
each row object they are processing is a Windchill Persistable object whose object
identifier can uniquely identify the object when a row is selected or when a row-
level actions menu needs to be displayed.
The correct target object has been specified for the panel, table or tree.

Solution
When the value of an attribute should be extracted from an object other than the
datum object you can configure a different “target object” from which attribute
values should be obtained.
The target object will be passed as the “datum” to data utilities instead of the
datum object. Note that the specified target object must be addressable from the
datum object. See Procedure – Configure a different target object
In cases where the datum object for a table or tree is not a Persistable object
whose identifier can be used for table row actions or row selection you can
configure how the row object identifier should be obtained. In order of preference,
your options are:
• Procedure – Implement getOid() on your row data object
• Procedure – Configure a diferent target object

Prerequisite Knowledge
You need to have an understanding of the following:
• Windchill application context (“service.properties”)
• JCA Overview
• MVC Overview
• JCA NmObjects Overview
Related Information on page 595 includes references to many or all of these
subjects.

Gathering the Data for the UI 591


Definition of Terms
Term Definition
datum object The objects returned by the getComponentData method of the
panel, tree, or table builder class. For example, a Collection of
BinaryLinks.
row data Same as datum objects
target objects The objects that will be sent into the data utilities. By default,
the target objects are the same as the row data. This can be
overridden per column where necessary. (For instance, the
target objects could be BinaryLinks for the first column, role A
objects for second column, role B objects for the third column
etc.) Warning - If you use both for the table, make sure the
NmObjectUtility will look to see what the target object is so
that creates the right NmObject. This can effect whether the
Number column works for example.

Implement getOid() on your row data object


This procedure describes the preferred technique for specifying the identifier that
should be used for table/tree row selections and actions when the row object is not
a Persistable object. This technique is not applicable for specifying a target object
that is different from the datum object for determining attribute values.
To use this technique you should modify the row objects to expose an API called
getOid(), which should return a unique identifier for the row.
The getOid() method should return one the following data types:
• String – which will map to a NmSimpleOid if it’s not a valid WTReference
• ObjectIdentifier
• NmOid
If is not possible to provide a getOid() method — for example, if such an API
already exists and is not appropriate, you can specify a “target” object for the
panel or row. See Configure a Different Target Object on page 593 for more
information.

592 Customization Guide


Configure a Different Target Object
This procedure describes how to specify a target object for an attribute panel or a
row that is different than the datum object. The unique identifier for row
selections and actions will be obtained from the target object and the target object
is also what will be passed to the data utility that creates the value displayed for an
attribute. The target object must be obtainable from the datum object via a getter
method. For tables and trees, a target object can be specified for the entire table or
tree or for just certain columns. For panels, a target object can be specified for the
entire panel or just certain attributes.
The target object must be retrievable via a “getter” method on the datum object.
When you configure a different target object for a table or tree that has row
selection and/or row action menus, the target object should be one of the
following types so that a unique row identifier can be determined:
• Persistable
• WTReference
• ObjectIdentifeir
• NmObject
• NmOid
• NmSimpleOid
Use one of the following methods to set the target object:
• JCATableConfig.setTargetObject() to set the target object for an entire table or
tree
• JCAColumnConfig.setTargetObject() to set the target object for a specific
table or tree column
• AttributePanelConfig.setTargetObject() to set the target object for an entire
attribute panel
• AttributeConfig.setTargetObject() to set the target object for a single attribute
in a panel
If you set the target object for the whole panel or table, that target object will be
used for every attribute/column unless overridden by the AttributeConfig or
JCAColumnConfig. If a target object is specified for the entire panel or table
and you want to use the datum object for a specific attribute or column, you can
set the target object to “” on the attribute or column config.
For example:
JcaTableConfig table = (JcaTableConfig)factory.newTableConfig();
table.setTargetObject(“foo”);
ColumnConfig c = factory.newColumnConfig("name",label,false);

Gathering the Data for the UI 593


ColumnConfig col = factory.newColumnConfig("thing1",label,false);
col.setTargetObject("");
ColumnConfig col2 = factory.newColumnConfig("thing2",label,false);
col2.setTargetObject("bar");

In the above example, for each column the DefaultNmObjectDataUtility


will try to create an NmObject from the targetObject. For the name
column, the targetObject is retrieved by calling getFoo() on the row
datum because “foo” is the target object configured for the table and it has not
been overridden for the name column. For thing1, the targetObject is the
row datum because “” is configured. For thing2, the targetObject is
retrieved by calling getBar() on the row datum.

How is this different than configuring bean properties?


You may be wondering how this configuration of targetObject differs from a
configuration that uses bean-style property configuration. For example the
following configurations both end up displaying getFoo().getBaz() of the
row objects returned for your table:
ColumnConfig colA = factory.newColumnConfig("thing1",label,false);
colA.setTargetObject("foo");
colA.setNeed("baz");
ColumnConfig colB = factory.newColumnConfig("thing2",label,false);
colB.setTargetObject("");
colB.setNeed("foo.baz");
The small difference is that colA would use ‘foo’ as the target object sent into
the DefaultNmObjectUtility and the DataUtility for the row etc. And
colB would use the original row object.

594 Customization Guide


Limitations
The infrastructure will try to get a target object for every row even if you do not
need one. There is no way to tell the infrastructure not to do this.
If you do not have your table configured correctly you may see an error like
2011-02-24 16:42:10,883 TRACE [TP-Processor7]
com.ptc.core.components.factory.dataUtilities.DefaultN
mObjectUtility wcadmin - nmObject
2011-02-24 16:42:10,883 DEBUG [TP-Processor7]
com.ptc.core.components.factory.dataUtilities.DefaultN
mObjectUtility wcadmin - Exception occured trying to get an
oid property.
java.lang.NoSuchMethodException: Unknown property 'oid'
on class 'class
com.ptc.core.meta.type.common.impl.DefaultTypeInstance'
...
If the table does not have any row actions or row selection, this error can be
ignored. It is harmless. It is not important to have the right target object if there
are no actions. The error message can be ignored or removed by implementing a
getOid method on the row data. If the table has row selection and/or actions, use
the guidelines in this document to correct the configuration and get the right oid.

Related Information
• Windchill Client Architecture Overview on page 232
• Windchill Client Architecture Common Objects Overview on page 245
MVC Components on page 257

Gathering the Data for the UI 595


File Download
You want to export data, identified by a Windchill URL, to a file in the user’s file
system, without interrupting any active AJAX requests.
This information applies to any coding scenario that involves exporting
(downloading to the client) a word processing document, spreadsheet, compressed
archive, etc. See Limitations on page 601 for file types not suited for this
technique.

Scope/Applicability/Assumptions
You have one of the following:
• JavaScript code
• A JSP page or fragment
• A Java class that descends from DefaultObjectFormProcessor, or
another use of a FormResult object
The code needs to allow a user to download a file, identifiable by a URL, to the
user’s computer. The download must not interfere with any pending AJAX
transaction, and must run in the background without preempting the Windchill UI.
For example, you might have a wizard that guides a user to select a document, and
a class <MyWizardFormProcessor>.java to process the form on closure. The form
processor can return a FormResult with the next action set to
FormResultAction.JAVASCRIPT, that includes a JavaScript call to
download the selected file.

Intended Outcome
The user’s web browser will present its standard file-save dialog box:

596 Customization Guide


Solution
Call the JavaScript function PTC.util.downloadUrl(url) to initiate the
file download. See Customization Points on page 600 for information about the
url parameter.
You can call directly from JavaScript, within a <script> section in JSP, or by
returning a FormResult from Java with a next action type of
FormResultAction.JAVASCRIPT.

Prerequisite Knowledge
To achieve this result, you need to understand:
• Basic development of Windchill web pages
• JavaScript
• Web server configuration and content-disposition
• URL security best practices

Gathering the Data for the UI 597


Solution Elements
Element Type Description
main.js JavaScript This file includes the
JavaScript fragment util.
jsf, which defines the
PTC.util.downloa
dUrl(url) function. It
is located in
//codebase/
netmarkets/
javascript/util
<MyScript.js> JavaScript (whole or Code a call to
or <MyScriptPart.jsfrag> fragment) PTC.util.downloa
<MyPage.jsp> or JSP (whole or fragment) dUrl(url) directly in
<MyPagePart.jspf> JavaScript or inside a
<script> tag in JSP.

598 Customization Guide


Element Type Description
<MyWizardFormProces Java class Use a FormResult object
sor.java> to pass JavaScript to the
client for execution. The
general pattern is:
formResult.setSta
tus(FormProces
singStatus.SUC
CESS); // or prior
value
formResult.setJa
vascript(js); //
where js is a string of
JavaScript code
formResult.setNex
tAction(FormResul
tAction.JAVA
SCRIPT); The
JavaScript string should
include a call to
PTC.util.downloa
dUrl(url); it may
also contain other
necessary code. If
handling the OK button
click in a wizard, you
should run the download
in the opening window:
window.opener.PT
C.util.downloa
dUrl(theURL);
and close the wizard:
window.close();

Procedure – Downloading a Windchill URL


Because PTC.util.downloadURL(url) is a utility function that might be
used under many circumstances, no single procedure can anticipate them.
For Javascript and JSP, create or modify the code that needs to initiate the
download, calculate or look up the URL of the desired file, and call
PTC.util.downloadURL(url) where needed.

Gathering the Data for the UI 599


For server-side initiation in Java, see Packaged Samples on page 601.

URL Security
Your file download implementation must take security issues into account.
• Information about the server’s file structure should never be displayed to the
user. This includes URLs.
• Users should not be allowed to traverse the file structure of the server when
downloading a file.
• Users should not be allowed to change a parameter, such as filename, when
downloading a file.
• Users should never be allowed unauthorized access to any file through such
traversals or modifications.

Customization Points
Parame- Default Possible Values Re- Description
ter Value quired
url None • A full URL Yes The URL of the
(protocol:// file to be
credentials@ downloaded to the
server/path1/ client.
path2…)
• A root-relative
URL (/path1/
path2…)
• The current
Windchill root
(from
getBaseH
ref()) will be
prepended to the
parameter.
• A current location-
relative URL
(path1/
path2…)

600 Customization Guide


Limitations
This practice is limited to content types that web browsers cannot display. It
cannot be used for text, HTML, XML, or common image formats such as PNG,
JPEG, or GIF.
The downloadURL function works by setting the source of a hidden <iframe>
to the specified URL. The browser will render text, HTML, images, etc. in the
<iframe>, rather than initiating a download.

Packaged Samples
There is an example that illustrates use of the downloadURL function in a
wizard. If you have the Client Customization utility enabled navigate to Navigator
▶ Customization ▶ Test Clients ▶ Download File Example to see the example.
The Client Customization utility is not enabled by default. See Enable
Customization Utilities on page 404 for instructions on how to enable the utility.

Gathering the Data for the UI 601


16
Presenting Information in the UI
Dynamically Resolved Attributes for Customizations .................................................. 604
Constructing and Rendering a Table Using the JSP Framework .................................. 606
Windchill Client Architecture Tree ............................................................................. 642
Attribute Customization............................................................................................ 658
Adding Custom Modeled Attributes to all Table Views................................................. 736
Attribute Tables ....................................................................................................... 737
Icon Delegates ........................................................................................................ 742
Creating Custom Graphical Representations ............................................................. 749
UI Validation............................................................................................................ 770
URL Authorization ................................................................................................... 823
Customizing the Find Number Field .......................................................................... 826
Inline Messaging ..................................................................................................... 832

This chapter describes how to customize information that is displayed in the user
interface.

603
Dynamically Resolved Attributes for
Customizations
The following dynamically resolved attributes are provided by PTC, and can be
used in customizations to return a specific set of attributes that are resolved at
runtime. The values returned for the following attributes will be instances of
AttribtueTypeIdentifierSet. The values represent the collection of
AttributeTypeIdentifiers associated with that attribute. In addition, values for each
of the attributes that is a member of the set will also be returned in the retrieved
TypeInstance.
Attribute Description
ALL_SOFT_ATTRIBUTES Returns a list of all reusable attributes
associated with the retrieved object as well
as values for all of those attributes.
ALL_SOFT_CLASSIFICATION_ Returns a list of all global attributes
ATTRIBUTES associated with the classification(s) of the
retrieved object as well as values for all of
those attributes.
ALL_SOFT_NON_SCHEMA_ Returns a list of all reusable attributes
ATTRIBUTES associated with the retrieved object which
are NOT global attribute on the type of the
retrieved object as well as values for all of
those attributes.
ALL_SOFT_SCHEMA_ Returns a list of all global attributes
ATTRIBUTES associated with the type of the retrieved
object as well as values for all of those
attributes.
ALL_SOFT_SCHEMA_ Returns a list of all global attributes
ATTRIBUTES_FOR_INPUT_ associated with the type indicated by the
TYPE context of the constructed
AttributeTypeIdentifier as well as values for
all of those attributes.
ALL_SOFT_NON_ Returns a list of all reusable attributes
CLASSIFICATION_ associated with the retrieved object which
ATTRIBUTES are NOT global attributes associated with
the classification(s) of the object, as well as
the values for those attributes.

604 Customization Guide


Example
TypeIdentifier type_x = ...;
AttributeTypeIdentifier ati = (AttributeTypeIdentifier)
IDENTIFIER_FACTORY.get("ALL_SOFT_SCHEMA_ATTRIBUTES_FOR_INPUT_TYPE"
,type_x);
If 'ati' is requested to be returned when a TypeInstance is retrieved, it will return a
list of only the attributes associated with type_x, regardless of the actual type of
the retrieved object.
This attribute is typically used for tables of objects which may or may not be of
the same type, but all have a common supertype which defines the appropriate
columns to display.
Attribute Description
ALL_SOFT_NON_ Returns a list of all global attributes
CLASSIFICATION_SCHEMA_ associated with the type of the retrieved
ATTRIBUTES object which are NOT associated with
the classification(s) of the retrieved
object as well as values for all of those
attributes.
ALL_CUSTOM_HARD_ Returns a list of all custom hard
ATTRIBUTES_FOR_INPUT_TYPE attributes associated with the type
indicated by the context of the
constructed AttributeTypeIdentifier as
well as values for all of those attributes.
'Custom' hard attributes are defined to
be all modeled attributes which are not
inherited from classes in the 'wt' or
'com.ptc' packages.

Presenting Information in the UI 605


Constructing and Rendering a Table
Using the JSP Framework
Objective
You want to present the information in a tabular format and optionally execute
actions on the presented data.

Background
The table common component presents information in a tabular format to help
users scan, locate, compare, and take actions on related data. Users may control
how to view data in the table using sorting and views.
The following tables details the specific elements within a table.
Element Description
Title Bar The title bar area tells users what information is displayed in
the table. The table title bar is located at the top of the table
and may contain: a table title, an object count, the Current
View pulldown list, and several action icons - Help etc.
Menu Bar Tables with many actions will display a menu bar. Each menu
title provides a pulldown list of actions.
Shortcut Tool The shortcut tool bar displays a subset of actions from the
Bar menu bar. These are actions that are frequently used. The
shortcut tool bar may be used without the menu bar when a
table contains few actions.
Column Header/ Sorting allows the user to control the presentation of table
Sorting data.
Selection The checkbox column allows users to select and deselect
objects within the table that they wish to perform an action
upon. A user can also select the rows across the multiple
pages and perform the desired actions on the same.
Status Glyph The status glyph column(s) convey status and messaging
Columns information about individual objects in the table.
Object Icon The object icon column displays the appropriate icon for that
Column object.
Action Column The action columns in the content area of a table contain the
(s) row-level actions for specific objects in a table.

606 Customization Guide


Element Description
Data Rows The data rows of a table contain attributes for a given object
in the table. This section covers table scroll bars.
Footer The table footer is located at the bottom of the table. It
provides visual closure to the table and contains the paging
and View All functionality, if used.

Scope/Applicability/Assumptions
Table common component should be used when there is a requirement to display
Windchill business objects in tabular form and not just for displaying the HTML
Table.

Intended Outcome
Depending upon the configuration, Table can be displayed in different formats.
Following is a general layout of a Table:

Solution
Implement MVC table builders to create or convert a JCA table component.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following JCA
techniques:
• Data utilities
• GUI component
• Actions framework

Presenting Information in the UI 607


• Configurable table views
• Java annotations

Solution Elements
Element Type Description
ComponentData- Java interface Creates the data model for the
Builder component
ComponentConfig- Java interface Creates the configuration for the
Builder component
ConfigurableTable- Java interface Creates the configurable table views
Builder for tables and trees
AbstractConfigura- Java class Base class that builders typically
bleTableBuilder extend
ComponentConfig Java interface Base interface for component
configurations
ComponentConfig- Java interface Creates ComponentConfig
Factory implementations
ComponentBuilder Java annotation Configures the component id used to
look up a component builder

Procedure – Configuring Table Common Component

Creating a new Builder class


A table builder class corresponds to a table configuration. All the table-level as
well as column-level properties should be configured in the builder class. When
creating a new builder class, you should typically extend one of the abstract base
classes provided by the MVC infrastructure:
• AbstractConfigurableTableBuilder
Use this base class if you are implementating a tree or table that supports
configurable table views. This base class is located in the CoreHtmlComp
module due to its dependency on the configurable table infrastructure.
• AbstractComponentBuilder
Use this base class for tables and trees that do not support configurable tables
• AbstractComponentConfigBuilder
Use this base class for info pages. You can also use this if you wish to separate
your table or tree config builder from its data builder (not a typical use case).
• AbstractComponentDataBuilder

608 Customization Guide


Use this base class for table and tree implementations where you have chosen
to separate the config and data builder implementations (not a typical use
case).

Implementing the ComponentConfigBuilder API


The table and column level configuration options can be specified by
implementing ComponentConfigBuilder. ComponentConfigBuilder currently
defines one method:
ComponentConfig buildComponentConfig(ComponentParams params);
The responsibility of this method roughly corresponds to what the describeTable
tag does in 9.x versions.

The ComponentConfig hierarchy:

Using ComponentConfigFactory to get Table/column


ComponentConfig objects
It is not necessary to create a ComponentConfig directly, instead use a
ComponentConfigFactory. When extending the abstract base builder classes, the
factory is available by calling getComponentConfigFactory(). When directly
implementing ComponentConfigBuilder, also implement
ComponentConfigFactoryAware. This will get you a reference to the factory when
the builder is initialized.
Instance of TableConfig and ColumnConfig need to be used to specify table level
and columns level customizations respectively. An example to get the
TableConfig/ColumnConfig instance look like this:
ComponentConfigFactory factory = getComponentConfigFactory();

Presenting Information in the UI 609


TableConfig table = factory.newTableConfig();

ColumnConfig col1 = factory.newColumnConfig(“column1Id”, false);

table.addComponent(col1);

Since column component is a nested component of table component,


ColumnConfig can be added to the TableConfig using the addComponent() API as
shown in above code snippet.

Setting properties on TableConfig and ColumnConfig:


Customization points available for the config classes are described in
Customization Points on page 614. Refer to the JavaDoc for more details on the
properties and capabilities of each config class.

Localizing your configs


To localize values within your config builder, the Mvc infrastructure provides a
new ClientMessageSource class. If you are extending one of the abstract
configuration base classes, then you can call getMessageSource(String) to create a
message source for a given resource bundle class name. ClientMessageSource
works like WTMessage, but ensures that the locale that you use is the client
locale, rather than the locale that the server is running with.

Specifying the view JSP

Implementing the ComponentDataBuilder API


The data acquisition mechanism for table can be configured using
ComponentDataBuilder interface. The data builder class needs to implement
ComponentDataBuilder interface. ComponentDataBuilder currently defines one
method:
Object buildComponentData(ComponentConfig config, ComponentParams params)

The responsibility of this method roughly corresponds to what the getModel/


getIeModel tag do in JCA in the 9.x release stream.

Registering your ConfigurableTable


If your ComponentConfigBuilder implementation also implements
ConfigurableTableBuilder, then you do not need to register your
ConfigurableTable implementation in service.properties. You cannot register
ConfigurableTableBuilder implementations themselves, independent from a
ComponentConfigBuilder implementation.

610 Customization Guide


Implementing your ConfigurableTable
You may choose to implement your ConfigurableTable as a static inner class of
your builder, or to put it in a separate file. If you only intend to use it from within
the builder implementation, then we recommend defining it as a private static
inner class. An example:
public class MyTableBuilder extends AbstractConfigurableTableBuilder {

@Override
public ConfigurableTable buildConfigurableTable(String tableId) throws WTException {
return new MyConfigurableTable();
}

private static class MyConfigurableTable extends JCAConfigurableTable {



}

}

Configuring separate config and data builders


If you wish to implement your config and data builders in separate classes, then
you must supply an additional ComponentBuilderType parameter to the
@ComponentBuilder annotation.
For config builders, this looks like:
@ComponentBuilder(value=“my.component.id”,
type=ComponentBuilderType.CONFIG)
public class MyConfigBuilder implements ComponentConfigBuilder…

For data builders, this looks like:


@ComponentBuilder(value=“my.component.id”,
type=ComponentBuilderType.DATA)
public class MyDataBuilder implements ComponentDataBuilder…

If you wish to configure separate builders without using annotations, then the bean
ids you choose must have the “.configBuilder” or “.dataBuilder” suffix. For
example to configure a config builder, you would do the following:
<bean name=”myComponent.configBuilder”
class=”my.config.builder.class.name”/>

Registering MVC builders


MVC builders can be registered using ComponentBuilder annotation or via
explicit configuration, or by automated scanning. Automated scanning. After
registering the table builders, the table component can be configured into the
application in actions.xml just as JSP-based JCA components.

Presenting Information in the UI 611


See MVC Components on page 257 and Constructing and Rendering a Table
Using the JSP Framework on page 606 for more information on registering/
configuring the table component.

Converting an Existing Table Implementation to MVC

Overview
This section describes the mapping of attributes from the 9.x legacy tags to the
corresponding attributes on the new MVC table builders.

describeTable
The content of the describeTable tag is now specified in the
buildComponentConfig method of ComponentConfigBuilder interface
JSP code was like this:
<jca:describeTable var="tableDescriptor" id="netmarkets_project_list"
configurable="true"
type="wt.projmgmt.admin.Project2" label="${projectListLabel}">

MVC code will look like this:


@ComponentBuilder(“netmarkets_project_list”)
public class ProjectListBuilder extends AbstractConfigurableTableBuilder {

@Override
public ComponentConfig buildComponentConfig(ComponentParams params) {
ComponentConfigFacory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
table.setLabel(ClientMessage.get(RESOURCE,"PROJECT_LIST_NAME");
table.setType("wt.projmgmt.admin.Project2");

return table;
}

describeColumn
The content of the describeColumn tag is also specified in the
buildComponentConfig method of ComponentConfigBuilder interface. As the
column component is an child component of the table component, it is added to
the table config.
JSP code was like this:
<describeTable var="tableDescriptor" type="wt.part.WTPart"
id=" test.table" label="testTable" >
<describeColumn id="name" sortable=”true”/>
<describeColumn id="number"/>
</describeTable>

612 Customization Guide


MVC code will look like this:
TableConfig table = factory.newTableConfig();

table.addComponent(factory.newColumnConfig(“name”,true));
table.addComponent(factory.newColumnConfig(“number”,false));

renderTable
The content of the renderTable tag is also specified in the buildComponentConfig
method of ComponentConfigBuilder interface.
JSP code was like this:
<jca:renderTable showCustomViewLink="false" model="${tableModel}" showCount="true"
showPagingLinks="true" />

MVC code will look like this:


TableConfig table = factory.newTableConfig();

table.setShowCount(true);
table.setShowCustomViewLink(false);

getModel
The content of the getModel tag is specified in the buildComponentData method
of ComponentDataBuilder interface.
JSP code was like this:
<jca:getModel var="tableModel" descriptor="${tableDescriptor}"
serviceName="com.ptc.netmarkets.projmgmt.ProjectCommands"
methodName="getProjects" ……. >
<jca:addServiceArgument value="${user}" type="wt.org.WTUser"/>
<jca:addServiceArgument value="${pseudoType}" type="java.lang.Integer"/>
</jca:getModel>

MVC code will look like this:


@Override
public QueryResult buildComponentData(ComponentConfig config,
ComponentParams params) {
WTPrincipal user = SessionHelper.getPrincipal();
return ProjectCommands.getProjects(user,0)
}

Presenting Information in the UI 613


Customization Points
JcaTableConfig class APIs can be explored for various table level customization
points. JcaColumnConfig class APIs can be explored for various table column
level customization points.

Configuring a custom view jsp for table component


The MVC infrastructure provides default JSPs for tables and trees. In most cases
you should not need to override the default view. If you need to render your table
model in a custom way, you can set a view path on your table or tree config object
to do this. Note that the view path must be relative to WEB-INF/jsp, to ensure that
the JSP is only accessed by MVC builders, rather than being directly accessible to
clients. This means you JSP must be checked in to a subfolder of <ModuleRoot>/
src_web/WEB-INF/jsp/<ModuleDirectory>/aCustomView.jsp
In table builder class:
TableConfig table = factory.newTableConfig ();

table.setView("/myModule/aCustomView.jsp");

The custom view jsp (/WEB-INF/jsp/<ModuleDirectory>/


aCustomView.jsp) will look something like this:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>

… /* custom code here */

<mvc:table/>

…/* custom code here */

614 Customization Guide


Reuse of a Table Builder Class
An API defined in one builder could be reused while writing a new builder. In
general, it is preferable to keep the needed builder as an instance field of the table
implementation, rather than extending the other builder. This follows the general
rule of thumb of favoring composition over inheritance. If reuse of a a config
builder is intended, it should be ensured to set the component config factory on it.
An example:
@ComponentBuilder("my.builder")
public class MyBuilder extends AbstractComponentBuilder {

private final OtherBuilder otherBuilder = new OtherBuilder ();

@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException{

}

@Override
public void setComponentConfigFactory(ComponentConfigFactory
configFactory) {
super.setComponentConfigFactory(configFactory);
otherBuilder.setComponentConfigFactory(configFactory);
}
}

Setting Sortable Columns


Sorting Behavior
• Table is sorted at client side in following scenarios:
1. It is an asynchronous datasource enabled table and application team has
not specified ‘preSorted’ property in result processor from builder to true.
2. If user explicitly changes the sort criteria and user revisits the table. (Sort
stickiness).
• Table is not sorted at client side in following scenarios:
1. If the application team set ‘preSorted’ property to true on the result
processor of table builder.
2. In case of synchronous datasource enabled table.
• During client side sorting, when the data chunk come to the client, they are
added to the store as per the client sort criteria.

Presenting Information in the UI 615


• If the user clicks sort while the data is loading, the data gets sorted at client
side. Also the data chunks that come later are also added in sorted order.
• Multi-column sorting: Multiclick to sort feature allows the user to sort
multiple columns at a time there by pressing the shift key and then sorting.
The limitation is maximum three columns are allowed to sort at a time.
• In case of sorting on version column, sorting happens at server side.

Setting Default Sort


A table column can be as a default sort column by using setDefaultSort(true) for
the column. For setting the direction setAscending() can be provided with value
‘true’ for ascending sort and ‘false’ for descending sort.
ColumnConfig col = factory.newColumnConfig(“name”, true);
col.setDefaultSort(true);
col.setAscending(false);
Configuring the column as above in table builder will cause a table to be displayed
as:

Configuring Strikethrough Feature


JCA Table component has ability to "redline" individual rows.

616 Customization Guide


The following configuration points are available for specifying which row(s) will
be struckthrough.

Configuring strikethrough on a hidden column


Add dataStoreOnly column with id "strikeThroughRow". Provide need attribute
for boolean column.
An example:
ColumnConfig strikeThroughColumn = factory.newColumnConfig("strikeThroughRow",
false);
strikeThroughColumn.setDataStoreOnly(true);
strikeThroughColumn.setNeed("someColumnId");

Configuring strikethrough on a row value


A new datautility that extends AbstractBooleanValueDataUtility should be defined
for the column.
The only abstract method getBooleanAttributeValue() should be defined to return
a Boolean. Custom code can be written to determine the returning Boolean. The
Boolean will decide if the row should be strikethroughed or not.
An example:
Column defined in builder to be added to JcaTableConfig:
ColumnConfig col = factory.newColumnConfig("myCol", false);

Corresponding mapping of the datautility for the column:


<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.ptc.windchill.enterprise.myModule.dataUtilities
.MyStrikeThroughRowDataUtility" requestor="java.lang.Object"
selector="myCol" cardinality="duplicate"/>
</Service>

Presenting Information in the UI 617


New datautility class:
public class MyStrikeThroughRowDataUtility extends
AbstractBooleanValueDataUtility {
public boolean getBooleanAttributeValue (String component_id, Object datum,
ModelContext mc) throws WTException {
/* some logic to return Boolean value*/
}
}

Configuring already present Boolean column as a strikethrough


column
The Boolean value column can be set as the strikethrough column in the table
builder. So the value of this column can be used to determine if the row will be
strikethrough.
An example:
TableConfig tableconfig = factory.newTableConfig(‘myTable’);
ColumnConfig aBooleanColumn = factory.newColumnConfig("aBooleanColumn", false);
Tableconfig.setRowStrikeThroughColumn(aBooleanColumn);

Configuring Search in List


By default the Search In List feature is enabled for the table. A user can enter text
and hit Enter or Search In List icon to execute the search. After applying the
search in list filter, the table will be displayed with the records matching with the
text entered. Only the values in the visible columns will be searched. The Search
in List filter will be sticky across component/page refreshes.
The Search in List table filter and View Selected Objects Only table filter interact
as follows:
1. Selected and disabled rows stay checked/disabled when the Search in Table
filter is applied. This is only allowed if the table in question is complete (the
data source is no longer running) and it only has one page of data. For tables
that are still populating or that have more than one page of data, the user is
warned that selections will be lost when applying the search filter.
2. Only one filter is allowed to be applied to the table at a time. The user can
apply either the Search in Table filter, OR the View Selected Objects Only
filter. But not both at once. When the user chooses one filter when the other is
on, they are prompted to that the original filter will be cleared as well.

618 Customization Guide


Disabling Search In List feature
Search in list can be disabled from a table by setting “false” in
setFindInTableEnabled.
TableConfig tableconfig = factory.newTableConfig('myTable');
tableConfig.setFindInTableEnabled(false);

Search In List modes


There are multiple modes available for Search in List. The Search in list mode can
be set using setFindInTableMode() method.
The search in list modes available are:
1. FindInTableMode.CLIENT_AND_SERVER(default mode): Perform the
search in table on the client or server data.
2. FindInTableMode.CLIENT_ONLY: Perform search in table on the client data
only.
3. FindInTableMode.DISABLED: Search in list panel is not displayed.

Configuring Non-Selectable Rows


Non selectable row based on an existing visible column
Non-selectable rows can be set depending upon a column that has a Boolean
value.
An example:
TableConfig table = factory.newTableConfig ();

//a column that is suppose to hold a boolean
ColumnConfig col1= factory.newColumnConfig (“aBooleanColumn”, false);

table.setNonSelectableColumn (col1);

Presenting Information in the UI 619


Configuring Non selectable rows based on a boolean attribute value
available in the backing object
The data utility com.ptc.core.components.factory.dataUtilities.
DefaultBooleanValueDataUtility is provided out of the box for configuring non
selectable rows. This data utility is mapped to column id “com.ptc.core.
components.descriptor.DescriptorConstants.ColumnIdentifiers.NON_
SELECTABLE_COLUMN”. There are two ways to set this data utility for a
column in a table:
• Use NON_SELECTABLE_COL as the column id
Create a column with an Id as “com.ptc.core.components.descriptor.
DescriptorConstants.ColumnIdentifiers.NON_SELECTABLE_COLUMN”.
Set the attribute as the need.
An example:
TableConfig table = factory.newTableConfig ();
ColumnConfig col = factory.newColumnConfig (NON_SELECTABLE_COLUMN, false);
col.setNeed (<Attribute>); // Specify the attribute which will decide the row is
selectable or not.
col.setDataStoreOnly (true); // this will make your Column hidden
table.addComponent (col);
table.setNonSelectableColumn (col);

• Setting datautility id to NON_SELECTABLE_COLUMN


Create a column with any Id, set the attribute as the need and set the
Datautility Id as “com.ptc.core.components.descriptor.DescriptorConstants.
ColumnIdentifiers.NON_SELECTABLE_COLUMN”.
An example:
TableConfig table = factory.newTableConfig ();
ColumnConfig col = factory.newColumnConfig(<columnId>, false);
col.setNeed (<Attribute>); // Specify the attribute which will decide the row is
selectable or not.
((JcaColumnConfig)col)setDataUtilityId (NON_SELECTABLE_COLUMN);
col.setDataStoreOnly (true); // this will make your Column hidden
table.addComponent (col);
table.setNonSelectableColumn (col);

Non selectable row based on a custom data utility


Create and register a custom data utility for the column to be used as a non-
selectable column.
• Create a custom data utility

620 Customization Guide


A custom data utility for controlling non selectable rows should extend “com.
ptc.core.components.factory.dataUtilities.AbstractBooleanValueDataUtility”.
The method getBooleanAttributeValue() method can be overridden with
custom logic:
An example:
package com.customPkg;
import com.ptc.core.components.factory.dataUtilities.
AbstractBooleanValueDataUtility;

public class TestCustomDataUtility extends AbstractNonSelectableRowDataUtility {

public boolean getBooleanAttributeValue (String component_id, Object datum,


ModelContext mc) throws
WTException {
/* this method will return true if the row is not selectable */
}
}

• Register the custom data utility:


Configure the newly created data utility against the column id:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.customPkg.TestCustomDataUtility "
requestor="java.lang.Object" selector="col1” cardinality="duplicate"/>
</Service>

Non-selected rows are displayed as follows:

Presenting Information in the UI 621


Configuring Data Store Only Column
Setting a column as data store only would make the column value available in data
store, but the column will not be displayed in the table.
For example:
TableConfig table = new TableConfig('testTable');
ColumnConfig dataStoreOnlyColumn = factory.newColumnConfig
("dataStoreOnlyColumn", false);
dataStoreOnlyColumn.setDataStoreOnly(true);
table.addComponent(dataStoreOnlyColumn);

Configuring Column as a Hidden Column


A column can be set as hidden so that it is not displayed on the table. However,
hidden column is available in the column list and thereby can be made un-hidden.
For example:
TableConfig table = new TableConfig("testTable");
ColumnConfig stateColumn = factory.newColumnConfig("state", true);
stateColumn.setHidden(true);
table.addComponent(stateColumn);

Adding a Toolbar
In order to add a toolbar, the key attribute must be set to “actionModel” and the
value attribute must be set to the name of the action model that contains the
toolbar actions.

622 Customization Guide


For example:
TableConfig table = factory.newTableConfig();
table.setActionModel("customToolbar");

This example uses a toolbar named “customToolbar” that contains pre-existing


folder actions.
If the table uses a new action model for the toolbar, it must be registered in the
actionModels.xml file.
<model name="CustomToolbar">
<action name="list_cut" type="object"/>
<action name="list_copy" type="object"/>
<action name="fbpaste" type="object"/>
<action name="list_delete" type="object"/>
<action name="separator" type="separator"/>
<action name="create" type="folder" shortcut="true" />
</model>

Configuring above action will produce an toolbar action model displayed as:

The *actions.xml and *actionModels.xml files can be modularized with logical


packaging. These files are located in <Windchill>/codebase/config/actions. There
is also a custom-actions.xml and custom-actionModels.xml file available to
register new actions and action models. The “customToolbar” action model is
registered in the custom-actionModels.xml file.
If the user selects few records and does a right click on the selected records, table
toolbar action model shall be displayed. But note, only the actions having
attributes selectRequired=”true” and multiSelect=”true” shall be displayed.

Configuring the Menubar


Menubar can be set for the table using setMenubarName() in table builder.

Presenting Information in the UI 623


For example:
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
table.setMenubarName("customMenubar");

This example uses an action model named “customMenubar”.


The action model must also be registered in the *action-models.xml file. Action
models can be nested using the submodel tag.
<model name="customMenubar">
<submodel name="fileMenu"/>
<submodel name="editMenu"/>
</model>
<model name="fileMenu">
<action name="list_cut" type="object"/>
<action name="list_copy" type="object"/>
<action name="fbpaste" type="object"/>
<action name="list_delete" type="object"/>
</model>
<model name="editMenu">
<action name="create" type="folder"/>
</model>

In order to label each menu, the description must be set for the File and Edit
submodels
The action properties must be included in either the action.properties file or in a
resource bundle
The properties depicted below are the entries that get added to the action.
properties file
The entries for the File and Edit actionModels would look like:
object.fileMenu.description.value=File
object.editMenu.description.value=Edit

624 Customization Guide


Adding the menu bar will produce the following results:

Configuring Table — Enabling a Row Selection


Making the rows selectable can be done by using setSelectable() on table config.
To make the table non-selectable the value must be set to “false”. By default, table
is selectable.
For example:
For setting non-selectable table.
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
table.setSelectable(false);

Configuring Single Select Table


We can have the single select facility to the table. This restricts the user to select
only one record at a time from the table. This can be done by setting the
singleSelect property on the table. A “true” value will present the table in a single
select (radio buttons) mode whereas a “false” value presents it in a multi select
(checkboxes) mode.
For example:
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
Table.setSingleSelect(true);

Presenting Information in the UI 625


Configuring non- Pre-Selection rows

Pre-Selection row depends on an existing visible column


Pre-selectable rows can be set depending upon a column that has a Boolean value.
The column should return a GUIComponent that has comparable value “true”/
”false”.
An example:
TableConfig table = factory.newTableConfig ();

//a column that is suppose to hold a boolean
ColumnConfig colX = factory.newColumnConfig(<columnId>, false);
table.setPreSelectableColumn(colX);

Configuring Pre selectable rows based on a boolean attribute value


available in the backing object
The com.ptc.core.components.factory.dataUtilities.
DefaultBooleanValueDataUtility is out of box datautility provided for this case.
This will simply return the value of the given column. There are two ways to set
this data utility for a column in a table:

Use PRE_SELECTABLE_COL as the column Id


Create a column with an Id as “com.ptc.core.components.descriptor.
DescriptorConstants.ColumnIdentifiers.PRE_SELECTABLE_COLUMN”
(against this the dataUtility has been registered) and set the attribute as the need.”.
An example:
TableConfig table = factory.newTableConfig ();

626 Customization Guide


---------
ColumnConfig col = factory.newColumnConfig (PRE_SELECTABLE_COLUMN, false);
col.setNeed (<Attribute>); // Specify the attribute which will decide the row i
pre-selectable or not.
col.setDataStoreOnly (true);// this will make your column available on store on
table.addComponent (col);
table.setPreSelectableColumn (col);

Setting datautility Id to PRE_SELECTABLE_COLUMN


Create a column with any Id, set the attribute as the need and set the Datautility Id
as “com.ptc.core.components.descriptor.DescriptorConstants.ColumnIdentifiers.
PRE_SELECTABLE_COLUMN”..
An example:
TableConfig table = factory.newTableConfig ();
--------
ColumnConfig col = factory.newColumnConfig(<columnId>, false);
col.setNeed (<Attribute>);
// Specify the attribute which will decide the row
is selectable or not.
((JcaColumnConfig)col)setDataUtilityId (PRE_SELECTABLE_COLUMN);
col.setDataStoreOnly (true); // this will make your Column hidden
table.addComponent (col);
table.setPreSelectableColumn (col);

Pre selectable rows based on a custom data utility


Create and register a custom data utility for the column to be used as a pre-
selectable column.

Create a custom data utility


Create your own DataUtility by extending “com.ptc.core.components.factory.
dataUtilities.AbstractBooleanValueDataUtility”.
Override getBooleanAttributeValue () method.
An example:
package com.customPkg;
import com.ptc.core.components.factory.dataUtilities.
AbstractBooleanValueDataUtility;
public class TestCustomDataUtility extends
AbstractBooleanValueDataUtility {
public boolean getBooleanAttributeValue(String
component_id, Object datum,
ModelContext mc) throws
WTException {
/* this method will return true if the row is pre selectable */
}
}

Presenting Information in the UI 627


Register the custom data utility
1. Configure the newly created data utility against the column id:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.customPkg.TestCustomDataUtility "
requestor="java.lang.Object" selector="col1” cardinality="duplicate"/>
</Service>
TableConfig table = factory.newTableConfig ();
--------
ColumnConfig col = factory.newColumnConfig(<'''columnId'''>, false);
col.setNeed (<Attribute>); // Specify the attribute which will decide the
row is pre selectable or not.
col.setDataStoreOnly (true); // this will make your Column hidden
table.addComponent (col);
table.setPreSelectableColumn (col);
2. Configure the newly created data utility against the Selector id:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="<DataUtility>" requestor="java.lang.Object"
selector="<selectorId>” cardinality="duplicate"/>
</Service>
TableConfig table = factory.newTableConfig ();
--------
ColumnConfig col = factory.newColumnConfig(<columnId>, false);
col.setNeed (<Attribute>); // Specify the attribute which will decide
the row is selectable or not.
((JcaColumnConfig)col) setDataUtilityId (<selectorId>);
col.setDataStoreOnly (true); // this will make your Column hidden
table.addComponent (col);
table.setPreSelectableColumn (col);

Configuring Column Wrap


We can mark a column to wrap its content by default. A column can be wrapped
through client side column level action also. For example:
ColumnConfig descritionColumn = factory.newColumnConfig(NAME, true);
descritionColumn.setColumnWrapped(true);

628 Customization Guide


Note
The screen shot above shows text wrapping enabled in the Name column and
the Wrap Text option in the drop down menu in the Last Modified column.

Additional attributes set via the setComponentProperty sub


tag
getModel tag attributes
getModel Creates a component model based on the supplied component descriptor
and query parameters. The resulting model is assigned to a scoped variable
specified by the var attribute. Its tag class is com.ptc.core.components.tags.
components.GetModelTag and the body content is “scriptless”

Configuring a Table — Adding a Help Icon


The help button will appear in the upper right corner of the table/tree if you set a
help context in your builder:
// sets the help topic to use from the Windchill Help Center
tableConfig.setHelpContext("HelpTopicName");

If your table/tree is still defined in a jsp instead of with a builder, adding the help
topic would be as follows:
<renderTable model="${tableModel}" helpContext=" HelpTopicName"/>

On click of the “?” button, a pop up window will open which will show the help
topic for the table.
See Linking to Help Topics on page 1114 for more information.

Presenting Information in the UI 629


Specifying Datautility for Columns
Data utilities allow developers to post-process and/or augment the data returned
by the low-level data acquisition API. The additional information can be returned
by an additional query, a call to a service, or whatever else you can get at via Java
code. To specify the data utility for a column can be done by using
setDataUtilityId() in table config.
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
ColumnConfig col = factory.newColumnConfig("iconType", true);
col.setDataUtilityId("typePicker.iconType");
table.addComponent(col);

To register the dataUtility, you need to put in *service.properties. An example


entry is:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.ptc.windchill.enterprise.picker.type.
dataUtilities.IconTypeDataUtility"
requestor="java.lang.Object"
selector="typePicker.iconType"
cardinality="duplicate"/>
</Service>

Configuring Table Columns as Hyperlinks


Adding hyperlink to the table data.
We can specify the link to the particular columns in the table. When the user
clicks on that link, the new page (Infopage) will open up. This can be done by
setting setInfoPageLink() to true in table builder.
For example:
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
ColumnConfig col = factory.newColumnConfig("name", true);
col.setInfoPageLink(true);
table.addComponent(col);

This result in the name column displayed as hyperlink.

630 Customization Guide


Configuring a Table — Creating a Customized View
If the table is to be configured to have customized views, table builder should
implement interface ConfigurableTableBuilder. The interface,
ConfigurableTableBuilder has only method:
ConfigurableTable buildConfigurableTable(String id) throws WTException;

The method should return an instance of a class implementing interface


ConfigurableTable. Default JCA implementation is provided by class
JCAConfigurableTable.
Table views intended for JCA are required to extend the com.ptc.core.htmlcomp.
components.JCAConfigurableTable class.
As in 9.x versions, no mapping in service.properties.xconf to this class is required.
When implementing getOOTBTableViews and defining OOTB views, it is
important to use the correct column ids. Column ids for common attributes are
defined in com.ptc.core.components.descriptor.DescriptorConstants.
ColumnIdentifiers. If the column is not found here, then it is best to use the
available attribute report for the types contained in the table. Available Attributes
report link is available under Customization tab inside “Tools” link.
If more than one table view was implemented, then the current view displayed
would be either the first view on the list (alphabetically) or the table view set in
the getOOTBActiveViewName method.

Presenting Information in the UI 631


Selecting “Customize…” from the current view list launches a pop-up displaying
the configurable table views. From there, additional table views can be added and
removed using the toolbar actions.
For each view in that list, there is an action to set that view as “active”. By using
this action, any view can be set as the default. An example:
public class MyTableBuilder extends AbstractConfigurableTableBuilder {

@Override
public ConfigurableTable buildConfigurableTable(String tableId)
throws WTException {
return new MyConfigurableTable();
}

/* an internal static class */


private static class MyConfigurableTable extends JCAConfigurableTable {

}

}

Setting Table Size Limits


The maximum number of rows that can be fetched in a table on a client can be set
using the table size limit preference.

632 Customization Guide


If the table has more data than the table size set in the preference, next/ previous
links are displayed at the footer to navigate through the data:

Using Tables in Wizards


Saving Form Data
The table component can be used to edit data. Since the table is using a buffered
view and not all objects are kept in the DOM at all times there can be some
special handling needed to ensure the data is getting saved as desired.
The data for the table is all saved behind the scenes in the table’s datastore. When
the user updates a field there is default handling in place that saves the updates to
this store. In some cases this default handling may not work. Additionally when a
wizard is submitted any hidden rows in a table are rendered to ensure that all data
is available in the form as it has always been.

Wizard Table Limitations


Due to browser security restrictions, browser file input fields cannot be saved to
the table’s datastore and re-rendered with a value. This means that any values
entered into browser file input fields will be lost when doing operations that
refresh the grid from the store (drag and drop, locking, scrolling in a buffered
table, etc.). Because of these limitations, it is recommended that you do not place
a file input field inside an editable table.

Presenting Information in the UI 633


If you must include a file input field in your editable table, you should configure it
to disable the grid features that cause the values to be lost. The following grid
features will be disabled:
• Drag and drop of columns
• Column locking
• Row buffering for performance improvements of large tables
• Find in table
• View selected objects only
• Performance improvements for mass removal of rows in the table.
It will only disable grid features if the File Upload preference is set to use the
default browser file input. To do this, add the following tag to your wizard JSP:
<jca:setTablePlugin ptype=”gridfileinputhandler”/>

The Attributes table in the Create Multiple Documents wizard, and the
Attachments table in the Attachments wizard step found in many wizards (new
Document, new Change Request, for example) have been configured to turn off
grid features because they contain a file input field in an editable table.

Limitations
None.

Other Resources
Related Customization Documentation
• Adding Actions and Hooking Them Up in the UI on page 511
• Customizing the UI with Ajax on page 291
• MVC Components on page 257
• Action Framework for Windchill Client Architecture on page 512
• User Interface Stickiness on page 561

Related Package/Class Javadoc


• com.ptc.core.htmlcomp.components.AbstractConfigurableTableBuilder
• com.ptc.core.htmlcomp.components.JCAConfigurableTable
• com.ptc.jca.mvc.components.JcaTableConfig
• com.ptc.jca.mvc.components.JcaColumnConfig
• com.ptc.mvc.components.ColumnConfig;

634 Customization Guide


• com.ptc.mvc.components.ComponentConfig;
• com.ptc.mvc.components.TableConfig;
• com.ptc.mvc.components.AbstractComponentConfigBuilder
• com.ptc.mvc.components.AbstractComponentBuilder
• com.ptc.mvc.components.ComponentConfigFactory
• com.ptc.mvc.components.AbstractComponentDataBuilder
• com.ptc.mvc.util.ClientMessageSource

Related Websites
The Spring Framework: http://www.springframework.org

Sample Code
Examples of Usage in Windchill Code
• Product > Folders table
• Product > Templates table
• Recent Updates table on Home page.
• Organization > Profiles table.

Example — Table with DataSources Enabled


This is an example of MVC table implementation that uses synchronous
datasource mode. The table is enabled with configurable views.

Location of the Example


To navigate to this example navigate to Customization ▶ Component Catalog ▶
Table ▶ Table with DataSources Enabled ( in the example section).

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Presenting Information in the UI 635


Action Models for this Example
• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table\DataSourceSyncTableBuilder.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Example — Table (Separate Builders)


This is an example of MVC table implementation that uses a separate config
builder and data builder classes for configuration.

Location of the Example


To navigate to this example navigate to Customization ▶ Component Catalog ▶
Table ▶ Table (Separate Builders) ( in the example section).

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table\MvcTableConfigBuilder.java
• com\ptc\mvc\builders\carambola\table\ MvcTableDataBuilder.java

636 Customization Guide


• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Example — Table (Info*Engine)


This is an example of MVC table implementation that use Info*Engine tasks as
the source of data.

Location of the Example


To navigate to this example navigate to Customization ▶ Component Catalog ▶
Table ▶ Table (Info*Engine) ( in the example section).

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table
\DataSourceSyncTableBuilderWithIETask.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Presenting Information in the UI 637


Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Example — Table With DataSources Enabled


This is an example of MVC table implementation that uses asynchronous
datasource mode. The table is enabled with configurable views.

Location of the Example


To navigate to this example navigate to Customization ▶ Component Catalog ▶
Table ▶ Table or Table - Async ( in the example section).

• Select “Table” for table that uses default OOTB result processor.
• Select “Table - Async” for table that uses a custom result processor.

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table\MvcTableBuilder.java
• com\ptc\mvc\builders\carambola\table\DataSourceASyncTableBuilder.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

638 Customization Guide


Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Example — Table(Info*Engine)
This is an example of MVC table implementation that use Info*Engine tasks as
the source of data. This is a synchronous data source example.

Location of the Example


To navigate to this example go to Customization ▶ Component Catalog ▶ Table,
and in the example section, select “Table (Info*Engine)”.

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table
\DataSourceSyncTableBuilderWithIETask.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Presenting Information in the UI 639


Example — Table Async
This is an example of MVC table implementation that uses asynchronous
datasource mode. The table is enabled with configurable views.

Location of the Example


To navigate to this example go to Customization ▶ Component Catalog ▶ Table in
the example section, select:
• “Table” for table that uses default OOTB result processor.
• “Table - Async” for table that uses a custom result processor.

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table\MvcTableBuilder.java
• com\ptc\mvc\builders\carambola\table\DataSourceASyncTableBuilder.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Example — Table (Info*Engine) Async


This is an example of MVC table implementation that use Info*Engine tasks as
the source of data.

640 Customization Guide


Location of the Example
To navigate to this example navigate to Customization ▶ Component Catalog ▶
Table ▶ Table (Info*Engine) or Table (Info*Engine) - Async ( in the example section).

• Select “Table (Info*Engine)” for table using asynchronous data source mode.
• Select “Table (Info*Engine) - Async” for table using asynchronous data source
mode with configurable views.

Actions for this Example


• sortByState
• reloadTable
• strikeThroughRows
• clearStrikeThrough
• CustEx_exportlisttofile_submenu

Action Models for this Example


• mvc_tables_toolbar

Files Used in This Example


• com\ptc\mvc\builders\carambola\table
\DataSourceASyncTableBuilderWithIETask.java
• com\ptc\mvc\builders\carambola\table\MvcTableBuilderWithIETask.java
• com\ptc\mvc\builders\carambola\table
\AbstractCarambolaTableConfigBuilder.java
• WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Note
If the customization source code examples are not installed on your server,
they are available for download from the following location: http://www.ptc.
com/view?im_dbkey=156765

Presenting Information in the UI 641


Windchill Client Architecture Tree
Objective
You want to implement a Windchill Client Architecture Tree for the display of
Windchill business objects.

Background
A tree view is used to display hierarchical data organized in the form of a tree. In
other words, a Tree is a visualization of a hierarchy. In a tree structure, there are
parent and child nodes. The hierarchy level is shown by indentation on the left
side of the Tree nodes.
Implementing a Windchill Client Architecture tree is the same as implementing a
Windchill Client Architecture table. In tree, as opposed to specifying a service
method or QuerySpec, a TreeHandler is specified to populate the content.
Following are the few key salient features of a Windchill Client Architecture Tree
with respect to a Windchill Client Architecture Table

Expand/Collapse Behavior
The expand/collapse functionality is used to traverse the hierarchy of the tree.
Your expansion of the tree will be sticky within a session and will return to the
default between sessions. You can expand or collapse a tree in two ways:
• By using the “Expand” and “Collapse” actions in the menu or toolbar.
○ Expand action enlarged to show detail

○ Collapse action enlarged to show detail

If used in combination with the selection radio button/checkboxes, the selected


nodes will only be expanded to the last level. If you try to expand or collapse
without checking any nodes, then all the nodes will be expanded to the last level.
• By using the Expand/Collapse icons:
○ Expand icon enlarged to show detail

642 Customization Guide


○ Collapse icon enlarged to show detail

The expand icon will populate its next level children, where as the
Collapse icon merely changes the node from an open to a closed state.

Scrolling Behavior
You will loose your sense of the structure if the tree is divided among pages and
hence paging is inappropriate for trees. If there is large data to be presented, the
tree can be made to scroll with column header remaining static.

Expand/Collapse Behavior When Data Size in Tree is More Than Result


Limit
The tree component respects the result limit set for table component. But it
doesn’t provide next – previous links, since user loose sense of structure if parent
nodes are removed. When result limit is reached user is provided with the option
to load all data or stop loading. If user wish to load data above result limit, based
on the expansion state of tree all possible nodes are displayed. If user cancels
loading of all data, number of nodes equal to result limit value are displayed.

Sorting Behavior
Columns in a tree will sort similarly to tables with the following exception: as the
structure of the tree must remain intact – the sorting will occur level-by-level. For
example, in a folder tree when sorting alphabetically by name, first level folders
are sorted as a group, then objects in individual folders are sort as a group, and so
on.

Presenting Information in the UI 643


Intended Outcome

Solution
Use Windchill Client Architecture Tree to display Windchill business objects in
Tree format.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• The actions framework in the Windchill client architecture.
• JCA Table component
• Data acquisitions, Data Utility, GUI component.
• JSP, JavaScript and Custom taglibs.
• Java annotations

644 Customization Guide


Solution Elements
Element Type Description
<your_ConfigBuilder> java TreeConfiguration is
defined here
<your_DataBuilder> java Data fetching service/
commands are defined
here
<your_view_page>.jsp jsp View rendering logic is
defined here
<your>service.properties. xconf DataUtilities and services
xconf are defined here.
<your>action.rbInfo rbInfo Action attributes defined
here.
<your>actions.xml xml Actions can be defined
here.
<your>actionModels.xml xml Action models can be
defined here.

Implementing Tree Component using Asynchronous DataSource


To implement a tree component using Asynchronous DataSource,
TreeDataBuilderAsync interface needs to be implemented. It has a single method
to be implemented by the concrete class:
void buildNodeData(Object node, ComponentResultProcessor resultProcessor)
throws Exception

It Fetches children for each node.The first call to this method from infrastructure
will always pass first argument as TreeNode.RootNode.This first call ensures that
all rootNodes are fetched for subsequent calls. The subsequent calls will always
pass a treeNode for which child nodes are required to be fetched.
E.g. The code should handle this case similar to following code snippet:
List nodes;
if (node == TreeNode.RootNode){
nodes = getRootNodes();
resultProcessor.addElements(nodes);
}else {
getNodes(node);
nodes = resultProcessor.addElements(nodes);
}

Presenting Information in the UI 645


Implementing Tree Component without using DataSources
To implement Tree component without DataSources, TreeHandler interface needs
to be implemented. TreeHandlerAdapter provides default implementation.
TreeHandler is a JAVA interface ,which is responsible for populating the tree
content.Following methods are provided by TreeHandler :
• ModelContext getModelContext() :- Get the handler's model context
• void setModelContext(ModelContext mc) throws WTException :- Sets the
contextual information about the tree that is being built, like the descriptor,
command bean etc. This should be initialized before data is requested from the
handler.
• List getRootNodes() throws WTException :- Get the list of root nodes for the
tree.
• Map<Object,List> getNodes(List parents) throws WTException :- Get a
mapping of the child nodes for each of the parent nodes in the given list This
is the only method that will be called for the expand action, so this method
must be able to initialize the handler properly so that it can answer the
question of what are the children of the parent.
• boolean isExpandNeeded(Object node, int level) throws WTException :-
Determines whether or not the given node needs to be expanded. The default
implementation looks at the session state of the list of nodes already expanded
or configured by the tag.
• boolean hasChildren(Object node) throws WTException :- Determines
whether or not the given node should show the expand norgie if its collapsed.
Override this method to improve performance or to get custom behavior. The
default implementation calls the getNodes and sees if the size is larger than 0.
• void addExpandedNode(Object node) throws WTException :- Add a node to
the expanded node list. This list is returned and used in session state to
remember what the tree expansion is.
Trees need to be carefully created because of their recursive nature that causes
many queries to the database. The Treehandler class can save tree state
information as private attributes on the class and reused for each getNodes call. In
addition, you can take advantage of knowing which tree rows are expanded by the
user with the isExpandNeeded method.
TreeHandlerAdapter is an abstract class which implements TreeHandler which
you can extent. Following is an example
getRootNodes() determine what the root nodes should be. The TreeHandler has
access to the ModelContext, which can be used to access required information.
public List getRootNodes() throws WTException {

NmCommandBean cb = getModelContext().getNmCommandBean();

WTPart part;

646 Customization Guide


NmOid oid = cb.getPageOid();
if (oid == null) {
log.debug("No oid found in request, trying GOLF_CART");
part = getGolfCart();
}else {
if (!oid.isA(WTPart.class)) {
throw new ClassCastException("Expected part, but was: " + oid);
}
part = (WTPart)oid.getRef();
}

if (part == null) {
log.debug("Couldn't get part");
return null;
}

configSpec = ConfigHelper.service.getConfigSpecFor(part);
return Collections.singletonList(part);
}

The method first retrieves the NmCommandBean from the model context and
extracts the primary oid from it. If no oid was requested from the user, then it uses
the GOLF_CART part instead by calling the getGolfCart method. The
getGolfCart method simply queries and returns the GOLF_CART. If the user did
specify an oid in the request parameter, it checks to make sure the oid is a
WTPart. Otherwise, it throws a ClassCastException. If it’s the expected oid, it
continues by retrieving the part from the oid via the getRef method. This method
inflates the referenced object, which then can be cast into a WTPart. The last thing
it checks is if the part retrieved either from the oid or the GOLF_CART is null and
if so return null. The configSpec variable is assigned the ConfigSpec of the part
using the ConfigHelper class. This helper class contains a service that helps obtain
Iterated objects from Mastered objects. Lastly, an immutable List containing the
part is returned.
getNodes(List parents) Get a mapping of the child nodes for each of the parent
nodes in the given list. It can be called directly without calling the getRootNodes()
method first. E.g. (expand action). This means that this method must be able to
initialize the handler properly so that it can answer the question of what are the
children of the parent.
The given example, generates a hierarchy of WTPart based on the
WTPartUsageLinks.
public Map<Object,List> getNodes(List parents) throws WTException {
if (configSpec == null) {
configSpec = getDefaultConfigSpec();
}
Map<Object,List> result = new HashMap<Object,List>();

Presenting Information in the UI 647


//API returns a 3D array where the 1st dim is the parent parts,
//the 2nd dim is the list of children for a given parent,
//and the 3rd dim is 2 element array w/the link obj at 0 and the child
part at 1
Persistable[][][] all_children = WTPartHelper.service.getUsesWTParts(
new WTArrayList(parents),
configSpec);
for (ListIterator i = parents.listIterator(); i.hasNext();) {
WTPart parent = (WTPart)i.next();
Persistable[][] branch = all_children[i.previousIndex()];
if (branch == null) {
continue;
}
List children = new ArrayList(branch.length);
result.put(parent,children);
for (Persistable[] child : branch) {
children.add(child[1]);
}
}
log.debug("ParentsToChildren: " + result);
return result;
}
private ConfigSpec getDefaultConfigSpec() throws WTException {
return ConfigHelper.service.getDefaultConfigSpecFor(WTPart.class);
}

Custom tree handlers need to be registered. Please refer Refererence to


<DataUtilities Document> for information on how to register services. Following
is a sample tree handler entry.
<Service context="default" name="com.ptc.core.components.beans.TreeHandler">
<Option requestor="your_object" selector="your_treeHandler"
serviceClass="your_treeHandler_class"
cardinality="duplicate"/>
</Service>

If you want to show non-persistables in a Tree, you are recommended to return


Element for getRootNodes & getNodes methods. If your element doesn’t have a
valid “ufid” value available or “obid” attribute, you need to provide NmObject for
each row object. This can be done in two ways.
1. Author a DataUtility which extends DefaultNmObjectUtility and override its
getTargetObject() method which will return a NmObject for the row object.
Please refer to NmObject Utilities on page 590 for more information.
2. Your Element will have an attribute named "nmObject" with its value an
instanceof NmObject

648 Customization Guide


Otherwise, to show non-persistables, you can write a wrapper class extending
from NmObject and override getOid() method to return proper NmOid.

Presenting Information in the UI 649


Procedure — Configuring JCA Tree
• Implementing ComponentConfigBuiler and ComponentDataBuilder
• Defining View

Implementing ComponentConfigBuiler and ComponentDataBuilder


There are two approaches:
• Separate builder approach
• Single builder approach

Separate Builder Approach


In this case separate classes are written for ComponentConfigBuiler and
ComponentDataBuilder

Using Asynchronous DataSource

Implementing ComponentConfigBuilder
Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type =
ComponentBuilderType.CONFIG_ONLY)
public class TreeExampleConfigBuilder extends AbstractComponentConfigBuilder {
private static final String RESOURCE = "com.ptc.carambola.carambolaResource";
@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
ComponentConfigFactory factory = getComponentConfigFactory();

//Create TreeConfig
TreeConfig tree = factory.newTreeConfig();
// Need to set DataSOurceModes explicitely to DataSourceMode.ASYNCHRONOUS
((JcaTreeConfig) tree).setDataSourceMode(DataSourceMode.ASYNCHRONOUS);

// Set expansion level . Default is TableTreeProperties.ONE_EXPAND


(expand by one level)
((JcaTreeConfig) tree).setExpansionLevel(TableTreeProperties.FULL_EXPAND);

tree.setLabel((new ResourceBundleClientMessageSource(RESOURCE)).getMessage
("PART_TREE_LABEL"));

//Add Columns to the config


tree.addComponent(factory.newColumnConfig(NAME, true));
tree.addComponent(factory.newColumnConfig(NUMBER, true));

//Set column to which expand/collapse norgie should appear


tree.setNodeColumn(NUMBER);
return tree;

650 Customization Guide


}
}
Important Points:
1. To use Asynchronous DataSource, DataSource mode should be explicitely set
to DataSourceMode.ASYNCHRONOUS.
2. setNodeColumn method, allows to choose the column for which expand/
collapse norgie is required. Default is “name ” column.

Implementing ComponentDataBuilder
The concrete class should implement interface
com.ptc.mvc.components.TreeDataBuilderAsync. Please check
Java API documentation for more details.
Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type =
ComponentBuilderType.DATA_ONLY)
public class TreeExampleComponentDataBuilder
implements TreeDataBuilderAsync {
@Override
public void buildNodeData(Object node,
ComponentResultProcessor resultProcessor)
throws Exception {
if (node == TreeNode.RootNode) {
List<Object> objects = getRootNodes();
resultProcessor.addElements(objects);
} else {
List nodeList = new ArrayList();
nodeList.add(node);
Map<Object, List> map = getNodes(nodeList);
Set keySet = map.keySet();
for (Object key : keySet) {
resultProcessor.addElements(map.get(key));
}
}
}
private List<Object> getRootNodes(){ // Add code to find RootNodes}
private List<Object> getNodes(List<Object> nodeList){ //
Add code to find ChildNodes}
}

Advanced Configurations by implementing


TreeExpansionStateManager
TreeExpansionStateManager provides following APIs
boolean isExpandNeeded(DefaultMutableTreeNode node, ComponentConfig config,
ComponentParams params) throws WTException;

void addExpandedNode(Object node, ComponentConfig config,

Presenting Information in the UI 651


ComponentParams params)
throws WTException;

Set getExpandedOids(ComponentConfig config, ComponentParams params)


throws WTException;

boolean hasChildren(Object node, ComponentResultProcessor resultProcessor,


TreeDataBuilderAsync builder) throws Exception;

List<DefaultMutableTreeNode> getDynamicExpandedNodes(ComponentConfig config,


ComponentParams params) throws WTException;
Please refer to JavaDoc for details.
Concrete implmenetation of TreeExpansionStateManager is provided by
DefaultTreeExpansionStateManager. This implementation can be
extended to customize the APIs as per requirement or
TreeExpansionStateManager can be implemented directly. The concrete
implementation can be injected into the builder by using
ExpansionStateManager annotation.
Example:
@ComponentBuilder ("folderbrowser_tree")
@ExpansionStateManager (FolderTreeExpansionStateHandler.class)
//
public class FolderTreeBuilder extends AbstractComponentConfigBuilder
implements TreeDataBuilderAsync{…}

Here FolderTreeExpansionStateHandler implements


DefaultTreeExpansionStateManager and is injected into the
FolderTreebuilder
These APIs are useful for customizing the tree expansion state behavior. E.g.
IsExpandNeeded API can be used to override the default logic which decides
whether the node should be expanded.

Without using DataSource


In this case the either setDataSourceMethod should not be called or should
set dataSourceMode to DataSourceMode.SYNCHRONOUS. All other
configurations are same as explained in the “Implementing
ComponentConfigBuilder” section.

Implementing ComponentConfigBuilder

Implementing ComponentDataBuilder
In this case the databuilder should implement ComponentDataBuilder interface.

652 Customization Guide


Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type =
ComponentBuilderType.DATA_ONLY)
public class TreeExampleComponentDataBuilder implements ComponentDataBuilder {

@Override
public TreeHandler buildComponentData(ComponentConfig config,
ComponentParams params) throws WTException {
return new customTreeHandler();// customTreeHandler should implement
TreeHandler or extend TreeHandlerAdapter
}
}

Single Builder Approach


In this case both ComponentConfigBuilder and ComponentDataBuilder are
implemented by a single class.

Using Asynchronous DataSource


Example:
@ComponentBuilder(value = "custom.treeExample")
public class TreeExampleBuilder implements TreeDataBuilderAsync,
ComponentConfigBuilder,ComponentConfigFactoryAware {....}

Without Using DataSource


Example:
@ComponentBuilder(value = "custom.treeExample")
public class TreeExampleComponentDataBuilder extends
AbstractConfigurableTableBuilder{….}

Defining View
setView method on componentConfig enables setting of view for a particular
builder The view should be set relative to /WEB-INF/jsp folder. The default view
points to uses WEB-INF/jsp/components/tree.jsp
The default view can be customized using the custom tag definitions provided in
file <Windchill>\codebase\WEB-INF\tlds\jcaMvc.tld

Presenting Information in the UI 653


Customization Points

Class Diagram

Customization points for JcaTreeConfig


The following table depicts the customization points available using TreeConfig
APIs.
Property setting API Description
setExpansionLevel Set the the initial expansion level of the
tree.
setNodeColumn Set the name of the column that will be
used to display node labels.
setShowTreeLines Set whether tree lines will be displayed
to show structure in the tree
setDisableAction If set to true, will not show the expand/
collapse norgie in the tree

JcatTableConfig provides an API setFindInTableMode. This API can be used for


tree to enable/disable findInTree functionality.

Configuring Tree – Defining Node Column


The id of the column that you want to display node labels (or +/- norgie) should be
passed to setNodeColumn method

654 Customization Guide


In buildcomponentCOnfig method, builder should call this setter method on
TreeConfig
Example:
TreeConfig tree = factory.newTreeConfig();
tree.addComponent(factory.newColumnConfig(NAME, true));
tree.addComponent(factory.newColumnConfig(NUMBER, true));
tree.setNodeColumn(NUMBER);

Configuring Tree — Control Level of Expansion


When the Tree is populated and presented for the first time, you can control the
level to which it’s expanded. It can be done by one of the following expansion
level using setExpansionLevel
• If the expansion value is “none”, it will be expanded until root level. For a
value of “one”, it will expand until I level and for a value of “full”, you get a
fully expanded tree.
Example:
TreeConfig tree = factory.newTreeConfig();
treeConfig. setExpansionLevel (TableTreeProperties.FULL_EXPAND);

Configuring Tree – Hide Expand/Collapse Norgie


Expand/collapse norgie presentation is controlled by setDisableAction method.
You can set string value for this attribute. “true” value will present the expand/
collapse norgie whereas “false” value will hide them.
TreeConfig tree = factory.newTreeConfig();
treeConfig. setDisableAction(“false”) //hides the expand/collapse Norgie

Presenting Information in the UI 655


Configuring Tree — Enable Tree Lines
You can show tree lines to display the structure in the tree by using calling
setShowTreeLines method as following:
TreeConfig tree = factory.newTreeConfig();
treeConfig. setshowTreeLines (false);

Configuring Tree — Pre Selection of Rows


To configure pre selection of rows in tree, register a function when component is
available.
The function name can be anything but it should be in global namespace.
PTC.onAvailable(‘<component_id>’,populateConfig);
In the registered function provide implementation of
populatePreSelectionsConfig function which is defined at grid object.
function populateConfig(grid){
grid.populatePreSelectionsConfig = function(preSelecionObj){
preSelecionObj.comparableFn = "PTC.carambola.compareOid";
var defaultValues = ['LEG','BOLT_1_4','TIRE'];
preSelecionObj.oids = defaultValues;

656 Customization Guide


}
}
Infrastructure calls populatePreSelectionsConfig function for each grid
at runtime so populatePreSelectionsConfig function name can’t be
changed.
In populatePreSelectionsConfig function specify values array which
needs to be preselected and comparator function in the preSelecionObj
argument.
Comparator function is needed to ascertain whether JCA oid’s representation is
same as specified in preSelectionObj.oids to preselect a row.
For e.g. in type picker, oid specified will be in the format
wt.doc.WTDocument while the JCA representation is
typepicker$typePicker$$|components$loadWizardStep$$wt.
doc.WTDocument!* so a comparator function would check whether
wt.doc.WTDocument is same as
typepicker$typePicker$$|components$loadWizardStep$$wt.
doc.WTDocument!*

Spring MVC Implemented Tree


Migrating JCA tree customization to the MVC implementation
customization
For customizing JCA trees, various attributes on the tags are specified. All
attributes supported on JCA tree tags are supported on the MVC beans. Each JCA
tree is represented by interface TableDefinition. The class implementing the
TableDefinition would implement methods that can be used to populate the
configurable attributes on the beans. So the attributes which were previously
configured for the tags should now be populated on corresponding beans
mentioned above. For detailed information on defining the TableDefinition refer
to Constructing and Rendering a Table Using the JSP Framework on page 606.

Sample Code
Examples of Usage in Windchill Code
• Folder Browser table
• Type Picker
• Team Tree on Home-> Team
• Preference Manager Tree
• Tree Examples under Customization Tab

Presenting Information in the UI 657


Attribute Customization
You want to customize the display of an attribute of a Windchill object.

Background
Windchill attempts to provide consistent attribute behavior across all client
applications. The Windchill Client Infrastructure provides support for rendering
attributes of the standard Windchill supported data types (see Windchill Attribute
Types on page 661 for more information). This infrastructure includes standard
data acquisition, rendering and form processing mechanisms and, re-usable
components for rendering the UI elements for attributes. These components honor
the meta-data from attribute definition, the configurations defined for that
attribute, and the persisted value(s) of the attribute, if any.
Windchill provides multiple configurations points for customizing an attribute’s
display and behavior. The Type and Attribute Management utility is the
recommended configuration tool. For certain cases, other configuration points
may need to be used, such as:
• Java source files of modeled Windchill classes. See “GeneratedProperty” in
Modeling Columns for more information.
• Object Initialization Rules Administration. See “About Object Initialization
Rules” in the Windchill Help Center for more information.
• Preference management. See “About the Preference Management Utility” in
the Windchill Help Center for more information.
• Profile administration. See “Profiles as a Visibility Control Mechanism” in the
Windchill Help Center for more information.
The most common configurations include:
• Constraints
• Properties that can be set on attributes in the Type and Attribute Management
utility
• Default values for attributes
Some of the other factors that implicitly affect the behavior of attributes include:
• Behavior built into the infrastructure to comply with Windchill UI standards
• DB configurations
• Attribute validators (see UI Validation on page 770 for more information)
The framework also provides extension points for customization via the ability to
override the standard rendering and data acquisition behavior. See Data Utilities
on page 704 for more information.

658 Customization Guide


Scope of an attribute configuration
Windchill offers multiple configuration points for the same configuration as a
mechanism to control the scope of the configuration. In general, there are 3
possible scopes for a configuration.
• Configurations that apply to all attributes of all object types on all screens.
This is normally set in the Preference Management Utility.
• Configurations that apply to a single attribute of a single type on all screens.
Attribute Definitions are set in the Type and Attribute Management Utility.
• Configurations that apply to a single attribute of a single type in a specific UI
only. Attribute Layouts are set in the Type and Attribute Management Utility or
when defining the component configuration using a java builder.
For certain configurations, more than one configuration point with the same scope
is available in order to support backward compatibility.
The mechanism used to resolve the values of a configuration set using multiple
configuration points varies with each configuration and is detailed in
Customization of Common Windchill Business Attributes on page 696.
For rules pertaining to overriding attribute constraints, please see administration
of Constraints in the Type and Attribute Management utility.

Terminology
Definition of some commonly used terms
Term Definition
Attribute Panel The UI for displaying attributes as name-value pairs
according to the Attribute Layout definition.
Client / Screen The end user UI in which the attributes will be
displayed. Example: Create Wizard Attributes Step.
Info Page Primary The attributes panel in the information page that is
attributes primarily used for displaying a small set of the
attributes. This is normally displayed at the top of the
info page.
Info Page Full attributes The attribute panel that is primarily used for displaying
list a larger set of attributes on an information page.

Presenting Information in the UI 659


Term Definition
GUI component / UI The UI widget (or a composite of UI widgets)
component displayed on the screen for the user to enter a value for
an attribute or to display the value of an attribute.
Attribute Properties Properties that can be set on attributes either in the
Type and Attribute Management utility or using other
configuration points to customize the display and data
acquisition for an attribute.

Windchill Attribute Customization Overview


There are three steps to getting an attribute rendered in the UI.
1. Placing the attribute in the UI
2. Configuring the UI widget for the attribute (optional)
3. Customizing the source of data (optional)
Out of these, steps 1 and 2 are the most commonly needed steps. This document
primarily deals with these two areas.

Placing the attribute in the UI


The local attribute containers supported by Windchill include:
• Attribute panel. See Attribute Panels on page 348 for more information.
• Attribute table. See Attribute Tables on page 737 for more information.
Attributes can also be displayed on the UI outside these containers.

Configuring the UI widget for the attribute


OOTB Windchill automatically determines the UI components to be used for a
certain attribute based on the following:
• Windchill UI standards
• The data type of attribute
• The constraints and other configurations defined on the attribute
The Windchill configuration points allow you to alter some of the rendering
properties of the widget
For some very limited cases, it is possible to specify an alternate widget using a
configuration. For all other cases, mapping an alternate widget to an attribute
would require writing a custom data utility. See Creating the Data Utility Class on
page 704 for more information.

660 Customization Guide


Customizing the source of data
The source of the data for a given attribute on a given UI can be altered by
configuring some of the data acquisition properties, but this should be used only
for some very special customization requirements.

Windchill Attribute Types


Windchill supports five types of attributes:
1. Modeled (see Modeling Columns on page 1952 for more information)
2. Global (see “Creating a New Attribute” in the Windchill Help Center for more
information)
3. Local (see “Creating a New Attribute” in the Windchill Help Centerfor more
information)
4. Alias (see see “Creating a New Attribute” in the Windchill Help Center for
more information)
5. Calculated (see “Creating a New Attribute” in the Windchill Help Center for
more information)

Calculated Attributes and Alias Attributes


Alias attributes and some calculated attributes are derived from the values of other
attributes. So these attributes should not be used on Create or Edit clients. If they
are used in create or edit layouts, “(Unassignable)” will be displayed. They can be
used on UIs that display persisted values of attributes.
Calculated attributes that are based on constant values may be displayed in create
and edit clients.
For more information on defining these attributes, see “Creating a New Attribute”
in the Windchill Help Center.

Presenting Information in the UI 661


Windchill Attribute Configurations
Attributes of Windchill objects are rendered in one of the two modes, commonly
known as the input mode and the view mode. The input mode is used for allowing
the user to set/edit the value of an attribute. The view mode is used for displaying
the value of an attribute in an un-editable mode.
The following sections identify the default implementation of each of the pieces
involved in displaying the input field and/or value field for each data type.

String
Default behavior and available configurations

662 Customization Guide


Input View
Rendered as: Rendered as:

UI Configurations: UI Configurations:
• Required Input on page 670 • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• Validating Input Values and Legal • Multiple Values (Global Attributes
Value Lists on page 678 Only) on page 686
• Visibility and Modifiability on page • Defining Custom Labels on page
675 689
• Multiple Values (Global Attributes • Create Hyperlinks (see
Only) on page 686 Configuration Points on page 708)
• Defining Custom Labels on page • Making a String Value All Upper
689 Case or All Lower Case on page
687
• Controlling the Size of Input Fields
for String Attributes on page 685
• Limiting the Length of Values
Entered for a String Attribute on
page 683
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Date and Time


Date & Time attributes are used to store a date only value (yyyy-mm-dd) or a date
and time value (yyyy-mm-dd hh:mm).
Default behavior and available configurations

Presenting Information in the UI 663


Input View
Rendered as: Rendered as:

UI Configurations: UI Configurations:
• Required Input on page 670 • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• Validating Input Values and Legal • Multiple Values (Global Attributes
Value Lists on page 678) Only) on page 686)
• Visibility and Modifiability on page • Defining Custom Labels on page
675 689
• Multiple Values (Global Attributes • Date Display Format (see
Only) on page 686 Configuration Points on page 708)
• Defining Custom Labels on page • Local Time Zone (see
689 Configuration Points on page 708)
• Date Input Field Type (see
Configuration Points on page 708)
• Local Time Zone (see
Configuration Points on page 708)
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Integer Numbers
Default behavior and available configurations

664 Customization Guide


Input View
Rendered as: Rendered as:

Configurations: Configurations:
• Required Input on page 670 • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• Validating Input Values and Legal • Multiple Values (Global Attributes
Value Lists on page 678 Only) on page 686
• Visibility and Modifiability on page • Defining Custom Labels on page
675 689
• Multiple Values (Global Attributes • Percent (see Configuration Points
Only) on page 686 on page 708)
• Defining Custom Labels on page • Currency (see Configuration Points
689 on page 708)
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Real Numbers
A Real Number is stored as a decimal representation (e.g. 1.23).
Default behavior and available configurations

Presenting Information in the UI 665


Input View
Rendered as: Rendered as:

Configurations: Configurations:
• Required Input on page 670 • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• ) on page 678 • Multiple Values (Global Attributes
Only) on page 686
• Visibility and Modifiability on page
675 • Defining Custom Labels on page
689
• Multiple Values (Global Attributes
Only) on page 686 • Percent (see Configuration Points
on page 708)
• Defining Custom Labels on page
689 • Currency (see Configuration Points
on page 708)
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Real Numbers with Units


Default behavior and available configurations

666 Customization Guide


Input View
Rendered as: Rendered as:

Configurations: Configurations:
• Required Input on page 670) • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• ) on page 678 • Multiple Values (Global Attributes
Only) on page 686
• Visibility and Modifiability on page
675 • Defining Custom Labels on page
689
• Multiple Values (Global Attributes
Only) on page 686 • Percent (see Configuration Points
on page 708)
• Defining Custom Labels on page
689 • Currency (see Configuration Points
on page 708)
• Measurement System (see
Configuration Points on page 708) • Measurement System (see
Configuration Points on page 708)
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Boolean
Default behavior and available configurations

Presenting Information in the UI 667


Input View
Rendered as: Rendered as:

Configurations: Configurations:
• Required Input on page 670 • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• Visibility and Modifiability on page • Defining Custom Labels on page
675 689
• Defining Custom Labels on page
689
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Use the “Include Blank Option” to control whether the Undefined option is
shown. For more information see Configuration Points on page 708.

Hyperlink (a.k.a. URL in the Manage Reusable Attributes utility)


Hyperlink attributes are used to create a link to a system outside of Windchill. The
value of this attribute should be a fully qualified URL.
Example:
Valid value: http://www.ptc.com or www.ptc.com
Invalid value: ptc.com
Default behavior and available configurations

668 Customization Guide


Input View
Rendered as: Rendered as:

Configurations: Configurations:
• Required Input on page 670) • Visibility (see Visibility and
• Default Values on page 673 Modifiability on page 675)
• ) on page 678 • Multiple Values (Global Attributes
Only) on page 686
• Visibility and Modifiability on page
675 • Defining Custom Labels on page
689
• Multiple Values (Global Attributes
Only) on page 686
• Defining Custom Labels on page
689
Data Acquisitions Configurations: Data Acquisitions Configurations:
• Configuring the source of data • Configuring the source of data
(Customizing Data Acquisition on (Customizing Data Acquisition on
page 690 for more information) page 690 for more information)
• Configuring the data utility (see • Configuring the data utility (see
Data Utilities on page 704 for more Data Utilities on page 704 for more
information) information)

Object Reference Attributes


Limited client infrastructure support is available for Object Reference attributes.
Display of object reference type attributes is supported out-of-the-box. Support for
input/editing of object reference type attributes is limited to very specific
attributes and specific usages only, and is not generally meant for reuse or
customization.

Presenting Information in the UI 669


Common Attribute Customization Procedures
The following attribute customizations are available:
• Required Input on page 670
• Default Values on page 673
• Visibility and Modifiability on page 675
• Validating Input Values and Legal Value Lists on page 678
• Limiting the Length of Values Entered for a String Attribute on page 683
• Controlling the Size of Input Fields for String Attributes on page 685
• Multiple Values (Global Attributes Only) on page 686
• Making a String Value All Upper Case or All Lower Case on page 687
• Automatically Creating Hyperlinks on page 688
• Defining Custom Labels on page 689
• Customizing Data Acquisition on page 690
• Providing Alternate UI Behavior on page 692

Required Input
You want to make it compulsory that a value is provided for an attribute.

670 Customization Guide


Solution Elements
Element Description
Required Constraint This configuration will be applied to an
attribute on all the UIs in which the
attribute is displayed. This rule is
enforced both in the UI and during
persistence in the DB. For exceptions
see the javadoc for
com.ptc.windchill.annota
tions.metadata.PropertyCon
straints.
The constraint can be set using one the
following configuration points:
For modeled attributes:
• Required
PropertyConstraint
annotation (see Modeling Business
Objects on page 91 for more
information)
• Required Constraint in the Type and
Attribute Management utility. See
the “Constraints Tab” online help
topic in the Windchill Help Center
for more information.
For global attributes & local attributes:
• Required Constraint in the Type and
Attribute Management utility. See
the “Constraints Tab” online help
topic in the Windchill Help Center
for more information.
Input required Property The property Input Required can
be set on a modeled, global or local
attribute.
Scope: This configuration is applied to
this attribute only on the specific
attribute panel for which the property is
set. This setting is purely a UI only rule
and is not enforced during persistence
in the DB.

Presenting Information in the UI 671


Element Description
The Input Required property
cannot be used to disable mandatory
input on an attribute that already has a
Required constraint.

Intended Outcome
When the attribute is displayed as a Name-Value pair like in an Attribute Panel,
the attribute will be marked with an ‘*’ in front of the label.

A validation message will be thrown when the data is submitted or when the user
navigates to another screen. This message is not customizable.

Solution
The configurations required to achieve the different kinds of behavior are listed
below:
If you want to….. Configuration
Make input required on all UIs in Use the Required Constraint
which the attribute is displayed for
entry/editing
Make input required when the attribute Use the Required Constraint
does not have a UI for entering the
value, like import of data,
programmatic creation of objects
objects/attributes
Make input required for the attribute Use the Input Required property
only on a specific UI
Make input required for the attribute Use the Input Required property
only in the UI; do not enforce this
outside the UI, like when a value is
provided programmatically

Note
In tables that allow input of data, the “*” will not be added to the column
headers. This is because if a table displays more than one object type, for any
given column, some types might have the attribute configured as required and
others may not.

672 Customization Guide


Default Values
You want to specify a default values for attributes.

Solution Elements
Element Description
initialValue A property used to specify default value
(s) for an attribute. Applies to modeled
attributes only.
See the javadoc for
com.ptc.windchill.annota
tions.metadata.Generated
Property and Modeling Business
Objects on page 91 for more
information.
Default Value A configuration in the Type and
Attribute Management utility.
See the “Default Values Tab” online
help topic for more information.
Object Initialization Rule See the “Object Initialization Rules”
online help topic for more information.
Default Value Display Mode A property used to configure how
default values will be displayed in the
UI. See “Default Value Display Mode”
in Configuration Points on page 708 for
more information.

Intended Outcome
Default values are presented in the UI in one of these three modes and/or, default
values are persisted automatically:
• Default value button
• Pre-populate the field with the default value
• Do not display default value

Solution
You want to specify a default values for attributes.
The configurations required to achieve the different kinds of behavior are listed
below:

Presenting Information in the UI 673


If you want to….. Configuration
Provide default value(s) for use in For a modeled attribute, use the initial
create UI only. value property
You do not want this value to be For global and local attributes, provide
automatically persisted when a value is the default value in the Type and
not provided in the UI. Attribute Management utility.
See the “Default Values Tab” online
help topic for more information.
Provide default value(s)s for use in the Specify the default values using an
Create UI and persistence Object Initialization Rule.
You want this value to be automatically
persisted for that attribute when a value
is not provided until the point of
persistence.
Provide default values for attributes Specify the default values using an
that are not displayed in the Create UI Object Initialization Rule.
and use this value for persistence
This applies when you want to create
an object programmatically (without a
UI) or, when some attributes of an
object are not added to the Create UI of
an attribute.
Specify how default values should be Use the Default Value Display Mode
presented in the UI property.

Limitations
• The default value specified in an Object Initialization Rule will not be
reflected in the Type and Attribute Management utility.
• The value set on an attribute during persistence is the value displayed for that
attribute in the UI. So when a default value is specified in the Modeled class or
the Type and Attribute Management utility, this value will be used only for
displaying in the UI. The default value will not be automatically set on an
attribute during persistence unless the default value was displayed in the UI as
the value of the attribute using one of the methods used for displaying the
default value. Only the default values specified using an Object Initialization
Rule will be automatically saved with the default value.

674 Customization Guide


Visibility and Modifiability
You want to control the visibility and the modifiability of an attribute.

Solution Elements
Element Description
Immutable constraint A constraint defined in the Type and
Attribute Management utility. See the
“Attribute Constraint Rules” online
help topic for more information.
Changeable constraint A property constraint. Applies to
modeled attributes only.
See the javadoc for com.ptc.windchill.
annotations.metadata.
PropertyConstraints and Modeling
Business Objects on page 91 for more
information.
Visibility setting in the Type and A configuration in the Type and
Attribute Management utility Attribute Management utility. See the
“Visibility Tab” online help topic for
more information.
Role-based Attribute Visibility A configuration in the Profiles
Management tool. See the “Managing
Profiles” online help topic for more
information.
Attribute validator Java classes that can be used to perform
attribute validation and filtering. See UI
Validation on page 770 for more
information

Intended Outcome
Attributes are displayed as follows in view mode for the various configurations:

Presenting Information in the UI 675


Outside a table In a table
Hidden The attribute (both label Column header will be displayed. For
attribute & value) is not displayed. those row objects for which the
attribute is hidden, the UI displays
“(Secured Information)”
Created By
(Hidden)
Value
hidden Created By: (Hidden) Created By
(Hidden)
Read-Only When the attribute does When the attribute does not have a
not have a value value:
Created By: Created By
(Unassignable) (Unassignable)
When the attribute has a
value
When the attribute has a value:
Created By: John Doe
Created By
John Doe
Read-Write When the attribute does When the attribute does not have a
not have a value yet value yet:
Created Created By
By:

When the attribute has


value When the attribute has value:
Created John Doe Created By
By:
John Doe

Solution
The configurations required to achieve the different kinds of behavior are listed
below:
If you want to….. Configuration
Always hide an attribute Simply exclude it from the UI (i.e. do not add it to
from a specific UI, for all an attribute panel or a table configuration).
profiles
Hide an attribute from a Use the validation service.
specific UI, for all profiles,
based on specific business

676 Customization Guide


If you want to….. Configuration
logic
Hide an attribute from all Use Role-based Attribute Visibility.
UIs, for specific profiles only Limitation: This feature is available only for
global attributes. See the “Creating a New
Attribute” online help topic for more information.
Always make an attribute not Use the Immutable constraint / changeable
modifiable in any of the UIs constraint.
it is displayed on Limitation: If the attribute is immutable on create
or edit, do not add it to an area of the UI where
fields that will be updated are placed.
Control the modifiability Use the visibility settings in the Type and Attribute
(hide value, make value Management utility to control the modifiability of
editable or read-only) of an an attribute in the end user UI. See the “Visibility
attribute in a specific UI, for Tab” online help topic for more information.
all profiles Limitations: This feature is limited to Create and
Edit UIs only.
Also, at this point, the visibility & modifiability
settings are honored only for those attributes that
have local attribute behavior (All local attributes,
global attributes and some modeled attributes).
Modeled attributes with special OOTB behavior
like Name, Number and Principal may not reflect
this configuration.
Control the modifiability Use Role-based Attribute Visibility.
(hide value, make value Limitation: This feature is available only for
editable or read-only) of an global attributes. See the “Creating a New
attribute in all UIs, for Attribute” online help topic for more information.
specific profiles only

Resolution of Multiple Configurations


When a global attribute has visibility configured both in the Profiles Management
tool and in the Type and Attribute Management utility, it is resolved as follows:
The most restrictive setting of the Type and Attribute Management utility
configuration and the result from the Profiles Management tool will be the final
visibility setting of the attribute.
Example: Visibility settings for the attribute ‘Color’

Presenting Information in the UI 677


in the Profiles Management Value Hidden
tool:
in the Type and Attribute Read-only
Management utility, for
Create Screen:
Resulting visibility setting Value-Hidden (this is the most restrictive of the
applied in the Create UI: two settings)

Validating Input Values and Legal Value Lists


You want to restrict the values allowed for an attribute.

Solution Elements
Element Description
Legal value list Constraint A constraint defined in the Type and Attribute
Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
Enumerated list Constraint A constraint defined in the Type and Attribute
Management utility. See Attribute Constraint Rules
for more information.
EnumeratedType in See the “GenAsEnueratedType columns” section in
Modeled class definitions the “Specialized Persistence Constraints” online
help topic for more information.
Valid Range Constraint A constraint defined in the Type and Attribute
Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
upperLimit, lowerLimit A constraint defined when defining the modeled
Constraints class. See Modeling Business Objects on page 91
for more information on
PropertyConstraints. Same functionality as
the range constraint when used with Numeric
attributes.
Wildcard Constraint A constraint defined in the Type and Attribute
Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
Regular expression A constraint defined in the Type and Attribute
constraint Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
String format constraint A constraint defined in the Type and Attribute
Management utility. See the “Attribute Constraint
Rules” online help topic for more information.

678 Customization Guide


Element Description
No Duplicate Values A constraint defined in the Type and Attribute
constraint Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
Selection List Style A property to specify how the legal values should
be displayed in the UI. See “Select List Style” in
Configuration Points on page 708 for more
information.
Include Blank Option A property to specify whether to include a blank
option in the legal value list . See “Include Blank
Option” in Configuration Points on page 708 for
more information.

Intended Outcome
You are able to do one or more of the following:
• Restrict the input by specifying a set of valid values that the user needs to pick
from.
Example:
○ When Include Blank Option is set to true

○ When Include Blank Option is set to false

• Restrict user input to be within a certain range and display a validation


message when the value is outside the range(s).
• Ensure that the user input for a String attribute conforms to a given pattern of
characters. Display a validation message when the value entered does not
conform to the pattern specified in the constraint.
• Require that user input values be unique.

Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:

Presenting Information in the UI 679


If you want to….. Configuration
Display a Dropdown list (also For global and local attributes, use:
configurable as a group of radio • Legal value list for non-localized
buttons) with the set of legal values for lists
the attribute; do not allow the user to • Enumerated list for localized lists.
type in a value.
For modeled attributes, use:
• EnumeratedType in Modeled class
definitions.
• To define a legal value list on an
existing modeled attribute without
having the need to recompile, use
the Legal Value list constraint
(localized list) or the Enumerated
list constraint(non-localized list) in
the Type and Attribute Management
utility.
Allow the user to type in a value, but For modeled attributes, use upper limit,
restrict the value to be within a given lower limit constraints.
range. For local and global attributes, use the
Range constraint.
Allow the user to type in a value, but Significant figures constraint
define more than one range for This is applicable only to Real
validating the value. Numbers and Real Numbers with Units.
You want to limit the value entered by Use the wildcard constraint, the regular
the user to conform to a given pattern. expression constraint or the string
format constraint
You want to require the set of values Use the No Duplicate Values constraint.
entered for a single business object to
be unique.
Specify how the legal values should be Use the property Selection List Style.
displayed in the UI
Provide a blank option to clear the Use the property Include Blank Option.
current value of the attribute, when
using legal value lists.

Combining legal value lists, valid range constraint significant and


figures constraint
It is possible to have more than one of these configurations defined for an
attribute. The following table shows the effect of combining these configurations:

680 Customization Guide


Constraints specified in Type and UI behavior
Attribute Management utility for
an attribute
Legal value list(s) + Enumerated list(s) The list displayed will be an
+ Enumerated type intersection of all the constraints i.e. the
list will have entries that are common
to all the defined lists.
Example:
Given the following constraints:
1. Enumeration:
COLOR_RED = Red
COLOR_BLUE = Blue
COLOR_GREEN=Green
2. Non-localized legal value list:
COLOR_RED
COLOR_BLUE

Presenting Information in the UI 681


Constraints specified in Type and UI behavior
Attribute Management utility for
an attribute
3. Non-localized legal value list:
Red
Blue

If the user were to apply 1 and 2, the


resulting legal values should be:
COLOR_RED = Red
COLOR_BLUE = Blue

If the user were to apply 1 and 3, the


result would be an empty set (no legal
values).
When all the legal value lists specified
for an attribute are combined, the
resulting list will be an intersection of
all the lists (i.e. only those entries that
are common to all the lists will be
added to the resulting list). So it is
possible to end up with an empty legal
values list when multiple legal value
lists have been defined. When the legal
value list is empty, the end-user UI
displays an input field.
Legal value list + Range constraint Drop down populated with only those
values in the legal value list that satisfy
the range constraint. (configurable as a
group of radio buttons). No tool-tip
message.
Legal value list + Significant figures Drop down populated with only those
constraint values in the legal value list that satisfy
the range derived from the significant
figures constraint. (configurable as a
group of radio buttons). No tool-tip
message.

682 Customization Guide


Constraints specified in Type and UI behavior
Attribute Management utility for
an attribute
Range constraint + Significant figures Input field with tool-tip indicating the
constraint valid range(s). Validation message will
indicate the valid range(s).
The valid range(s) will be the range(s)
derived from the intersection of these 2
constraints.
Legal value list + Range constraint + Drop down populated with only those
Significant figures constraint values in the discrete set that satisfy
both the range(s) of the “Range
constraint” and the range(s) of the
“Significant figures” constraint. No
tool-tip message.

Limiting the Length of Values Entered for a String Attribute


You want to limit the length of the value entered for a string attribute.

Solution Elements
Element Description
upperLimit, lowerLimit Constraints A constraint defined when defining the
modeled class. See the information on
PropertyConstraint in Modeling
Business Objects on page 91 for more
information.
String length Constraint A constraint defined in the Type and
Attribute Management utility. See the
“Attribute Constraint Rules” online
help topic for more information.
Character Entry Limit The property Character Entry
Limit can be set on a modeled, global
or local attribute. See Configuration
Points on page 708 for more
information.

Presenting Information in the UI 683


Intended Outcome
You are able to restrict the length of string attributes in the UI and/or during
persistence and provide feedback to the user when the limit is exceeded.

Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:
If you want to….. Configuration
Restrict input to a certain number of For modeled attributes, use upper limit,
characters on all the UIs in which the lower limit constraints.
attribute will be displayed for editing. For global and local attributes, use the
Also apply this restriction during String length constraint.
persistence. This applies when you The string length constraint can be used
want to create an object on modeled attributes also to make
programmatically (without a UI) or, configurations without requiring Java
when some attributes of an object are code compilation.
not added to the Create UI of an
attribute. Limitation: The length of the Name
attribute conforms to Windchill UI
standards and so cannot be overridden
using this constraint.
Restrict input to a certain number of Use the property Character Entry Limit.
characters on a specific UI only. Note: This limit has to be less than the
Also, do not apply this restriction maximum string length.
during persistence.

Byte length
The validation in the end-user UI also takes into consideration the number of
bytes needed to store the characters entered, to account for variable width
encoding and multi-byte databases.

Merging multiple constraint definitions


When the upperLimit, lowerLimit constraints are specified in the modeled class
and one or more String length constraints are specified for the same attribute in
the Type and Attribute Management utility, all these constraints are compiled
together to provide a range that is common to all of them.
So the minimum number of characters that can be entered will be the maximum of
all the lower limit values. The maximum number of characters that can be entered
will be the minimum of all the lower limit values.
Example:
Annotated Constraint: Lower limit = 30 Upper limit = 50

684 Customization Guide


Type and Attribute Management utility String Length constraint 1: 20 – 40
Type and Attribute Management utility String Length constraint 2: 35 - 45
Result of combining all these constraints: 35 - 40

Controlling the Size of Input Fields for String Attributes


You want to customize the physical width and/or height of the input fields for
string attributes.

Solution Elements
Element Description
String Length Threshold Provided as a property or a preference. See String
For Multiple Line Input Length Threshold For Multiple Line Input in
Configuration Points on page 708 for more
information.
Input Field Type Provided as a property. See Input Field Type in
Configuration Points on page 708 for more
information.
Text Input Rows Provided as a property. See Text Input Rows in
Configuration Points on page 708 for more
information.
Text Input Columns Provided as a property. See Text Input Columns in
Configuration Points on page 708 for more
information.

Intended Outcome
You are able customize the physical width and/or height of the input fields for
some string attributes.

Limitations
• The width and height are not configurable for certain special attributes like
Name and Number.
• If a string input attribute is set to span columns in a layout, the input field
width will expand to fit the combined width of the columns spanned. This will
occur even if the string input length is smaller than the spanned width.
• Column span is not supported in the Structure Browser in this release.

Presenting Information in the UI 685


Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:
If you want to….. Configuration
Customize the height of all input fields Use String Length Threshold For
automatically based on the string length Multiple Line Input
constraint
Override the automatic behavior Use Input Field Type
provided by the String Length
Threshold For Multiple Line Input for a
specific attribute only
Always display a certain type of field Use Input Field Type
(either single line or multi line) for a
specific attribute
Specify the actual number of rows Use Text Input Rows.
visible without scrolling, in a multi-line
text input field.
Customize the width of the input field Use Text Input Columns.
Note: For most fields, the width of the
field defaults to that specified by
Windchill UI standards and the
attribute’s String Length Constraint.

Multiple Values (Global Attributes Only)


You want to allow an attribute to be assigned more than one value.

Solution Elements
Element Description
Single Value Constraint A constraint defined in the Type and Attribute
Management utility. See the “Attribute Constraint
Rules” online help topic for more information.
Delimiter for multi-valued A preference. See “Delimiter for multi-valued
attributes. attributes” in Configuration Points on page 708 for
more information.
No Duplicate Values A constraint that requires the set of values for a
multi-valued attribute to be distinct. Duplicate
values are not allowed.

686 Customization Guide


Intended Outcome
You are able to
• enter multiple values for an attribute
• edit the values stored for an attribute
• add / remove values when editing the attribute
• require each entered value to be unique
• customize the separator used when displaying multiple values in the UI in the
‘view’ mode

Solution
To configure a global attribute to have multiple values, remove its Single Value
constraint. See the “Attribute Constraint Rules” online help topic for more
information.
To require each value to be unique, add the No Duplicate Values constraint.
Otherwise duplicate values are allowed.
When multiple values assigned to a global attributes are displayed in the UI in the
‘view’ mode, they are separated by commas. To customize the separator, use the
preference “Delimiter for multi-valued attributes” . See “Delimiter for multi-
valued attributes” in Configuration Points on page 708 for more information.
Limitation: Support for multiple values for Alias attributes and Calculated
attributes is not available at this time.

Making a String Value All Upper Case or All Lower Case


You want to automatically make a string value all upper-case or all lower-case
without imposing this requirement on the user or any system that provides the
value.

Solution Elements
Element Description
Lower case constraint A constraint defined in the Type and
Attribute Management utility. See the
“Attribute Constraint Rules” online
help topic for more information.
Upper case constraint A constraint defined in the Type and
Attribute Management utility. See the
“Attribute Constraint Rules” online
help topic for more information.

Presenting Information in the UI 687


Intended Outcome
• You are able to enter the value of a string in any case (upper, lower or mixed-
case) in the Create or Edit UIs and have it automatically stored and displayed
as either all upper-case or all lower-case.
• You are able to programmatically(using java code, import operations etc) set
the value of a string attribute in any case (upper, lower or mixed-case) in the
Create or Edit UIs and have it automatically stored and displayed as either all
upper-case or all lower-case.

Solution
`
To configure a string attribute’s value to be automatically converted to all lower-
case, use the Lower case constraint.
To configure a string attribute’s value to be automatically converted to all upper-
case, use the Lower case constraint.

Automatically Creating Hyperlinks


You want to control the automatic conversion of hyperlink text embedded in a
string value to HTML hyperlinks.

Solution Elements
Element Description
Create Hyperlinks preference This preference is available in the
Attribute Handling category. See
“Create Hyperlinks” in Configuration
Points on page 708 for more
information.
Create Hyperlinks property Available in the Type and Attribute
Management utility Attribute
Definition. See “Create Hyperlinks” in
Configuration Points on page 708 for
more information.

Intended Outcome
• You are able set up a string attribute for the automatic conversion of hyperlink
text embedded in a string value to HTML hyperlinks.
• You are able to prevent the automatic conversion of hyperlink text embedded
in a string value to HTML hyperlinks.

688 Customization Guide


Solution
To configure this setting for all attributes, use the Create Hyperlinks preference.
This preference is available under the Attribute Handling category.
To configure this setting for a specific attribute, use the Create Hyperlinks
property that can be set on the attribute definition in the Type and Attribute
Management utility.

Note
The value of the property overrides the value of the preference.

Defining Custom Labels


You want to customize the label displayed for an attribute.

Solution Elements
Element Description
Label property A property defined in the Type and
Attribute Management utility. See
“Label” in Configuration Points on
page 708 for more information.
Display Name property A property defined in the Type and
Attribute Management utility Attribute
Definition. See the “Attribute
Information Page” online help topic for
more information.
rbInfo files • componentRB.rbInfo
• tableRB.rbInfo
• com.ptc.core.htmlcomp.jstable.
jstableResource
• com.ptc.core.ui.tableRB
• wt.enterprise.enterpriseResource
(this is also used as the default)
• wt.identity.identityResource
• wt.templateutil.table.tableResource
• com.ptc.windchill.cadx.ws.
wsResource

Presenting Information in the UI 689


Intended Outcome

Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:
If you want to….. Configuration
Use a custom label on one specific Use the Label property
attribute panel only
Use a custom column header for an If the table is defined using a Java
attribute on a specific table only builder class, set the custom label using
the setLabel() method when
defining the com.ptc.mvc.components.
ComponentConfig for the column
representing the attribute. See the
JavaDoc for more information.
Use the same custom label in all the For attributes of TypeManaged objects,
attribute panels in which this attribute use the Display Name property.
will be displayed
Use the same custom column header for If the attribute has an entry on one of
an attribute, on all tables in which this the following rbInfo files, modify the
attribute will be displayed. rbInfo file entry
com.ptc.core.htmlcomp.jstable.
jstableResource
com.ptc.core.ui.tableRB
wt.enterprise.enterpriseResource (this is
also used as the default)
wt.identity.identityResource
wt.templateutil.table.tableResource
com.ptc.windchill.cadx.ws.wsResource
Determine the source of the label of an Enable the logger
attribute com.ptc.core.component.la
bels

Customizing Data Acquisition


You want to customize the source of the data of an attribute.

690 Customization Guide


Solution Elements
Element Description
Data Utility ID A property defined in the Type and Attribute
Management utility or component builder. See “Data
Utility Id” in Configuration Points on page 708 for
more information.
Need property A property defined in the Type and Attribute
Management utility. See “ Need“ in Configuration
Points on page 708 for more information.
Target Object property A property defined in the Type and Attribute
Management utility. See “Target object” in
Configuration Points on page 708 for more
information.

Intended Outcome
The data for an attribute can be fetched from attributes other than the default.

Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:

Presenting Information in the UI 691


If you want to…. Configuration
Specify the source of data for a Example
composite attribute or a reference The value of the state attribute actually
attribute comes from State.state. The attribute
that is defined on the type is State.
When defining the component
configuration, to indicate that the
source of data for this attribute is State.
state, set the value of the Need property
of the State attribute to State.state.
Specify a different source of data for a When defining the component
specific to the UI only configuration, set the value of the Need
property of the attribute.
Use data from multiple attributes and Wherever possible, define a calculated
assemble them using custom logic, to attribute.
form the value to be displayed in the If the required calculation is outside the
UI. scope of the current support provided
for calculated attributes, use a custom
data utility. When defining the
component configuration, set the value
of the Need property of the attribute to
the list of attributes that need to be
fetched for calculating the value.
Example:
attributeConfig.setNeed("
name, number, creator");

Providing Alternate UI Behavior


You have a need to customize the rendering of a local attribute like Name that
already has a data utility mapped to it, only for a specific case. Since the attribute
id is already mapped to a data utility, adding another mapping using the same
attribute id will not work as expected. See Data Utilities on page 704 for
additional information.

692 Customization Guide


Solution Elements
Element Description
Data Utility ID A property defined in the Type and
Attribute Management utility or
component builder. See “Data Utility
Id” in Configuration Points on page 708
for more information.
Need property A property defined in the Type and
Attribute Management utility. See
“Need” in Configuration Points on page
708 for more information.
Target Object property A property defined in the Type and
Attribute Management utility. See
“Target object” in Configuration Points
on page 708 for more information.

Intended Outcome
The data for an attribute can be fetched from attributes other than the default.

Solution
The combinations of the solution elements required to achieve the different kinds
of behavior are listed below:
If you want to….. Configuration
Use a custom data utility to render Example:
an attribute for the scope of a To render Number using a custom data utility
specific UI only and that attribute called MyNumberDataUtility
already has a data utility mapped
to it and, the UI is one of the 1. Define your custom data utility
following: (MyNumberDataUtility)
• an Attribute panel defined 2. In an xconf file, map the custom data
using the Type and Attribute utility to a custom attribute id
Management utility or a (myNumber). For more information see
builder class Map the Data Utility to the Attribute ID
• an Table defined using the on page 706.
Type and Attribute 3. Set the Data Utility Id property of that
Management utility or a
attribute to myNumber
builder class
Use an existing data utility to In an xconf file, map the custom data utility
render an attribute in all the UIs in to a custom attribute id(myNumber)
which the attribute is rendered
In a specific UI only, render an To render myNumber using using a custom
attribute using an existing data data utility called MyNumberDataUtility

Presenting Information in the UI 693


If you want to….. Configuration
utility; the existing DU might be
1. Define your custom data utility
already mapped to one or more (MyNumberDataUtility)
attributes
2. In an xconf file, map the custom data
utility to a custom attribute id
(myNumber)
3. Set the Data Utility Id property of that
attribute to myNumber

694 Customization Guide


If you want to….. Configuration
Rendering the same attribute for The column ids must be unique, so you need
multiple objects within the same to use Target Object and Data Utility Id
table properties to accomplish this. For example, a
table could have 3 columns that all render
the Name attribute, but from 3 different
objects:
1. Add all the three attributes to the
attribute panel or table definition
2. For the attributes that belong on objects
that are not the backing object, set the
value of the property Data Utility Id to
“name” and the Target Object to the
attribute that represents the object
Example:
To display the name attributes of the
roleAObject and roleBObject the same way
the name attribute of the backing object is
displayed, for each of those attributes, set the
properties as follows:
• For roleAName
○ Data Utility Id = name
○ Target Object = roleAObject
• For roleBName
○ Data Utility Id = name
○ Target Object = roleBObject
Specifying different renderers for Example:
the same attribute id for different You need to render the render the state
object types attribute of a Document differently than the
state attribute of a Part.
Type-based lookup of data utilities is
currently not supported by the infrastructure.
If this type of behavior is needed, and if your
UI displays objects of the same type, then
use the Data Utility Id property to
accomplish this. On a UI that displays
objects of multiple types, like the Folders

Presenting Information in the UI 695


If you want to….. Configuration
page, you may use a custom data utility and
do the type-based checking within that
custom data utility.

Customization of Common Windchill Business Attributes


Some Windchill attributes need to adhere to specific Windchill standards and
rules. This behavior is provided OOTB. Some of this behavior is customizable.
This section lists some of these standard Windchill attributes and their
configuration points.

Number

Render Number as a link to the object’s information page


Use case: I want to render the Number attribute as a hyperlink to the object’s
information page.
This behavior can be enabled/disabled by using the “Is Info Page Link“ property.
See Configuration Points on page 708 for more information.

Making the value of Number server-generated/ server pre-generated/


immutable
The out of the box behavior of Number can be customized using Object
Initialization Rules. See the “Object Initialization Rules” online help topic for
more information.
The combinations of Object Initialization Rules required to achieve the different
kinds of behavior for Number are listed below:
If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
Always use the server <Value algorithm=
generated value and, do "com.ptc.core.ru
not allow the user to enter le.server.impl.Ge
a value. tImmutableCon
straint"/><Value
algorithm=
"com.ptc.core.ru
le.server.impl.
GetServerAssigned
Constraint"/>
Always use the pre- <Value algorithm= Pre-generated value with
generated value "com.ptc.core.ru no override

696 Customization Guide


If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
configured in the Object le.server.impl.Ge
Initialization Rules and, tImmutableCon
display this value in the straint"/><Value
UI and, do not allow the algorithm=
user to modify this value. "com.ptc.core.ru
le.server.impl.
GetServerPreGener
atedValue"/>
Use the pre- generated <Value algorithm= Pre-generated value with
value defined in the "com.ptc.core.ru override.
Object Initialization le.server.impl.
Rules and, display this GetServerPreGener
value in the UI and, want atedValue"/>
to allow the user to
modify this value.
Always require the user If there are no other OIR
to provide the value constraints defined for
Number, this needs an
empty constraints list to
work as expected.
<AttrConstraint
id="number"
algorithm=
"com.ptc.core.ru
le.server.impl.Ga
therAttributeCon
straints"/>
Allow the user to enter a <Value algorithm=
value and, if a value is not "com.ptc.core.ru
provided by the user, le.server.impl.
auto-generate a value on GetServerAssigned
the server. Constraint"/>

Presenting Information in the UI 697


Note
If the above configurations do not yield the results listed above, check the
following values of these other configurations which also affect the editability
of Number in a Create or Edit UI:
• The changeable Property Constraint for a Modeled attribute. See
Modeling Business Objects on page 1944 for more information.
• The Type and Attribute Management utility Visibility settings. See the
“Visibility Tab” online help topic for more information.

Name

Render Name as a link to the object’s information page


This behavior can be enabled/disabled by using the “Is Info Page Link” property.
See Configuration Points on page 708 for more information.

Making the value of Name server-generated/ server pre-generated/


immutable
The same customization method used for Number can be used for Name to make
it server-generated or server pre-generated or immutable. Object Initialization
Rules required to achieve the different kinds of behavior for Name as the same as
those of Number listed in the “Making the value of Number server-generated/
server pre-generated/ immutable “ section in Number on page 696.

Built-in support for Enumeration Constraints on the Name attribute


Starting in Windchill release 10.1 the Name attribute of the Document, Part, and
EPM Document types now has built-in support for Enumeration Constraints
(static and dynamic). Remember that Enumeration entries have both an internal
value and display values for each entry. The display values may be localized in
multiple languages.
This new support allows customers to easily restrict the allowable values for the
Name attribute, and also allows users to see localized values for the saved/
persisted name, depending on their current locale.
If you have activated this feature and also configured an enumeration constraint
on the Name attribute of any of these types (actually the constraint must be
applied to the ___Master of these types), then in Create & Rename (ex. Edit)
wizards the Name attribute will appear as a ComboBox with the (potentially
localized) entries that were specified in the enumeration. In display-only tables &
Info pages, the Name attribute will appear with the “Display” value of the saved
enumeration entry.

698 Customization Guide


Example of an enumeration constraint applied to the “name” attribute (note the
“_EN” suffix was manually added to the display values for testing)

To activate support for Enumeration Constraints on the Name attribute, the


following property must be added to site.xconf, and then “xconfmanager –Fp”
must be run from a windchill shell (and then Windchill must be restarted):
<Property name="com.ptc.EnableEnumeratedName"
overridable="true" targetFile="codebase/wt.properties"
value="true"/>
After this has been done, then launch the Type and Attribute Management utility
(from the “Utilities” page), select one of these types from the tree: Document
Master, Part Master, or EPM Document Master , and then select the “name”
attribute, enter “Edit” mode, add a new Enumeration Constraint (static or
dynamic), and then edit the enumeration (for static, add entries; for dynamic, set
the provider & init string), and then save the changes. (See the Type and Attribute
Management documentation for more info.)
Note that if the “com.ptc.EnableEnumeratedName” property is set, when
the Name attribute is saved (from a Create or Rename wizard), the internal value
of the enumeration entry is saved to the database, NOT the display value of the
entry. When the name attribute is displayed in “view” mode (like in a table or Info
Page), the (localized) display name will be referenced from the enumeration and
displayed in the UI. This allows different users that are using different locales to
see different localized values for the name attribute.
However, it also means that if the “com.ptc.EnableEnumeratedName”
property is set to false (or removed) OR if the enumeration constraint is disabled
or deleted, then the INTERNAL value will be displayed in view mode. Please
keep this aspect of the feature in mind.

Location
The UI behavior of the Location attribute can be customized using Object
Initialization Rules (see the “About Object Initialization Rules“ online help topic
for more information). The combinations of Object Initialization Rules required to
achieve the different kinds of behavior for Location are listed below:

Presenting Information in the UI 699


If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
Always use the ‘server <Value algorithm=
assigned’ folder and, do "com.ptc.core.ru
not want to allow the user le.server.impl.Ge
to specify a folder. tImmutableCon
straint"/><Value
algorithm=
"com.ptc.core.ru
le.server.impl.
GetServerAssigned
Constraint"/>
Always use the pre- <Value algorithm=
generated folder defined "com.ptc.core.ru
using Object Initialization le.server.impl.Ge
Rules and, display this tImmutableCon
value in the UI and, do straint"/><Value
not want to allow the user algorithm=
to modify this value. "com.ptc.core.ru
le.server.impl.
GetServerPreGener
atedValue"/>
Allow the user to select a If there are no other OIR
folder manually, and to constraints defined for
The field is populated
display the launch context Location, this needs an
with the folder from the
folder as the default empty constraints list to launch context.
value. work as expected.
<AttrConstraint
id="folder.id"
algorithm=
"com.ptc.core.ru
le.server.impl.Ga
therAttributeCon
straints"/>
Provide the following <Value algorithm=
options to the user "com.ptc.core.ru
• Use the pre-generated le.server.impl. The value of Autoselect
Folder is the pre-
folder defined using GetServerPreGener
generated value defined
Object Initialization atedValue"/>
using Object Initialization
Rules or, rules.
• Select a folder

700 Customization Guide


If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
manually; display the
launch context folder
as the default value
for this.
• Pre-select the launch
context folder as the
default option.

Presenting Information in the UI 701


If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
Provide the following <Value algorithm=
options to the user "com.ptc.core.ru
• Use the pre-generated le.server.impl. The value of Autoselect
folder defined in GetServerPreGener Folder is the pre-
generated value defined
Object Initialization atedValue"/>
in Object Initialization
Rules or, <Value algorithm=
rules.
• Select a folder "com.ptc.core.ru
manually. display the le.server.impl.Ge
launch context folder tRendererCon
as the default value straint">
for this <Arg>SelectGenera
tedFolderByDe
• Pre-select the pre- fault</Arg></
generated folder as Value>
the default option.
Provide the following <Value algorithm=
options to the user "com.ptc.core.ru
• Use the ‘server le.server.impl.
assigned’ folder or, GetServerAssigned
• Select a folder Constraint"/>
manually; display the
launch context folder
as the default value
for this
• Pre-select the launch
context folder as the
default option.
Provide the following <Value algorithm=
options to the user "com.ptc.core.ru
• Use the ‘server le.server.impl.
assigned’ folder or, GetServerAssigned
• Select a folder Constraint"/>
manually; display the <Value algorithm=
launch context folder "com.ptc.core.ru
as the default value le.server.impl.Ge
for this. tRendererCon
straint">
<Arg>SelectGenera
tedFolderByDe

702 Customization Guide


If you want to….. You will need to The UI the Create
configure your OIRs Wizard will look like
like this… this…
• Pre-select the server- fault</Arg>
assigned folder as the </Value>
default option.

Principal Attributes
1. Render Principal as a link to the Principal’s information page
This behavior can be enabled/disabled by using the “Is Info Page Link”property
(see Configuration Points on page 708).

Revision
The Revision attribute can be configured to distinguish between the checked-out
original and the working copy. This can be done by setting the “Distinguish WIP
Versions” property (seeConfiguration Points on page 708).

Lifecycle State
The Lifecycle State attribute can be configured to render all the lifecycle states
instead of just the current state. This can be configured by setting the “Is Render
All States” property (see Configuration Points on page 708).

Note
This configuration is applied only when the attribute is displayed on a table or
on a component whose com.ptc.core.ui.resources.ComponentType is SIMPLE.

UI behavior
• When Is Render All States is set to true:

• When Is Render All States is set to false:

Presenting Information in the UI 703


Data Utilities
Data utilities are java classes that can be used for customizations that cannot be
accomplished using the available configuration points.
A data utility is used to get the data and meta-data of an attribute and create the UI
component which will be used to render the attribute in the UI. If the data returned
by a core API is not sufficient for creating the UI component, data utilities can be
used to augment this data with additional information. The additional information
can be fetched by an additional query, a call to a service, or whatever else you can
get at via Java code.
The OOTB implementations of data utilities provide the behavior defined for
Windchill OOTB applications in accordance with Windchill UI standards.
You can configure a data utility for any attribute id.

Creating a Data Utility


Creating a new data utility consists of the following steps:
• Create the data utility (Java) class
• Map the data utility class to the attribute id in an XCONF file

Creating the Data Utility Class


Create your data utility by implementing the com.ptc.core.components.descriptor.
DataUtility interface.
Since data utilities are looked up using application context, your implementation
class must be public and must have a public no-arg constructor.
It is highly recommended that when you implement a new data utility, you extend
the AbstractDataUtility base class.
If you have a need to augment the attribute value or change how the attribute is
rendered, you should consider extending the existing data utility, if applicable.
Use the Available Attributes Report or JcaDebug to find the data utility currently
mapped to an attribute. See Available Attributes Report on page 413 and Using
jcaDebug on page 432 for more information.

704 Customization Guide


1. Implement the getDataValue() method of the DataUtility interface:
The getDataValue() method gets the content that should be placed in the UI for
a given attribute.
Example:
Suppose you want to append the value of a specific string attribute with some
extra text. This can be done as follows:
Object getDataValue(String component_id, Object datum, ModelContext mc)
throws WTException {
…..
…..
String rawVal = myObject.get(component_id);
String displayVal = rawVal + “My extra text”;
TextDisplayComponent gui = new TextDisplayComponent(…);
gui.setValue(displayVal);


return gui;
}

Note
Avoid making database calls in getDataValue(), because when dealing with
tables, the method is called once for every cell in the column. If they must
be done, try to do work in setModelData() which is called once per column
and cache the results so the database does not have to be called more often
than necessary.

2. Implement the setModelData() method of the DataUtility interface:


In the interests of performance, we want to process all the objects to be
displayed in a single call to setModelData() and to perform the required
database queries for all the objects at once, rather than making a separate
query for each object.
When multiple objects needs to be fetched, as in the case of a table where
multiple row objects needs to be fetched, the setModelData() method allows
the data utility to prefetch data for all the row objects that will be rendered.
The method is called before getDataValue() is called for any row/cell, and is
supplied a list of all the objects that will be processed.

Presenting Information in the UI 705


You can take advantage of this call to do some multi-object queries and save
the results for later use in the getDataValue() method. If this method is
implemented, then you must configure the data utility to be stateful.

Map the Data Utility to the Attribute ID


Add an application context entry to an xconf file like the following:
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.ptc.core.components.factory.
dataUtilities.ProjectDataUtility"
requestor="java.lang.Object"
selector="projectHealthStatus"
cardinality="singleton"/>
</Service>
<Service name="com.ptc.core.components.descriptor.DataUtility">
<Option serviceClass="com.ptc.core.components.factory.dataUtilities.
FolderedDataUtility"
requestor="java.lang.Object"
selector="location"
cardinality="duplicate"/>
</Service>

A note on cardinality:
Your safest bet is to use a "duplicate" cardinality. This will create a new instance
of the data utility each time one is requested.
Data utility configuration entries can be added to any xconf file that ends up being
read in by application context (any "service.properties"-type file). The general
convention is to use a file named someprefix.dataUtilities.properties.xconf.
When setModelData() is called, the data utility is given a set of objects for which
the JCA infrastructure will later request a suitable value to display in the table for
each of the objects; the data utility has the opportunity to determine these values
and cache them for later retrieval. The JCA infrastructure will later call the
getDataValue() method to obtain the specific table cell value for a given object,
which the data utility may retrieve from its previously computed cache.

How to Find an Attribute ID


When creating an attribute configuration in your java code you must specify the id
of the attribute.
For Typed and TypeManaged objects, the id should be the Internal Name shown
for the attribute in the Type and Attribute Management utility. For other objects,
names can be found in the following sources. When using these reports you must
type in a fully qualified type name, including the full package – for example, “wt.
part.WTPart.”

706 Customization Guide


Logical Attributes Report
This can be viewed by navigating to Customization -> Tools -> Logical Attributes
Report.
For TypeManaged classes, this report includes:
1. Alias attributes defined in LogicalAttributes.xml file(s) (Note: This is no
longer a recommended practice. Use the Type and Attribute Management utility
to define alias attributes instead..)
2. Hard (annotated) attributes, unless overridden by the above.
3. Attributes defined in the Type and Attribute Management utility, unless
overridden by an alias attribute..
For non-TypeManaged classes, this report includes:
1. Alias attributes defined in LogicalAttributes.xml file(s)
2. Hard (annotated attributes), unless overridden by an alias attribute.
Use the Logical Form of the name from this file as the attribute id in
AttributeConfigs and describeProperty tags. Note that not all attributes listed can
be used in the UI. A data utility that has the ability to create a gui component for
the attribute must be available before it can be displayed.

Available Attributes Report


This can be viewed by navigating to Customization -> Tools -> Available
Attributes Report.
This report lists the attributes that can be included in table views. Any attribute in
this list could be included in an attribute panel using the name in the JCA ID
column.

Property Report
This can be viewed by navigating to Customization -> Tools -> Property Report.
This is a composite report that includes the hard attributes of a type, the logical
attributes listed in the Logical Attribute Report, and the table view attributes listed
in the Available Attributes Report. You can click on each attribute to display
additional information about it, including the data utility registered for it, if any.
Note that the DefaultDataUtility will handle many attributes for which there is not
a specific data utility listed.
Not all the attributes in this report are viewable in an attribute panel. In particular,
Calculated attributes cannot typically be used in the UI.

Presenting Information in the UI 707


Configuration Points
Considerations
• Type and Attribute Management utility Attribute Definition : Set using the
Attribute Information Page.. The configuration applies to a specific attributes,
in all clients.
• Type and Attribute Management utility Attribute Panel Layout Definition : Set
using the Editing Group Attribute Properties window of the attribute in the
Type and Attribute Management utility. Can be used only for attribute panels
since the scope is limited to the specific panel.
Can also be set using the ComponentConfig builder, which is used for
customizing attributes on attribute panels or tables. The configuration applies
to a specific attribute in a specific UI only.

708 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Default All data Configures Available as If not If not
Value types how to a Site level specified, specified,
Display populate the preference the value of the value of
Mode default in the the this
value, if Attribute preference property
any, in the Handling “Default from the
input field category. Value Attribute
for the Display Definition
attribute. Mode” will will be
Defaults to be used. used, if one
“Pre- has been
populate”. specified.
Otherwise,
Possible
the value of
values:
the
• None –
preference
the
will be
default
used.
value
will not OR
be used setDefault-
to ValueDis-
populate playMode()
the
input
field
• Pre-
Populate
– the
default
value, if
one is
set, will

Presenting Information in the UI 709


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
be set in
the
input
field
• Button –
A
button
will be
dis-
played
after the
input
field,
the user
can
click the
button
to add
the
default
value to
the
input
field.
Selection All Specifies Available as If not If not
List UI attributes whether the a Site level specified, specified,
Style that have a legal values preference. the value of the value of
Legal Value (selection Note: the this
List list) for the Applies to preference property
constraint attribute all “Selection from the
or an should be attributes, List Style” Attribute
Enumerated displayed as except will be Definition

710 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Value List a drop- Boolean used. will be
constraint down list or attributes. used, if one
defined. as a set of AT this has been
radio- level, the specified.
buttons, style for Otherwise,
Boolean
when the the value of
attributes is
attribute is controlled the
presented by the preference
for data preference will be
entry. Boolean used.
Defaults to Style. OR
“Drop
setSelec-
Down List”.
tionList-
Possible Style()
values:
• Drop
Down
List –
the
values
will be
rendered
in a
drop
down
list,
where
the user
can
select
one
option

Presenting Information in the UI 711


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
• Radio
Buttons
– the
values
will be
rendered
as a set
of radio
buttons,
where
the user
can
select
one
option
Boolean Boolean Controls Available as Use the If not
Style how a Site level property specified,
Boolean preference. “Selection the value of
attributes List Style” the property
are to override “Selection
displayed the value of List Style”
for input, this from the
either as preference Attribute
radio for a Definition
buttons or specific will be
as a attribute. used, if one
dropdown If not has been
list. specified, specified.
Defaults to the value of Otherwise,
“Radio the the value of
Buttons”. preference the
preference

712 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Possible “Boolean will be
values: Style” will used.
be used.
• Drop OR
Down setSelec-
List – tionList-
the Style()
values
will be
rendered
in a
drop
down
list,
where
the user
can
select
one
option

Presenting Information in the UI 713


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
• Radio
Buttons
– the
values
will be
rendered
as a set
of radio
buttons,
where
the user
can
select
one
option
String String Specifies Available as If not If not
Length the a Site level specified, specified,
Threshhold threshold preference. the value of the value of
For for the this
Multiline rendering a preference property
Input multi-line “String from the
input field Length Attribute
for a String Threshold Definition
attribute. for will be
The value Multiline used, if one
can be any Input” will has been
positive be used. specified.
number. If Otherwise,
the the value of
maximum the
length of preference
the attribute will be

714 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
in used.
characters setStrin-
exceeds this gLength-
value, a Threshhold-
multiline ForMultili-
input field neInput()
will be
displayed
for data
entry.
Defaults to
60.
Input Field String Specifies Not If not If not
Type whether the available at specified, specified,
input field this level this the value of
for the property is this
attribute not assigned property
should be a default from the
single-line value. Attribute
or multi- Definition
line. This will be
directive used, if one
will has been
override specified.
that of the OR
string-
Length- setInput-
FieldType()
Threshold-
ForMultili-
neInput.
Possible
values:

Presenting Information in the UI 715


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
• Single
Line – a
textbox
will be
rendered
for this
attribute
• Multiple
Lines –
a text
area will
be
rendered
for this
attribute
Date Input Date Specifies Not If not If not
Field Type whether the available at specified, specified,
input field this level. the default the value of
for a will be this
Timestamp used. property
attribute is from the
of type Attribute
date-only or Definition
date & time, will be
so that the used, if that
UI has been
components specified.
can be Otherwise
created the default
accordingly. will be
used.
OR

716 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
The default setDateIn-
is “Date putField-
Only”. Type()
Possible
values:
• Date
Only –
Allow
the user
to only
set the
date
portion.
• Date
and
Time –
Allow
the user
to set
both the
date and
time
portion.
Date Date A date Not If not If not
Display format available at specified, specified,
Format string (i.e. this level. the default the value of
yyyy-mm- will be this
dd) to use used. property
when from the
displaying Attribute
the value of Definition
this will be

Presenting Information in the UI 717


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
attribute in used, if that
View mode. has been
This does specified.
not affect Otherwise
the format the default
used to set will be
the value in used.
input mode. OR
Please refer setDateDis-
to the Java playFormat
class java. ()
text.
SimpleDa-
teFormat
for the full
set of valid
characters.
If not set,
one of the
following
formats will
be used
from the
rbInfo file
compo-
nentRB:
• STAN-
DARD_
DATE_
DIS-
PLAY_
FOR-
MAT –

718 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
if the
value of
the
property
“Date
Input
Field
Type” is
set to
“Date
Only”,
this
format
will be
used.

Presenting Information in the UI 719


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
• STAN-
DARD_
DATE_
TIME_
ZONE_
DIS-
PLAY_
FOR-
MAT –
if the
value of
the
property
“Date
Input
Field
Type” is
not set
or is set
to “Date
and
Time”,
this
format
will be
used.
Local Time Date Specifies Available as Not Not
Zone the time a User level available at available at
zone to use preference this level. this level.
for Date
attributes
that display
both the

720 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Date and
Time
portions (i.
e. yyyy-
MM-dd hh:
mm zzz).
This is only
used in
view mode;
it is not
used for
input mode.
Measure- Real Specifies Available as Not Not
ment Number the a User level available at available at
system with Units measure- preference this level. this level.
ment
system to
use for Real
Numbers
with Units.
Create String Specifies Available as Note: When Not
Hyperlinks whether a Site level upgrading available at
(in 9.x this URL style preference from 9.x to this level.
was called text 10.0, if this
Ignore URL embedded property
values in in the value were
strings) of a String customized
attribute using the
should be file
displayed as AllClient.
a hyperlink xml, manual
in the view migration is

Presenting Information in the UI 721


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
mode needed.
(example: If not
http://www. specified,
ptc.com). the value of
Defaults to the
‘true’. preference
“Create
Hyperlinks”
will be
used.
Percent Numeric Specifies if Not If not If not
a numeric available at specified, specified,
value is to this level. the default the value of
be will be this
displayed as used. property
a from the
percentage Attribute
or not. This Definition
property is will be
only used in used, if that
view mode. has been
When specified.
specified, Otherwise
the notation the default
used will be will be
locale- used.
specific. OR
Defaults to setPercent()
false.
Currency Numeric Specifies if Not If not If not
a numeric available at specified, specified,
value is to this level. the default the value of
be will be this

722 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
displayed as used. property
currency from the
value or Attribute
not. This Definition
property is will be
only used in used, if that
view mode. has been
When specified.
specified, Otherwise
the notation the default
used will be will be
locale- used.
specific. OR
Defaults to setCurrency
false. ()

Presenting Information in the UI 723


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Input All Used to Not Not If not
Required mark available at available specified,
attributes as this level. the default
‘Required will be
fields’ even used.
though they OR
may not
have a setInputRe-
quired()
‘Required’
constraint.
This
property is
used purely
for the UI
rendering.
Unlike the
“Required
constraint”,
this will not
trigger any
server-side
validation.
Note: If an
attribute
that has a
‘Required
constraint’
is marked as
“not
required”
using this
property, a
server-side

724 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
exception
will be
thrown,
unless the
server-side
code takes
care of
setting the
value for
the attribute
by some
other
means.
The most
common
usage of
this
property is
to force the
user to
provide a
value for an
attribute
that does
not have a
“required
constraint”
defined on
it.
Is Info Page ‘Name’, Specifies if Not Not If not
Link the attribute available at available at specified,
is to be this level. this level. the default
displayed as will be
a hyperlink used.

Presenting Information in the UI 725


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
‘Number’ to the OR
and Information
Page. In the setInfoPa-
Principal geLink()
attributes case of
only Principal
attributes,
this will be
displayed as
a link to the
principal’s
info page.
When not
specified,
the
following
defaults are
used:
• ‘true’
for
Number
and
Contain-
er name
• ‘false’
for all
other
attrib-
utes

Delimiter Specifies Available as Not Not


for the a Site level available at available
multivalued character(s) preference this level.

726 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
attributes to use as a
separator
when
displaying
the values
of an
attribute
that contain
multiple
values. This
applies only
to Global
Attributes
since they
are the only
type of
attributes
that can
have
multiple
values
assigned to
an attribute.
Defaults to
a comma
followed by
a space.
Text Input An integer Not Not If not
Columns value that available at available at specified,
specifies the this level. this level. the width
width to defaults to
render the the value

Presenting Information in the UI 727


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Text Area in specified by
create or Windchill
edit mode. UI
This only standards
applies to and the
String attribute’s
attributes String
and is only Length
used when Constraint.
the property
“Input Field
Type” is set
to “Multiple
Lines”
Text Input An integer Not Not If not
Rows value that available at available at specified,
specifies the this level. this level. the number
height to of rows is
render the based on the
Text Area in String
create or Length
edit mode. Constraint
This only and the
applies to width of the
String column.
attributes The max
and is only number of
used when a rows is
multi-line limited to 3.
input field A scroll bar
is required is added
based on the when the

728 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
properties input
String exceeds 3
Length rows.
Threshhold OR
For
Multiline setTextIn-
putRows()
Input and
Input Field
Type.

Include Specifies Not Not If not


Blank whether a available at available at specified,
Option blank this level. this level. the value
option defaults to
should be true.
added as the OR
first entry of
a dropdown setInclude-
BlankOp-
list that
tion()
displays the
legal value
list of an
attribute.
When the
legal values
are
displayed as
a set of
radio-
buttons, a
button with
the label

Presenting Information in the UI 729


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
“Unde-
fined” will
be added as
the first
button in
the list.
Default to
true.
isRender- Lifecycle Specifies Not Not If not
AllStates state whether to available at available at specified,
attributes render all this level. this level. the value
only the lifecycle defaults to
states false.
instead of OR
just the
current setRender-
AllStates()
state.
NOTE: This
attribute is
applicable
to
components
with
component
type of
SIMPLE or
TABLE
only.
Default to
false.
Distinguish Revision Specifies Not Not If not
WIP attribute whether to available at available at specified,
Versions only distinguish this level. this level. the value

730 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
between the defaults to
checked-out false.
original and OR
the working
copy. setDistin-
guishWIP-
Versions()
Character Species the Not Not setCharac-
Entry Limit maximum available at available at terEntryLi-
number of this level. this level. mit()
characters
that can be
entered in
the UI for a
String
attribute.
Data Utility The id to Not Not setDataUti-
ID use for data available at available at lityId()
utility this level. this level.
lookup.
When
unspecified,
the
descriptor
id is used
for the
lookup.
Need The logical Not Not setNeed()
name of an available at available at
object this level. this level.
attribute
needed to
create the

Presenting Information in the UI 731


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
display
value for a
column cell.
Used by
data utilities
for
retrieving
the cell
value when
the
property/
column id is
not an
attribute
name
defined by
introspec-
tion or
logical
attributes.
Use a
comma-
separated
list if
multiple
attributes
are needed.

732 Customization Guide


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Target The target Not Not Component-
Object object to available at available at Config.
use for this this level. this level. setTarge-
column tObject()
when it is
processed
by the
Windchill
Client
Architecture
infrastruc-
ture. By
configuring
the
targetObject
property,
the
developer
tells the
infrastruc-
ture to use
an alternate
row object
that is
derived
from the
backing row
object
returned by
the
underlying
api.

Presenting Information in the UI 733


Property Applica- Descrip- Prefer- Type and Type and
Name ble tion ence Attribute Attribute
attribute Manage- Manage-
(The
data types ment ment
configura-
utility utility
tion
Attribute Attribute
applies to
Definition Panel
all
Layout
attributes,
Definition
in all
clients)
Label Used to set Not Use the setLabel()
the label of available at display
an attribute this level. name on the
attribute
definition.
Mode The mode Not Not setMode()
in which the available at available at
attribute this level. this level.
will be
displayed.
There are 3
modes
available:
Create, Edit
and View

Limitations
Defining Discrete Set using OIRs / Providing Input Components for
Reference Attributes
OOTB, discrete sets are defined for TeamTemplate and Lifecycle Template
attributes in the OIRs rather than in the Type Manager. This is because these
attributes are reference attributes.
At present we do not have infrastructure support for displaying reference
attributes in the input mode. We will need to map each of the reference attributes
to a picker if this needs to be enabled. If there is a request from a customer for this
support, we could try of the OIR approach used for TeamTemplate and Lifecycle
Template attributes will work for that case.

734 Customization Guide


Checklist for Things to Add when Writing Attribute Customization
• Configuration points
• Effect of multiple configurations – what takes precedence, how they are
resolved
○ Hierarchical
○ Duplicate (when they are at the same level and scope)
• UI behavior
• Validation
○ In the UI
○ At the server

Calculated Attributes with Formula to Gather Multiple Values ay not


work without a DataUtility
Because some attributes are generated via a dataUtility, their value may not be
available to be added automatically to a calculated attribute where the formula
calls out the value to be used. In this case, the new attribute would also need a
dataUtility where the value can be put together properly

Presenting Information in the UI 735


Adding Custom Modeled Attributes to all
Table Views
This section details the steps required to make custom modeled attributes
available in the create table view user interface.
Prerequisite: You already have a class with custom modeled attributes. See
Attribute Customization on page 658 for more information.
1. Create a site specific file to describe the new class and its attributes.
• For example codebase\AvailableAttributesSite.xml
• Create this file and include content in the following format:
<?xml version="1.0" standalone="no"?>
<AvailableAttributes>

<Class name="<fully qualified class name>">


<Include name="<fully qualified super class name>"/>
<Attribute id="<attribute name>"/>

</Class>
</AvailableAttributes>

Example:
<AvailableAttributes>

<Class name="ext.myCompany.MyCompanyChangeIssue">
<Include name="wt.change2.WTChangeIssue"/>
<Attribute id="myCompanyString"/>
<Attribute id="myCompanyInt"/>
<Attribute id="myCompanyTime"/>
</Class>
</AvailableAttributes>
• Any attributes you include in this file will be available in all tables that
include that class.
2. Modify site.xconf with the following command to include the new file in the
attribute lookup.
xconfmanager -s
com.ptc.core.htmlcomp.createtableview.AvailableAttributesDigest
er.fileLocation=/com/ptc/core/htmlcomp/createtableview/Availabl
eAttributes.xml,AvailableAttributesSite.xml
3. Propogate the xconf changes with the following command
xconfmanager -p

736 Customization Guide


Attribute Tables
Objective
This documentation provides developers with the information required for
implementing the attributes table component for a given business object in
information page.
The Attribute Table component was developed to give the Windchill products
consistency for displaying all necessary attributes of any object in details page.
The component should also make developing attributes table much easier. Using
this component, a developer only needs to configure attributes tables page only,
while the main layout of the page is provided by the component.

Applicability
This documentation should be used by a developer who is responsible for
configuring the info page for some object in one of the Windchill products. This
design pattern shows how to configured and where the configuration should be
done for the attributes table.

Participants
The readers of this documentation should have a basic understanding of JSP, tag
libraries and JSTL.

Consequences
By following this documentation the configuration of all attributes table for any
business objects should be done in a consistent manner. This will make
maintaining these attributes table much easier and more manageable task.

Solution

Overview
The attributes table component was developed using the Windchill Client
Architecture. This component provides a common layout for an object’s attributes
as it is displayed in any of the Windchill products. Using the attributes table
component will provide consistency between all objects and Windchill products.

Presenting Information in the UI 737


What is the component
• Attributes table Image neededIt is a combination of a JSP, bean, taglib,
renderers and service call(s).
• It displays all the attributes and its value configured for a given object.
• Not yet implemented: It displays the classification attributes table for
WTParts.
• Follows user interface standards
• Supports customization requirements
The default attributes table implementation have been added for parts and
documents. However both these tables need to be reworked so that necessary or
required attributes can be configured.
For all the business objects that need to use the attributes table, the developer will
need to create a new JSP that is configured for your type. All the details links to
attributes table will lead to a servlet which will figure out which page to forward
to based on the object type.

Using the component

Create a JSP for your object type


• Creating a JSP on page 738
• Resgistering the JSP on page 739

Creating a JSP
Your attributes.JSP will have only the describeAttributesTable tag and list of
attribute names as id in describeProperty. Based on the configuration in the
describeAttributesTable, the showSoftAttribute.jspf component will render the
attributes table panel and its content.

738 Customization Guide


Here is the example of attributes.jsp for document object.
<jca:describeAttributesTable var="attributesTableDescriptor"
mode=”VIEW”>
<jca:describeProperty id="<Logical Form>" />
<jca:describeProperty id="<Logical Form>" />
</jca:describeAttributeTable>

The attribute values are based on logical attribute mapping using the mechanism
in place for type instances. For a given object type, you can see what the logical
attribute names are by using the LogicalAttributes.jsp. This JSP can be accessed
from a running Windchill build; http://<machine>/<Windchill-app-name>/meta/
LogicalAttributeReport.jsp

In the type input field, type the fully qualified class name and click Submit. This
should give you a listing of the attributes that can be used for the given object
type. Either the logical or the external form can be specified, although the logical
form is preferred.

Resgistering the JSP


For the info page servlet to know which JSP to forward to for your type, an entry
for your JSP needs to be specified in a properties file that is used by the type
based service. The default properties file for this is typedservices.properties which
can be found directly in codebase. The entries should be in the following format:
wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto
ry/Attributes/wt.doc.WTDocument/0=/netmarkets/jsp/document/attribu
tes.jsp

wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto
ry/Attributes/wt.part.WTPart/0=/netmarkets/jsp/part/attributes.jsp

Here is an example of the xcong format:


<!--Info page fragments, Resource is the filepath to a jsp fragment

Presenting Information in the UI 739


that will configure the info page -->

<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">

<Option requestor="wt.part.WTPart"
resource="/netmarkets/jsp/part/attributes.jsp"
selector="Attributes"/>

<Option requestor="wt.doc.WTDocument"
resource="/netmarkets/jsp/document/attributes.jsp"
selector="Attributes"/>

</Resource>

Windchill/src/typedservices.properties.xconf file is the default xconf file used for


type based application context lookups. For your type, you would create your own
xconf file within your module that targets typedservices.properties.

Sample Code

Example implementation for the attributesTableComponent


This is an example of how the attributes table could be configured for some object
type. However these steps reference to codebase locations only. These steps do not
include instructions for source placement or best practices for entering
information in xconf files or building of the content or entering in xconf files. This
is only to communicate the concepts for getting started.
1. Create a JSP file called attributes.jsp and place it in the following location in
your codebase.
codebase/netmarkets/jsp/part/

For now, just add the following content to the page


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>

<jca:describeAttributesTable var="attributesTableDescriptor"
mode="VIEW" id="view.setAttribute"
label="Attributes" scope="request">
<jca:describeProperty id="containerName" />
<jca:describeProperty id="name"/>
<jca:describeProperty id="number"/>
<jca:describeProperty id="creatorName" />

740 Customization Guide


<jca:describeProperty id="currentPrincipal" />
<jca:describeProperty id="cabinet"/>
<jca:describeProperty id="cabinetName"/>
<jca:describeProperty id="checkoutInfo.state" />
<jca:describeProperty id="comment"/>
<jca:describeProperty id="displayIdentifier"/>
<jca:describeProperty id="endItem"/>
<jca:describeProperty id="folderName"/>
<jca:describeProperty id="lifeCycleName" />
<jca:describeProperty id="usedBy"/>
<jca:describeProperty id="version"/>
<jca:describeProperty id="view" />
<jca:describeProperty id="viewName"/>
<jca:describeProperty id="owner.id"/>
<jca:describeProperty id="ALL_SOFT_SCHEMA_ATTRIBUTES"/>*
</jca:describeAttributesTable>

Also, Edit action can be launched with below steps. The step to initially
display can be set on request with this form.
startStep=<step id>

* “ALL_SOFT_SCHEMA_ATTRIBUTES” display all the global attributes


and its value.
2. Register your JSP so the info page servlet will know to forward to it.
Add the following entry into codebase/typedservices.properties:
wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFa
ctory/Attributes/wt.part.WTPart/0=/netmarkets/jsp/part/attribut
es.jsp
3. Test your new jsp. The icons from the Home page or from the Folders page
should lead to the new info page servlet. The URL will look something like
this:
http://<machine>/<WindchillAppName>/servlet/InfoPage?oid=OR:wt.
part.WTPart:62028

The servlet will look up which JSP to forward to in typedservices.properties.


You should see the list of attributes name and its value in Third Level
Navigation for attributes table.

Presenting Information in the UI 741


Icon Delegates
Objective
You want to author an IconDelegate to display icon for a Windchill object
type.

Background
The purpose of object icons is to allow the user to readily distinguish between
different Windchill business objects in the Windchill UI. Its possible to associate
an icon with a Modeled type while modeling the class. This icon will be used
when an object of this type is displayed. In case of subtypes, the Type and
Attribute Management utility allows the user to associate an icon to be used to
represent this subtype in the UI. If the icon specified is an invalid or blank, the
icon of the parent type is used. This behavior is accomplished using
IconDelegates.
However, there are cases where the icons are determined dynamically by other
factors, such as attributes on the object. The following table shows the OOTB
IconDelegates available for some Windchill Types.
Windchill Type IconDelegate
wt.part.WTPart com.ptc.windchill.enterprise.part.comm
ands.delegate.WTPartIconDelegate
wt.epm.EPMDocument wt.epm.identity.
EPMDocumentIconDelegate
wt.doc.WTDocument wt.doc.DocumentIconDelegate

If the user needs different icons on types (other than the OOTB) or for his own
modeled/subtypes, he needs to author custom IconDelegates for the respective
type.

Scope/Applicability/Assumptions
User is not supposed to author custom IconDelegates for types for which
OOTB IconDelegates exists.

Intended Outcome
User able to view the icons defined by his IconDelegate for the respective
Windchill type objects.

Solution
Author custom IconDelegate for Windchill type to specify your icon.

742 Customization Guide


Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Java
• Windchill Type Identifiers

Solution Elements
Element Type Description
<custom_IconDelegate>. java java Your IcondDelegate
Run time Location:
<Windchill>\codebase\*
Your xconf file xconf Register your IconDelegate
Run time Location:
<Windchill>\codebase\*

Procedure – Authoring Custom IconDelegate


Windchill UI deals with objects either in Persistable form or in TypeInstance
form and hence IconDelegates should be able to handle both the forms. The
attributes that participate in determining the icon is easily available if you have the
object in Persistable form. If the object is in a TypeInstance form and the
attributes are not available, then the TypeInstance has to be inflated to get the
attributes, which can degrade the performance. If its in a TypeInstance object,
the icon and tool tip for the icon are available as an SCA attribute, which is
defined in <Windchill>/codebase/LogicalAttributes.xml
<Class name="wt.fc.Persistable">
-------
<Property>
<LogicalForm>objectIcon</LogicalForm>
<ExternalForm>SCA|objectIcon</ExternalForm>
</Property>

<Property>
<!-- This attribute is populated by the SCA|objectIcon
function -->
<LogicalForm>objectTooltip</LogicalForm>
<ExternalForm>NPA|objectTooltip</ExternalForm>
</Property>

Presenting Information in the UI 743


Authoring the custom IconDelegate
1. You can extend either wt.fc.IconDelegate or an existing subclass of
wt.fc.IconDelegate.
2. There are few API’s that you need to over-ride, where you have to put your
icon determining logic.
a. These two API’s returns an IconSelector object, which holds the
information of the icon for the specific Windchill object.
API Signature Description
public IconSelector Get the standard selector for the
getStandardIconSelector() icon
throws WTException,
IllegalAccessException,
InvocationTargetException;
public IconSelector Get a selector for when the object is
getOpenIconSelector() opened (for example when a folder
is opened)
throws WTException,
IllegalAccessException,
InvocationTargetException;

b. This API returns the localized tooltip value that need to be shown for the
icon.
API Signature Description
public String getToolTip() The tooltip to be shown with the
icon.
c. This API is needed to handle TypeInstances. In the method, you have
to check whether the available TypeInstance has all the minimum
required attribute values to determine icon and tool tip. If not there is a
need to inflate the TypeInstance.
API Signature Description
protected Boolean inflateRequired() Inflate Required, if TypeInstance
doesn't have required attributes to
calculate the icon/tool tip.
@Override
protected boolean inflateRequired() {
boolean need = super.inflateRequired();
TypeInstance ti = getTypeInstanceObject();
if(ti != null && !need){
//check you necessary attributes in TypeInstance
// to determine to inflate it or not.

744 Customization Guide


}
}
return need;
}

d. This API is needed to handle TypeInstances. In the method, you have


to add all the attributes that drive icon/tool tip determination. This will
make sure that they are properly populated when you invoke
getStandardIconSelector() or getOpenIconSelector().
API Signature Description
protected void initAttributes Update <AttributeTypeIdentifier>
(Set<AttributeTypeIdentifier> with attributes that drive-
attributes) determining icon/tool tip.
@Override
protected void initAttributes(Set<AttributeTypeIdentifier>
attributes) {
super.initAttributes(attributes);
//add your attributes here
}

3. IconDelegate defines a static helper method to create


AttributeTypeIdentifier and TypeIdentifier objects that your
subclass can use. e.g.
AttributeTypeIdentifier NAME_ATI = getIdentifier("name",
"wt.part.WTPart");
TypeIdentifier WTPART_TI = getIdentifier("wt.part.WTPart",
null);

4. The getObject() API will convert the current TypeInstance to a


Persistable, if not available. Hence its usage should be avoided in favor of
getObject(false).

Coding Pattern
Many of the IconDelegate subclasses now use an internal "params" object to
encapsulate whether or not they are working with a Persistable or a
TypeInstance. The params object has simple properties that the icon
resolution logic can use, regardless of whether the properties were populated from
a Persistable or TypeInstance.
AttributeTypeIdentifier PERSONAL_CABINET_ATI =
getIdentifier("personalCabinet", "wt.folder.Cabinet");
TypeIdentifier CABINET_TID = getIdentifier("wt.folder.Cabinet",
null);

protected void initAttributes(Set<AttributeTypeIdentifier>


attributes) {
super.initAttributes(attributes);

Presenting Information in the UI 745


attributes.add(PERSONAL_CABINET_ATI);
}

private static class ObjectParams {

Cabinet cabinet = null;


TypeInstance ti = null;

ObjectParams(Cabinet cabinet){
if(cabinet != null)
this.cabinet = cabinet;
}
ObjectParams(TypeInstance ti){
if(ti != null)
this.ti = ti;
}
void reSetObject(Cabinet cabinet){
if(cabinet != null)
this.cabinet = cabinet;
}
boolean isPersonalCabinet(){
if(cabinet != null){
return (cabinet.isPersonalCabinet());
}else{
return (Boolean)ti.get(PERSONAL_CABINET_ATI);
}
}
}

protected boolean inflateRequired() {


boolean need = false;
TypeInstance ti = getTypeInstanceObject();
if(ti != null){
need = super.inflateRequired();
if(!need){
if(ti.get(PERSONAL_CABINET_ATI) == null){ // should contain
PERSONAL_CABINET_ATI
need = true;
}
}
}
return need;
}
private ObjectParams getObjectParams(){

ObjectParams object_params = null;

746 Customization Guide


WTObject obj = super.getObject(false);
TypeInstance ti = getTypeInstanceObject();
if (obj != null && obj instanceof Cabinet) {//Object is available
object_params = new ObjectParams((Cabinet)obj);
} else if(ti != null) {//TypeInstance is available
if(inflateRequired()){
obj = super.getObject(true);
if (obj != null && obj instanceof Cabinet) {
object_params = new ObjectParams((Cabinet)obj);
}else{
object_params = null;
}
} else {
object_params = new ObjectParams(ti);
}
}
return object_params;
}

public IconSelector getStandardIconSelector()


throws WTException, IllegalAccessException,
InvocationTargetException {
IconSelector icon = null;

ObjectParams object_params = getObjectParams();


if(object_params != null){
boolean is_personal_cabinet =
object_params.isPersonalCabinet();
if(is_personal_cabinet)
icon = new IconSelector(PERSONAL_ICON);
else
icon = new IconSelector(SHARED_ICON);
}
if (icon == null)
icon = super.getStandardIconSelector();
return icon;
}

Registering the custom IconDelegate


You need to register your custom IconDelegate in an xconf file and propagate
into the <Windchill>/codebase/service.properties file via
xconfmanager.
<Service context="default" name="wt.fc.IconDelegate">
<Option cardinality="duplicate" requestor="<your_type>"

Presenting Information in the UI 747


serviceClass="<your_IconDelegate>"/>
</Service>

748 Customization Guide


Creating Custom Graphical
Representations
Certain types of business information are intended for providing business insights
“at a glance” and are best represented graphically rather than as text. Windchill
uses graphical representations like icons to represent some of the information. You
may have custom attributes which, if represented graphically, makes your users
more efficient. You can create your own graphical representations if you find that
the existing three out-of-the-box graphical representations for attributes are not
sufficient for your needs.
The available out of the box the graphical representations are described in detail in
the Reference on page 766 section.

Objective
Scope/Applicability/Assumptions
Graphical representations can only be applied to calculated attributes. Particular
representations may only apply to calculated attributes of specific data types and
may only support a well-defined subset of the possible formula results. See the
Solution Elements on page 752 section for more info on the scope, configuration,
and limitations of the three out-of-the-box graphical representations.

Intended Outcome
When an attribute is configured with a custom graphical representation, it displays
as graphical throughout the product in all tables that support graphical attributes,
in information pages and wizards.
The following are examples of the three available out-of-the-box graphical
representations in various Windchill UIs:

Presenting Information in the UI 749


750 Customization Guide
Graphical representations are also supported in GWT based user interfaces:

Presenting Information in the UI 751


Solution
Create a new custom graphical representation and configure an attribute to use it.

Prerequisite Knowledge
To successfully create a new custom representation, it is helpful to have an
understanding of the following subjects:
• “Creating a New Attribute“ topic in the Windchill Help Center
• “Calculated Attribute Formulas” topic in the Windchill Help Center
• Constructing and Rendering a Table Using the JSP Framework on page 606
• Attribute Customization on page 658
• The Additional Resources on page 769 section below includes references to
more subjects.
• The “Graphical Attributes” topic in the Windchill Help Center contains
additional information on the three out-of-the-box graphical representations.
• Reference on page 766 contains design & implementation details on the three
available out-of-the-box graphical representations. This information can be
helpful when creating your custom graphical representation.

Overview of creating a custom graphical representation


The typical process for creating a custom graphical representation involves four
steps:
1. Create a custom server-side component that extends the
AbstractGraphicalComponent class.
2. Create the client-side JavaScript renderer for the new component.
3. Use the Type and Attribute Management utility to add a unique entry to the
“Graphical Attribute Representations” enumeration for your new
representation.
4. Add the xconf entry that connects your enumeration value with your
component class, and run xconfmanager to propagate the change.
These steps are fully explained the following sections.

Solution Elements
The following table lists the primary classes used to implement custom graphical
representations. Typically customizers need to extend
AbstractGraphicalComponent, and implement
GraphicalAttRepresentationHandler and GraphicalComponent.

752 Customization Guide


Reference on page 766 contains design & implementation details on the three
available out-of-the-box graphical representations. This information can be
helpful when creating your custom graphical representation.
Element Type Description
AbstractGraphical Java Class This is the abstract parent
Component class to use for all
graphical components.
GraphicalAttribu Java Class This is the data utility that
teDataUtility handles all graphical
representations. It is not
intended to be
customized.
GraphicalAttRepre Java Interface This is the interface that
sentationHandler must be implemented to
configure a new custom
graphical representation.
The interface defines the
types of calculated
attributes that the
representation handles.
GraphicalCompo Java Interface This is the interface that
nent must be implemented to
define and configure new
custom graphical
component. It extends
GraphicalAttRepre
sentationHandler.
Type and Attribute Management properties related to Graphical Attributes

Presenting Information in the UI 753


Parameter Default Possible Required? Description
Value values
Graphical None Percent No This property
Representation Complete is only
Progress Bar available on a
calculated
Traffic Light attribute. And
the options
vary per
datatype, for
example
Traffic Light is
only available
for Integer
datatype, but
Progress Bar
and Percent
Complete are
available for
Integer, Real
Number, and
Real Number
with Units
Graphical None No This property
Representation is also only
Parameters available on
calculated
attributes. It
allows extra
parameters to
be configured
per graphical
representation
as needed.
Some
representa-
tions, like
Traffic light
and Percent
Complete,
don’t need
extra

754 Customization Guide


Parameter Default Possible Required? Description
Value values
parameters.
Other options,
like Progress
Bar, require
this property to
be set to the
name of an
attribute which
contains the
parameters.
(See Progress
Bar on page
768Progress
Bar on page
768 for more
info)

Procedure – Creating a Simple Custom Graphical


Representation
To illustrate how to create a new custom graphical representation,
create a new “Multi State Icon Component”
The out-of-the-box “Traffic Light” graphical component (discussed in Traffic
Light on page 767) is an example of a Multi State Icon Component. It is possible
to easily create other custom graphical components that follow this model. For
example, a customer could create a traffic light type component with more states,
or they could create a new “Rain or Shine” graphical component. This describes
how to create the new “Rain or Shine” component next.

Create the “Rain or Shine” Custom Graphical Representation class


Your custom component class should extend the provided
MultiStateIconComponent class and define an implementation of
getIconComponent(). Typically this class will also define an enumeration
that contains the allowed values and images to be rendered.
Your “Rain or Shine” component might look like this:
public class RainOrShineComponent extends MultiStateIconComponent {

public enum RainOrShineEnum {


// Maps an integer to a specific .gif graphical representation
// All possible states supported are listed here

Presenting Information in the UI 755


RAIN(0, "com/mycompany/images/rain.gif", "Rain"),
SHINE(1, "com/mycompany/images/sunshine.gif", "Shine");

private final int key;


private final String image;
private final String tooltip;

private RainOrShineEnum(int key, String image, String tooltip) {


this.key = key;
this.image = image;
this.tooltip = tooltip;
}

@Override
public IconComponent getIconComponent() {
// create the icon component using the correct image path
final IconComponent component = new IconComponent(image);
// set the tooltip
component.setTooltip(tooltip);
return component;
}

@Override
public static RainOrShineEnum getElement(int key) throws WTException {
for (RainOrShineEnum tls : values()) {
if (key == tls.key) {
return tls;
}
}
LOGGER.error("Undefined RainOrShineState: " + key);
LOGGER.error("Change the formula to return one of the
following states: 0, 1");
throw new WTException("Undefined RainOrShineState: " + key);
}
}

@Override
public IconComponent getIconComponent(int key) throws WTException {
return RainOrShineEnum.getElement(key).getIconComponent();
}
}

Add an Entry to the Enumeration of Graphical Representations


Use the Type and Attribute Management utility to add an entry to the enumeration
of graphical representations. The enumeration is named “Graphical Attribute
Representations” and is in the system-level organizer named “PTC
Enumerations”. Remember the internal name of your entry. It will be used in the
next step. For this example, assume “rainOrShine” as the internal name of the new
entry.

756 Customization Guide


Create the xconf mapping for the component
Add an xconf entry that maps the internal name of your graphical representation’s
enumeration entry to the custom “RainOrShineComponent” class you
created above. For the rain or shine component the new entry might look like this.
Note the selector must match the internal name of the enumeration entry in the
previous section and the serviceClass must match the fully-qualified name of your
custom component class.
<Service name=
"com.ptc.core.lwc.common.graphicalatts.GraphicalAttRepresentationHandler">
<Option serviceClass="com.mycompany.RainOrShineComponent" requestor="null"
selector="rainOrShine" />
</Service>
Once you have updated the xconf file, you need to propagate it to the property file
by running XConfManager in a Windchill shell: “xconfmanager -pF” and then
restarting the Method Server.

Testing
1. First create a new calculated attribute in the Type and Attribute Management
utility (maybe on the Document or Part type).
2. Then, on this attribute, set the “Graphical Representation” property to “Rain
Or Shine”, and set the formula to 0 or 1.
3. Save your changes.
4. Navigate to an instance of this type in Windchill (or create a new instance).
Whenever this attribute appears in “view” mode in Windchill it is displayed as the
“rain.gif “or “sunshine.gif” image!

Creating a Fully-Custom Graphical Representation


The process for creating a fully-custom graphical representation is very similar to
the “Rain or Shine” example in the previous section. There are four steps:
1. Create a custom component that extends the
AbstractGraphicalComponent class.
2. Create the client-side JavaScript renderer for the new component.
3. Add an entry to the enumeration of graphical representations.
4. Add the xconf entry that connects your enumeration value with your
component class.
The differences from the simple “Rain or Shine” example above and a full
graphical representation are that in a full implementation your component class
must extend AbstractGraphicalComponent and implement
GraphicalComponent, not MultiStateIconComponent, and your
component is also responsible for handling the client-side rendering.

Presenting Information in the UI 757


Create the Custom Component
Your custom component needs to implement the one API in
GraphicalAttRepresentationHandler, three APIs from
GraphicalComponent, and one API from GuiComponent class.
• public boolean isValidForDatatype(final Class
datatype);
This GraphicalAttRepresentationHandler API is called by the
Type and Attribute Management utility to determine whether your graphical
representation is available for attributes with the specified datatype. For
example, if your representation only applies to integer-valued attributes, like
the traffic light example, the API would return true when datatype was
java.lang.Long and false otherwise.
• public GraphicalComponent newInstance(Object value,
Map<String, Object> metaData) throws WTException;
This GraphicalComponent API is called to create new instances of your
graphical component. The parameters include the value of the calculated
attribute that is to be displayed, and a map of the values that were specified in
the corresponding graphical representation parameters attribute. This method
should return a new instance of itself initialized with the specified parameters.
• public JSONObject toJSON() throws WTException;
This GraphicalComponent API is called to convert your graphical
component into the JSON object that is passed from the server to the client
where it is rendered. The choice of what to pass is entirely up to you. The
infrastructure adds one additional item named “comparable” to whatever this
method returns.
• public String getJSRendererName();
This GraphicalComponent API is called to determine the name of your
client-side renderer. This method should return the full name of the JavaScript
method that implements your client-side renderer. For the example below, this
function would return “XyzCorp.pieChart.renderer”.
• public Comparable getInternalValue()
This GuiComponent API is called to get the value used for sorting and
grouping in client-side tables. The returned value is included in the JSON
value passed to the client, in a field named “comparable”. This comparable
value is used for sorting.

758 Customization Guide


Create the Client-Side Renderer
The client-side of your custom graphical representation is a JavaScript renderer.
This piece of code uses the JSON value produced by the component in the
previous step to produce the final HTML representation.
It is important to avoid name conflicts in the JavaScript code. So it is best practice
to put all of your JavaScript code in a private name space. For our example, let’s
assume your work for Xyz Inc. and you are implementing a new pie chart
graphical representation. Your JavaScript name space could be
“XyzCorp.pieChart”.
The skeleton of your renderer should look like this:
XyzCorp = {};
XyzCorp.pieChart = {};

XyzCorp.pieChart.renderer = function(table, column, row) {


var data = jsca.columns.getCellValue(column, row);

return “<the html value as a string>”;
}

XyzCorp.pieChart.renderer.exportRenderer = function(table, column, row) {


var data = jsca.columns.getCellValue(column, row);

return <the export value>;
};

XyzCorp.pieChart.renderer.exportRendererForGWT = function(data) {

return <the export value>;
};

XyzCorp.pieChart.renderer.searchFunc = function(table, column, row) {


var data = jsca.columns.getCellValue(column, row);

return “<the search value as a string>”;
};

XyzCorp.pieChart.renderer.groupFunc = function(table, column, row) {


var data = jsca.columns.getCellValue(column, row);

return “<the group label as a string>”;
};

Presenting Information in the UI 759


Note
• The first two lines create the name space. Each of the following functions
implements a piece of the client-side UI for your graphical representation. The
first thing each of these functions does is retrieve into “data” the JSON value
that was produced on the server. This value is cached on the client and
fetching it does not create client-server traffic. Then each function computes a
return value to reflect its aspect of the UI. If there was a serious problem on
the server, the value of data may be a simple string, not the expected JSON
value. So, it is typical for these functions to first check whether the value is as
expected. For example:
if (data && data.myExpectedField1) {
… handle expected values …
} else {
… handle the server-generated error string …
}

• The first and main “renderer()” function produces the HTML that
represents this element on the rendered page. If the server sent an error string,
it should be returned as the result of this function. Otherwise, you can use the
JSON value in data to generate whatever HTML is desired.
• The second “exportRenderer()” function returns the string value to be
exported for this element. This export value may appear in any of the files
produced by the “Export List to File” action in the Windchill UI.
• The third “exportRendererForGWT()” function returns the string value
to be exported for this element in GWT, Cadx, and PSB based UIs. This export
value may appear in any of the files produced by the “Export List to File”
action in the Windchill GWT-based UIs.
• The fourth “searchFunc()” function returns the string value that
represents this element during search-in-table operations. If a search string
matches any substring of this function’s return value, the corresponding
element is included in the search results.
• Finally, the fifth “groupFunc()” function returns the label that is used to
identify the group containing this element. When a user uses the table column
header menu to “Group By This Field”, the table is sorted and any contiguous
rows of the table having the same group label is clustered together using that
label to identify the group.

760 Customization Guide


• Notice that the exportRenderer, searchFunc, and groupFunc
functions are all defined on the renderer function,
XyzCorp.pieChart.renderer. This naming convention is required for
those functions to take effect. If you try to name your functions differently or
use a different prefix, they are ignored.

Add an Entry to the Enumeration of Graphical Representations


Just like the simple “Rain or Shine” example above, use the Type and Attribute
Management utility to add an entry to the enumeration of graphical
representations. The enumeration is named “Graphical Attribute Representations”
and is in the system-level organizer named “PTC Enumerations”. Remember the
internal name of your entry. It will be used in the next step. For this example,
assume “pieChart” as the internal name of the new entry.

Create the xconf mapping for the component


Add an xconf entry that maps the internal name of your graphical representation’s
enumeration entry to the custom component class you created above. For our
example pie chart the new entry might look like this. Note the selector must match
the internal name of the enumeration entry in the previous section and the
serviceClass must match the fully-qualified name of your custom component
class.
<Service name=
"com.ptc.core.lwc.common.graphicalatts.GraphicalAttRepresentationHandler">
<Option serviceClass="com.XyzCorp.PieChartComponent" requestor="null"
selector="pieChart" />
</Service>
Again, once you have updated the xconf file, you need to propagate it to the
property file it by running XConfManager in a Windchill shell:
“xconfmanager -pF” and then restarting the Method Server.

Procedure – Supporting Graphical Attributes in a


Configurable Table
Most tables in the Windchill UI are configurable tables and support graphical
attributes automatically out of the box with no additional work required.
Any table that implements the ConfigurableTableBuilder interface
(generally done by extending AbstractConfigurableTableBuilder) is a
configurable table.
See Graphical Attributes Example Configurable Table on page 764 for details on a
provided example of a configurable table.

Presenting Information in the UI 761


Procedure – Supporting Graphical Attributes in a
Non-Configurable Table
If a table does not implement ConfigurableTableBuilder, then it is a non-
configurable table and an extra step is required to enable it to contain graphical
attributes.
To enable graphical attribute support in a non-configurable table, you must specify
the types that are displayed in that table in your table builder using the
setTypes API on the TableConfig.
ComponentConfigFactory factory = getComponentConfigFactory();
TableConfig table = factory.newTableConfig();
table.setTypes("org.example.FakeLiterature", "org.example.FakeNovel");
This single line of code is all that is required to enable the table to display
attributes as graphical attributes. Graphical attributes are added to the
TableConfig in exactly the same way as any other attribute.
Be as thorough as possible in creating the type list. All types that are in the table
should be included in the type list. All subtypes should be listed out separately and
individually as in the example above. FakeNovel is a sub type of
FakeLiterature, but both must be listed explicitly. Listing only the
supertypes will not be sufficient when the graphical attribute is actually on a sub
type. Even if not all types have graphical attributes when you are creating the list,
later those types may have graphical attributes and then they will not work if the
type is not in the list. It is best to make a comprehensive list from the beginning.
If a graphical attribute is added to a non-configurable table that has not been
updated to support graphical attributes (or a non-configurable table that does not
contain the right type in its’ type list), then the attribute behaves as though it is not
graphical in that table. For example, a traffic light attribute would show as an
integer 0, 1, 2 or 3 rather than as the correct image or blank.
See Graphical Attributes Example Non-Configurable Table on page 765 for
details on a provided example of non-configurable table.

Limitations
The internal names of graphical attributes must be used consistently throughout
the system. Once you have chosen to use an attribute internal name for a graphical
attribute on one type you should only use that attribute internal name for the same
kind of graphical attribute anywhere you use it in the system.
If you reuse the same internal name for different purposes in this way you will see
unexpected results where sometimes you do not get the graphical representation
you expect or you get a graphical representation where you were not expecting
one at all, or you get errors in the UI.

762 Customization Guide


An attribute internal name must not be used across types for a mixture of
graphical and non-graphical attributes. For example, you create an attribute named
<myGraphicalAttr> on a document and make it a traffic light. You should
not then create an attribute named <myGraphicalAttr> on part and make it
an integer. Similarly you should not mix graphical attribute types with one internal
name. You should not create an attribute called <myGraphicalAttr> on
another type that is using a graphical representation other than traffic light.
Making mixed use of an attribute internal name is not supported.

Performance Considerations
Please be aware that since graphical representations are rendered throughout the
Windchill user interface, they have the potential to impact the performance of
rendering attributes in the UI. In particular if you define many graphical attributes
and then create a custom table view that contains many columns of graphical
attributes, rendering performance of the table may potentially suffer.
For this reason it is recommended to keep performance in mind as you implement
your custom graphical representation.

Customization Sample Code


There are example graphical attributes and example tables that support graphical
representations.
There are two example tables in the customization area of Windchill that display
graphical attributes. The graphical attributes are defined on the example sub types
of Part, called “Novel” and “Slider”. Those example types and some example
instances of those types are loaded automatically when the site admin visits a
customization example that needs them.
You will see the instances of the example types in the configurable and non-
configurable example tables available in the Windchill product by navigating to
Customization ▶ Component Catalog ▶ Graphical Attributes.
The “exampleTrafficLight” calculated integer attribute is configured as a
graphical attribute on both Novel and Slider types (subtypes of Document/
Literature and Part/Widget). Both attributes are configured with the Graphical
Representation of “Traffic Light” and with the formula
state.state=="INWORK"?1:((state.state==
"CANCELLED")?0:2)
This means when the object is “in work” the traffic light is yellow, when it is
“cancelled” the traffic light is red, anything else (ie. “Released”) and the traffic
light is green.

Presenting Information in the UI 763


Similarly the “exampleProgressBar” and
“examplePercentComplete” attributes are configured to display as a
progress bar and as a percent complete respectively.

Graphical Attributes Example Configurable Table


http://<hostName>/<webApp>/app/#ptc1/comp/
carambola.graphicalAttrsConfigExample

This example shows how graphical attributes work in a configurable table.


Configurable tables support graphical attributes by default so no extra work is
required.

Location of Example
This example can be viewed in the Windchill product by navigating to
Customization ▶ Component Catalog ▶ Graphical Attributes ▶ Examples section ▶
Graphical Attributes in Configurable Table Example

Note
If these options are not visible, you must enable the Customization UI. See
“Enable Customization Utilites” in Customization Tools Overview on page
404 for more information.

764 Customization Guide


Example FIles
Files used in this example can be found in the Carambola source tree:
• src/com/ptc/mvc/builders/carambola/table/
CarambolaGraphicalAttributesConfigurableExampleTable
Builder.java
• src/com/ptc/mvc/builders/carambola/table/
CarambolaGraphicalAttributesExampleTableDataBuilder.
java
• src/loadFiles/customization/LiteratureSoftTypes.xml
• src/loadFiles/customization/WidgetSoftTypes.xml
• src_web/config/actions/Carambola-actions.xml

Graphical Attributes Example Non-Configurable Table


http://<hostName>/<webApp>/app/#ptc1/comp/
carambola.graphicalAttrsNonConfigExample

This example shows how to make a non-configurable table support graphical


attributes by using the setTypes API.

Location of Example
This example can be viewed in the Windchill product by navigating to
Customization ▶ Component Catalog ▶ Graphical Attributes ▶ Examples section ▶
Graphical Attributes in Non Configurable Table Example

Note
If these options are not visible, you must enable the Customization UI. See
“Enable Customization Utilites” in Customization Tools Overview on page
404 for more information.

Presenting Information in the UI 765


Example Files
Files used in this example can be found in the Carambola source tree:
• src/com/ptc/mvc/builders/carambola/table/
CarambolaGraphicalAttributesExampleTableBuilder.java
• src/com/ptc/mvc/builders/carambola/table/
CarambolaGraphicalAttributesExampleTableDataBuilder.
java
• src/loadFiles/customization/LiteratureSoftTypes.xml
• src/loadFiles/customization/WidgetSoftTypes.xml
• src_web/config/actions/Carambola-actions.xml

Reference
This section contains details on the three out-of-the-box graphical representations.
The information in this section is provided as background details on how the three
out-of-the-box graphical representations (Traffic Light, Progress Bar, and Percent
Complete) are configured and implemented. This information can be valuable
when creating your own custom graphical representation.
The diagram below is a partial representation of how these classes have been
extended to implement the OOTB graphical representations.

766 Customization Guide


Traffic Light
Solution Elements
The code specific to the Traffic Light representation includes:
Element Type Description
MultiStateIconCom Java Class This is the abstract parent
ponent class used for creating
custom Multi State Icon
graphical representations.
This abstract class
extends
AbstractGraphical
Component.
TrafficLightCompo Java Class This is the class that
nent defines and supports the
out of the box graphical
representation of “Traffic
Light.” It is a subclass of
AbstractMultiSta
teIconComponent
and defines a four-state
enumeration allowing
administrators to
configure an attribute to
display as a red, yellow or
green traffic light, or the
fourth state of blank.
This component leverages
the existing
IconComponent,
which in turn utilizes the
jsca.columns.ima
geRenderer JS
renderer to actually
render the multiple icons
of the traffic light.

The TrafficLightComponent is an example of a Multi-State Icon


Component. It implements a 4-state enumeration where one of the states simply
displays a blank. This is a good example to look at when implementing a custom
subclass of MultiStateIconComponent (which is explained in Procedure –
Supporting Graphical Attributes in a Non-Configurable Table on page 762).

Presenting Information in the UI 767


This component resides in the
“com.ptc.core.components.rendering.guicomponents.Traffi
cLightComponent” class.

Progress Bar
Solution Elements
The code specific to the Progress Bar representation includes:
Element Type Description
ProgressBarCompo Java Class This class defines and
nent supports the out of the
box graphical
representation of
“Progress Bar.” It is a
subclass of
AbstractGraphical
Component. Unlike the
traffic light, this
component does not
leverage an existing
component, so it also
defines a new JavaScript
renderer (called
PTC.progressBar.
renderer).
progressBarRender JS Class This class defines the
er.jsfrag JavaScript renderer for
the progress bar,
converting the JSON
containing the progress
meta-data into the
corresponding HTML
(with an appropriate
tooltip).

768 Customization Guide


Percent Complete
Solution Elements
Element Type Description
PercentComplete Java Class This is the class that
Component defines and supports the
out of the box graphical
representation of “Percent
Complete.” It is a
subclass of
ProgressBarCompo
nent. Because this
graphical representation
leverages the
ProgressBarCompo
nent, it also utilizes the
PTC.progressBar.
renderer JS renderer.

Additional Resources
Related Package/Class Javadoc
• AbstractGraphicalComponent
• GraphicalAttributeDataUtility
• GraphicalAttRepresentationHandler
• GraphicalComponent
• MultiStateIconComponent
• MultiStateIconEnum
• PercentCompleteComponent
• ProgressBarComponent
• TrafficLightComponent

Presenting Information in the UI 769


UI Validation
Objective
You want to hide an action or attribute in the UI based on some context
information.
• You want to determine whether or not an action selected in the UI should be
allowed to proceed based on some context information.
• You want to determine whether or not a user can proceed to the next step in a
wizard or whether the entire wizard may be submitted, based on the data
entered by the user in that wizard.

Background
UI Validation is intended to simplify the experience of the Windchill end-user.
There are three categories of UI Validation that will each be discussed in further
detail in this document.
• Pre-Validation
• Post-Select-Validation
• Post-Submit Validation

Pre-Validation
The first category of UI Validation is referred to as Pre-Validation. This is the
category of validation that most people will first associate with UI Validation. Pre-
Validation is a term that describes the process of determining whether or not a UI
Component should be available in the UI. An example of Pre-Validation would be
disabling the “check-in” action for an object that is not checked-out. Pre-
Validation can be applied to both actions and attributes in the UI. Of the three
types of UI Validation, this type is the most often-used.

Post-Select Validation
A second category of UI Validation is Post-Select Validation. Post-Select
Validation is the process of determining whether or not an action should be
allowed to proceed once it is selected in the UI. An example of post-select
validation would be displaying an error message and not allowing the checkout to
proceed if a user tries to perform a checkout on an object that is already checked
out. Post-Select Validation applies only to actions.

Post-Submit Validation
The final category of UI Validation is Post-Submit Validation. This type of
validation is used exclusively in wizards or other forms where users enter data. An
example of Post-Submit Validation would be stopping a user from moving to the

770 Customization Guide


next step in a wizard because the data they’ve entered in the current step is
invalid. Post-Submit Validation applies only to wizard steps and wizard
submissions.

Scope/Applicability/Assumptions
• Pre-Validation - Suppose you want to hide an action in the UI from users who
are not members of the current container’s team.
• Post-Select Validation - After a user selects an action, you want to determine
whether or not the target object is in a certain lifecycle state before allowing
the action to proceed.
• Post-Submit Validation - After a user enters data in the first step of a wizard
and tries to navigate to the next step, you want to determine whether or not the
information entered on the first step is valid before allowing them to proceed.

Intended Outcome
• Pre-Validation - Before the page is rendered, you are able to determine
whether or not the user is a member of the current container’s team. If not, the
action is not displayed on the page.
• Post-Select Validation - After the user invokes the action, you are able to
check the target object’s lifecycle state. If the state is not the state you require,
you can display a message to the user, and the action is not performed.
• Post-Submit Validation - When the user clicks “next” on the wizard, you get
the data entered in the current step and are able to determine whether or not it
is adequate to allow the user to proceed to the next step. If the data is
inadequate or invalid, you can display a message to the user and not allow
them to proceed to the next step.

Solutions
• Pre-Validation - Determine whether the business logic is specific to a single
action or attribute, or if the same logic could apply to multiple actions or
attributes. If the logic is specific to a single UI Component (action or
attribute), add the logic to a Validator. If the logic could apply to multiple UI
Components, add the logic to a Filter. Finally, associate the Validator or Filter
with the UI Component to ensure that the business logic is applied to that
component.
○ Pre-Validation in a Validator - Implement the performFullPreValidation()
and performLimitedPreValidation() methods in a Validator to contain the
desired business logic.

Presenting Information in the UI 771


○ Pre-Validation in a Filter - Implement the preValidateAction method in a
Filter to contain the desired business logic.
• Post-Select Validation - Implement the validateSelectedAction() and
validateSelectedMultiSelectAction() methods in a Validator to define the
desired business logic, and associate the Validator with the action.
• Post-Submit Validation - Implement the validateFormSubmission() method in
a Validator to define the desired business logic, and associate the Validator
with the wizard step or the entire wizard.

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of the following:
• The actions framework in the Windchill client architecture.
• The Application Context or service.properties mechanism for registering
delegates.
• A basic familiarity with the NmCommandBean and its methods will be
helpful.
• The validation service is very generic in nature. It does not provide the APIs
you’ll need in order to determine whether or not something is valid. The
service will provide your validators or filters with the context data and form
data you need to determine whether or not a UI Component is valid. But you
will need to know what to do with that data in order to apply your validation
business logic.

772 Customization Guide


Solution Elements
In addition to the solution elements involved in UI Validation, this section also
contains some definitions of key terms (in bold italic).
Element Type Description
StandardUIComponentValida- Java class Often referred to as the
tion Service validation service. This is the
service class that controls UI
Validation. It receives validation
requests from the client
infrastructure and delegates to
the appropriate validators and
filters for validation results. It
then passes the validation results
back to the client infrastructure.
Customizers and application
developers should not have to
interact directly with this class.
UIValidationKey Java class Often referred to as a validation
key. A UIValidationKey is used
to identify the UI Component
being validated. You can think of
a UIValidationKey as having a
one-to-one relationship with an
action or attribute.
UIValidationCriteria Java class Often referred to as the
validation criteria.
The UIValidationCriteria is a
bean class that contains the
context (request, session) data
which is passed from the client
infrastructure to the validators
and filters via the validation
service.
Most of the content in the
UIValidationCriteria is taken
directly from the
NmCommandBean, although the
objects are typically returned as
WTReferences, as opposed to
NmOids.
UIValidationResult Java class Often referred to as a validation
result.

Presenting Information in the UI 773


Element Type Description
A UIValidationResult represents
one unit of validation. In other
words, it associates a validation
status with a UI Component
(action or attribute). In cases
where validation is being
performed for the same action on
multiple objects, a
UIValidationResult can be
associated with each object.
UIValidationResultSet Java class Often referred to as a result set.
A UIValidationResultSet is just a
collection of UIValidationResult
objects. The result sets are used
in situations where multiple
validations are being performed
at the same time. For example, if
a validator was doing a pre-
validation check for the same
action on multiple objects, it
could aggregate the validation
results for each of the objects
into a UIValidationResultSet.
UIValidationStatus Java class Often referred to as validation
status.
This is an enumeration used to
determine if or how a UI
component should be displayed
in the UI. For example, there are
values to indicate that an action
should be hidden, that an action
should be disabled, or that an
action should be enabled.
UIValidationFeedbackMsg Java class Often referred to as a feedback
message.
This is a message that can be
associated with a validation
result. It is only used for post-
select validation and post-submit
validation. Any feedback

774 Customization Guide


Element Type Description
messages associated with
validation results returned by
pre-validation will be ignored.
Feedback messages can have
different feedback types
(FeedbackType.java) associated
with them to indicate whether
they are, for example, error
messages, warning messages, or
info messages.
UIComponentValidator Java This is the interface that all
interface validator implementations need
to implement. However,
validators should not directly
implement this interface. Rather,
they should extend
DefaultUIComponentValidator.
Each UI component can have
zero or one validators associated
with it. Typically, a validator will
contain logic specific to a single
UI component. For more generic
validation logic that applies to
multiple UI components, a filter
is typically used.
Validators are called by the
validation service to determine
the validation status for a
specific UI component.
Customizers and application
developers should not have to
interact directly with this class.
DefaultUIComponentValidator Java class This is a default implementation
of the UIComponentValidator
interface. All validator
implementations should extend
this class.
ValidationFilter Java This is the interface that all filter
interface implementations need to
implement. However, filters
should not implement this
interface directly. Rather, they

Presenting Information in the UI 775


Element Type Description
should extend
DefaultSimpleValidationFilter or
DefaultUniversalValidationFil-
ter.
Each UI component can have
zero to many filters associated
with it. Typically, a filter will
contain generic validation logic
that could apply to multiple UI
components. For validation logic
that is specific to a single UI
component or a small set of UI
components, a validator is
typically used.
There are two categories of
filters: simple filters and
universal filters. Simple filters
are applied on a component-by-
component basis. In other words,
you have to choose which UI
components the logic in a simple
filter will apply to. Conversely,
universal filters are applied to all
UI components, which means
you have to choose which UI
components the logic in a
universal filter does not apply to.
Filtersare called by the
validation service to determine
the validation status for a
specific UI component.
Customizers and application
developers should not have to
interact directly with this class.

776 Customization Guide


Element Type Description
SimpleValidationFilter Java This is the interface that all
interface simple filter implementations
need to implement. However,
simple filters should not
implement this interface directly.
Rather, they should extend
DefaultSimpleValidationFilter.
Customizers and application
developers should not have to
interact directly with this class.
UniversalValidationFilter Java This is the interface that all
interface universal filter implementations
need to implement. However,
universal filters should not
implement this interface directly.
Rather, they should extend
DefaultUniversalValidationFil-
ter.
Customizers and application
developers should not have to
interact directly with this class.
DefaultSimpleValidationFilter Java class This is a default implementation
of the SimpleValidationFilter
interface. All simple filter
implementations should extend
this class.
DefaultUniversalValidationFilter Java class This is a default implementation
of the UniversalValidationFilter
interface. All universal filter
implementations should extend
this class.
UIComponentSolutionGroup Java This is an interface that all
interface solution group implementations
need to implement.
A solution group is a special
type of validator that is used for
pre-validation based on the
installed solutions. For example,
if a given action should not be
available if Windchill
ProjectLink is not installed, that
logic should be defined in a
solution group.

Presenting Information in the UI 777


Element Type Description
*actions.xml XML file(s) There are multiple “satellite”
versions of actions.xml files
(typically one per module),
which contain action definitions.
It is also in these files that we
configure actions to include
simple filters, and exclude
universal filters.
*service.properties.xconf XConf file There are multiple “satellite”
(s) versions of service.properites.
xconf files (typically one or
more per module), which contain
class delegate registry entries.
These files are where you
register your validators, filters
and solution groups so that the
validation service knows where
to find them.

778 Customization Guide


Pre-Validation Sequence
The pre-validation sequence begins with the client infrastructure (typically, but not
exclusively, the StandardNmActionService) sending a list of UI components to the
validation service. The expectation is that for each of those UI components, the
validation service will return a validation result indicating the display status for
the UI component. Each UI component is represented by a validation key. It is
also expected that the Client Infrastructure passes context (session, request, or
form) data to the validation service inside of a validation criteria object.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).

Once the validation service receives the validation request from the client
infrastructure, the validation service iterates through each of the validation keys,
and performs several tasks to determine the validation status for each of the keys.
The first such task that the validation service performs is to see whether or not a
given validation key represents a component that should be hidden, based on the
PTC solutions that are installed. This is accomplished by referencing a cache of
invalid validation keys that is created when the validation service is first started.
To create the cache, the validation service simply calls all registered solution
groups and asks for a list of invalid validation keys from each of them, based on
the installed solutions.

Presenting Information in the UI 779


If the cache of invalid solution-based keys contains the current validation key, the
validation service sets the component’s status to “hidden” and does not perform
any additional validation on the component. Otherwise, if the cache of invalid
solution-based keys does not contain the current validation key, the validation
service continues with its pre-validation checks.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. For each validation key, the validation service performs a series of tasks to
determine the validation status for that key. The tasks are executed in the
following order:
a. Check to see if the validation key is in the list of invalid keys for the
installed solution set.
The second pre-validation check performed by the validation service is to see
whether or not the component is hidden or disabled by the role-based UI service.
The role-based UI service was introduced in 8.0 as a way for admin users to
configure the display of UI components based on a user’s role. With the
introduction of the UI Validation Service in 9.0, the role-based UI service has
become a special delegate of the UI Validation Service.
If the role-based UI service returns a status of “hidden” or “disabled”, the
validation service sets the component’s status correspondingly and does not
perform any additional validation on the component. Otherwise, if the role-based
UI service returns an “enabled” status, the validation service continues with its
pre-validation checks.

780 Customization Guide


Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. For each validation key, the validation service performs a series of tasks to
determine the validation status for that key. The tasks are executed in the
following order:
a. Check to see if the validation key is in the list of invalid keys for the
installed solution set.
b. Check to see if the role-based UI service was configured to disable or
hide the component.

Assuming the role-based UI service says the component should be enabled, the
validation service will next check to see if any filters are associated with the UI
component.
To determine which filters should be applied to a UI component, the validation
service references some additional cached data that is stored when the validation
service is first started. The first cache referenced contains a list of all registered
universal filters. When a filter is defined and registered as a universal filter, it is
automatically applied to all UI components by default. If any universal filters are
found in this cache, they are automatically added to the list of filters that will be
applied to a given UI component.
Although universal filters are applied to all UI components by default, there is
support for configuring actions to ignore individual universal filters. (Currently,
there is no similar support available for configuring attributes to ignore universal

Presenting Information in the UI 781


filters, meaning that any universal filter will always be applied to all attributes.) If
you want to configure an action to ignore a universal filter, you do so in the
action’s definition in an actions.xml file. When the validation service is started, a
second cache is created containing a map of actions and any universal filters they
are configured to ignore. If an entry is found in this cache for a given action, the
universal filters that are supposed to be ignored will be removed from the list of
filters to be applied to the UI component.
Finally, the validation service references a third cache to determine any additional
filters that should be applied to a UI component. This third cache is a map that
associates actions with simple filters. A filter that is defined and registered as a
simple filter must be explicitly associated with an action in order for it to be
applied to any actions. (Currently, there is no support for associating a simple
filter with an attribute.) If you want to configure an action to use a simple filter,
you do so in the action’s definition in an actions.xml file. When the validation
service is started, this third cache of actions and associated simple filters is
created.
To summarize, the algorithm used by the validation service to determine which
filters should be applied to a given UI component, you could use the following
formula:
Filters per component = all universal filters – ignored universal filters + associated
simple filters
Once the list of filters is established, the validation service calls each of the filters
to determine the validation status for the UI component. Please note that the order
in which the filters are called can not be guaranteed. If any of the filters return a
validation status of “hidden” or “disabled”, the validation service sets the
component’s status correspondingly and does not perform any additional

782 Customization Guide


validation on the component. Otherwise if all of the filters applied to a given UI
component return an “enabled” status, the validation service continues with its
pre-validation checks.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. For each validation key, the validation service performs a series of tasks to
determine the validation status for that key. The tasks are executed in the
following order:
a. Check to see if the validation key is in the list of invalid keys for the
installed solution set.
b. Check to see if the role-based UI service was configured to disable or
hide the component.
c. Check to see if any of the filters associated with the UI component
indicate that the component should be disabled or hidden.

Presenting Information in the UI 783


(See the diagram on the following page for additional details.)If none of the filters
indicate that a UI component should be disabled or hidden, the final check
performed by the validation service for a given UI component is to check to see if
there is a validator associated with the UI component.
A validator is associated with a UI component by creating an entry in a service.
properties.xconf file that links the action id (for actions) or the descriptor id (for
attributes) to the class name of the validator class that should be used for that
component.
If there is not a validator registered for the UI component, the component is
enabled. Otherwise, if there is a validator associated with the UI component, the
validation service calls that validator to get a validation status for the UI
component.

784 Customization Guide


Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. For each validation key, the validation service performs a series of tasks to
determine the validation status for that key. The tasks are executed in the
following order:
a. Check to see if the validation key is in the list of invalid keys for the
installed solution set.
b. Check to see if the role-based UI service was configured to disable or
hide the component.
c. Check to see if any of the filters associated with the UI component
indicate that the component should be disabled or hidden.
d. Get the validation status from the validator, if there is one associated with
the UI component.

(See the diagram on the following page for additional details.)At this point, the
validation service has completed its validation checks for each UI component. If
the client infrastructure passed a single UI component to the validation service to
be pre-validated, the validation service will return a single validation result to the
caller. If multiple UI components were passed to the validation service for pre-

Presenting Information in the UI 785


validation, the validation service will organize the validation results for each
component into a validation result set, which contains one result per UI
component. The validation result set is then returned to the caller.

786 Customization Guide


Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. For each validation key, the validation service performs a series of tasks to
determine the validation status for that key. The tasks are executed in the
following order:
a. Check to see if the validation key is in the list of invalid keys for the
installed solution set.
b. Check to see if the role-based UI service was configured to disable or
hide the component.
c. Check to see if any of the filters associated with the UI component
indicate that the component should be disabled or hidden.
d. Get the validation status from the validator, if there is one associated with
the UI component.
3. Return the validation result or validation result set to the client infrastructure.

Presenting Information in the UI 787


Post-Select Validation Sequence
Conceptually, post-select validation occurs immediately after a user invokes an
action in the UI. In reality, however, post-select validation actually takes place
when the target page is being rendered. In other words, there is logic in begin.jspf
(code that is included on every JSP page authored in the Windchill Client
Architecture) that will call the validation service to determine whether or not the
page should be rendered before actually rendering it.
Validators are the only accepted locations for post-select validation logic. Unlike
pre-validation, there is no interaction with the solution groups, role-based UI
service, or filters for post-select validation. Therefore, the sequence for post-select
validation is much simpler than for pre-validation.
First, the client infrastructure calls the validation service, passing the action
corresponding to the page being rendered (this action is represented by a
validation key). Along with the action, the client infrastructure passes the context
data in the form of a validation criteria instance.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).

After receiving a post-select validation request from the client infrastructure, the
validation service checks to see if there is a validator associated with the specified
action.
As is the case with pre-validation, a validator is associated with an action by
creating an entry in a service.properties.xconf file that links the action id to the
class name of the validator class for that action.

788 Customization Guide


If there is not a validator registered for the action, the user is permitted to perform
the action. Otherwise, if there is a validator associated with the action, the
validation service calls that validator to get a validation status for the action.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. The validation service checks to see if there is a validator associated with the
action. If so, it calls the validator to get the validation status (permitted or
denied) for the action.

After the validator returns its validation result, the validation service simply
passes along the validation result returned by the validator to the client
infrastructure. The client infrastructure will check to see whether that status is
“permitted” or “denied”. If the status is “permitted”, the page or wizard is

Presenting Information in the UI 789


displayed. If the status is “denied”, the user is redirected to the previous page, and
if the validator returned a message indicating why the action was denied, that
message is displayed to the user.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. The validation service checks to see if there is a validator associated with the
action. If so, it calls the validator to get the validation status (permitted or
denied) for the action.
3. The validation service passes the validation status (wrapped in a validation
result) from the validator to the client infrastructure, which either displays the
target page/wizard, or brings the user back to the page where the action was
invoked.

790 Customization Guide


Post-Submit Validation Sequence
Post-submit validation occurs when a user navigates from one step to another in a
wizard, or when a user submits the entire wizard.
Validators are the only accepted locations for post-submit validation logic Unlike
pre-validation, there is no interaction with the solution groups, role-based UI
service, or filters for post-submit validation. Therefore, the sequence for post-
submit validation is much simpler than for pre-validation. In fact, it is nearly
identical to the sequence for post-select validation.
First, the client infrastructure calls the validation service, passing the id associated
with the “Next” or “OK” wizard action (this id is represented by a validation key).
Along with the validation key, the client infrastructure passes the context data in
the form of a validation criteria instance.

Key
1. The Client Infrastructure calls the validation service, passing an id associated
with a wizard's "Next" or "OK" action (represented by a validation key), and
the context data (represented by a validation criteria instance).

After receiving a post-submit validation request from the client infrastructure, the
validation service checks to see if there is a validator associated with the wizard’s
“Next” or “OK” action.
As is the case with pre-validation and post-select validation, a validator is
associated with a wizard’s “Next” or “OK” action by creating an entry in a
service.properties.xconf file that links the action id to the class name of the
validator class for that action.

Presenting Information in the UI 791


If there is not a validator registered for the action, the user is permitted to move to
the next step or submit the entire wizard. Otherwise, if there is a validator
associated with the “Next” or “OK” action, the validation service calls that
validator to get a validation status for the action.

Key
1. The Client Infrastructure calls the validation service, passing an id associated
with a wizard's next or OK action (represented by a validation key), and the
context data (represented by a validation criteria instance).
2. The validation service checks to see if there is a validator associated with the
"Next" or "OK" action. If so, it calls the validator to get the validation status
(permitted or denied) for the action.

After the validator returns its validation result, the validation service simply
passes along the validation result returned by the validator to the client
infrastructure. The client infrastructure will check to see whether that status is
“permitted” or “denied”. If the status is “permitted”, the user is allowed to proceed
to the next step in the wizard, or complete the wizard submission. If the status is

792 Customization Guide


“denied”, the user restricted from moving to the next wizard step or submitting the
wizard, and if the validator returned a message indicating why the action was
denied, that message is displayed to the user.

Key
1. The Client Infrastructure calls the validation service, passing an action
(represented by a validation key) corresponding to the page being rendered,
and the context data (represented by a validation criteria instance).
2. The validation service checks to see if there is a validator associated with the
"Next" or "OK" action. If so, it calls the validator to get the validation status
(permitted or denied) for the action.
3. The validation service passes the validation status (wrapped in a validation
result) from the validator to the client infrastructure, which either allows the
user to proceed to the next step in the wizard or submit the entire wizard, or
brings the user back to the wizard step where the action was invoked.

Presenting Information in the UI 793


Procedure – Pre-Validation
This section describes the steps you should perform for various operations related
to pre-validation.
This section contains the following procedures:
• Distinguishing between Pre-Validation Statuses on page 794
• Implementing Solution-Based Pre-Validation on page 796
• Implementing Role-Based Pre-Validation on page 799
• Implementing Validation Filters on page 799
• Implementing Validators for Pre-Validation on page 805

Distinguishing between Pre-Validation Statuses


Depending on whether you’re validating actions or attributes, the validation
statuses you’ll return from your filters or validators will vary. This section
describes some of the rules and best practices for determining which validation
statuses to return in certain scenarios.

Action Pre-Validation Statuses


The validation service and client infrastructure currently support three statuses for
pre-validated actions: “enabled”, “disabled”, and “hidden”. As you might suspect,
an “enabled” status means that the action is visible to the user and selectable for
the user. The “disabled” status means that the action is visible to the user, but not
selectable (i.e., the action is “grayed-out”). And the “hidden” status means that the
action is not visible at all to the user. Note that there is currently no support to
“disable” actions rendered as icons (in a table header or table row, for example). If
the validation service returns a “disabled” status for an action icon, the client
infrastructure will simply hide the action icon.
Whether you’re implementing a filter or validator to perform pre-validation logic,
you’ll be expected to return a validation status (either directly or wrapped in a
validation result) to the validation service. (If you implement a solution group, the
validation service automatically assigns a “hidden” status to all components
deemed invalid by that solution group.)
When trying to choose which status to return from your validator or filter, use the
following rules of thumb:
• Always err on the side of enabling. If you can’t determine conclusively
whether or not an action should be available, give it an enabled status.
Chances are there is additional validation that will occur down the line
(whether it be another filter, a validator, or post-select validation) when there

794 Customization Guide


is more context information available that can disable or deny the user. You’re
almost always better off showing a user an action they can’t perform than
hiding an action that they should be able to perform.
• When trying to choose between hidden and disabled, ask yourself whether the
action could ever be visible to the user in the current context. If the answer is
yes, then the status should be disabled. For example, the “check-out” action is
not valid for an object that is currently checked out. But if that same object
wasn’t checked out, the “check-out” action would be available to the user. In
that case, a disabled status is appropriate. However, suppose you had an action
that was only available to admin users, and your user is a non-admin. In that
case, the action would never be available to that user, so a hidden status would
be appropriate.

Attribute Pre-Validation Statuses


The validation service and client infrastructure currently support four statuses for
pre-validated attributes: “hidden” (ATTR_HIDDEN), “hidden value” (ATTR_
HIDDEN_VALUE), “read only” (ATTR_READ_ONLY), and “visible” (ATTR_
VISIBLE).
The “hidden” status means that the attribute’s name nor value is never displayed
in the UI. The “hidden value” status means that the attribute’s name will be
displayed, but not its value. The “read only” status is used to indicate that an
attribute’s name and value are displayed, but that user may not modify the value.
And the “visible” status is used to indicate that the attribute’s name and value will
be displayed and that the user may modify the value when it is available in a form
or wizard.
To determine which status applies to your attribute under certain conditions, you
should probably seek clarification from the customer, product manager, etc. There
aren’t really any generic rules that can be applied to all attributes.
You may recall that a single filter can be applied to multiple actions and attributes.
So you may be wondering which status the filter should return in situations where
it may be applied to both actions and attributes. In those situations, use the
statuses reserved for actions (“enabled”, “disabled”, and “hidden”). The client
infrastructure will treat “enabled” like “visible”, “disabled” like “read only”, and
“hidden” like “hidden”.
When applying a validator to an attribute in a table the validator will be applied to
the entire column. The validators for an attribute cannot be applied to a single cell.
The entire column will receive the most restrictive state found for any column. For
example, if one cell is read only and one is hidden, the entire column will be
hidden.

Presenting Information in the UI 795


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");

796 Customization Guide


/*
* 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=""

Presenting Information in the UI 797


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"

798 Customization Guide


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 the Customizing Role-Based UI Function — Action Visibility.

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.

Presenting Information in the UI 799


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){

800 Customization Guide


// 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.

Presenting Information in the UI 801


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>
...

Note
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" >

802 Customization Guide


<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>
...

Note
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>

Note
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.

Presenting Information in the UI 803


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>

Note
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>

804 Customization Guide


Note
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>

Note
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.

Implementing Validators for Pre-Validation


Assuming the solution-based, role-based, and filter checks pass, the final thing the
validation service will do when performing a pre-validation activity is to call the
validator associated with a UI component. As previously mentioned, a typical
validator will contain pre-validation logic that is unique to a single UI component
or a small set of related components. In other words, it is possible to associate a
single validator with multiple UI components, if the validation logic is identical
for those components. But in that case, you may also want to consider a filter. The
advantage of using a filter is that you would always have the option to add a
validator at a later time if the logic for one of the components deviates from the
others.

Presenting Information in the UI 805


Limited Pre-Validation vs. Full Pre-Validation
There are actually two pre-validation methods defined in a validator – one method
is for “limited” pre-validation, and the other is for “full” pre-validation. The
respective methods you’ll implement are called performLimitedPreValidation()
and performFullPreValidation().
The distinction between limited pre-validation and full pre-validation is made for
performance considerations. The client infrastructure will ask the validation
service to perform limited pre-validation in situations where performance is
essential. Currently, the only scenario when limited pre-validation is requested for
actions is when the row-level “action icons” are being pre-validated in a table or
tree. For attributes, limited pre-validation is always requested.
As a validator developer, you don’t need to figure out when limited pre-validation
is called vs. when full pre-validation is called. You just implement both methods
(performLimitedPreValidation() and performFullPreValidation()) in your validator
and assume that the infrastructure will call the appropriate method under the given
conditions. It’s possible and, in many cases, likely that your
performLimitedPreValidation() and performFullPreValidation() methods will have
the exact same logic.

Limited Pre-Validation Explained


Consider a table that has 50 rows, with five row-level action icons in each row.
Before the table is rendered, there will be 250 (50 rows x 5 actions) pre-validation
checks performed to determine which actions should be available in each row. If
each of those validation checks even takes .01 second, that means that 2.5 seconds
will be spent on pre-validation alone before the page is even rendered.
In this case, we are willing to sacrifice validation “accuracy” for “performance”.
The client infrastructure will request “limited” pre-validation from the validation
service in this case. The expectation is that your validator will not perform any
“expensive” validation checks when limited pre-validation is invoked, erring on
the side of enabling the action.
In other words, suppose that you need to check some access permissions in order
to really determine whether or not an action should be available to a user, but you
know that access permissions are expensive to check. In your validator’s
performLimitedPreValidation() you would skip the access permission check and
assume that the user has the appropriate permissions. The worst case scenario is
that the action is displayed and enabled for the user, but once they try to invoke it,
post-select validation performs a more complete check and denies the user from
performing the action. This is what is meant by sacrificing “accuracy” for
“performance” in limited pre-validation.

806 Customization Guide


Full Pre-Validation Explained
On the other hand, suppose you’re pre-validating an action in a “drop-down” list
of actions in a table row, or on an info page. Since we’re using Ajax to populate
these dropdown lists once the user selects them (as opposed to when the page is
initially rendered), performance is not as critical. At most, we’ll be validating
several actions, but only for a single context object.
In this case, it is acceptable to have slower performance in favor of validation
accuracy. Considering the same example we described for limited pre-validation,
if you need to perform some access permission checking to determine whether or
not an action should be available to a user, you can afford to make that check in
your validator’s performFullPreValidation() method. It may take longer to
perform the check, but since the number of validations being performed before the
page (or Ajax component) is rendered is manageable, the less-performant check is
acceptable.
Keep in mind that in many situations, your validator’s performFullPreValidation()
and performLimitedPreValidation() method implementations will be identical.

Creating a Validator
Creating a validator class should be fairly simple. All you need to do is create a
class that extends com.ptc.core.ui.validation.DefaultUIComponentValidator.
The class below represents a skeleton for a simple validator class.
package com.ptc.windchill.enterprise.myPackage.validators;

import com.ptc.core.ui.validation.DefaultUIComponentValidator;

public class MyValidator extends DefaultUIComponentValidator{


//override one or more validation methods from
DefaultUIComponentValidator
}

Implementing Pre-Validation Methods


Once you’ve created a validator class skeleton, if you’re adding pre-validation
logic for an attribute, you’ll want to implement the performLimitedPreValidation()
method. If you’re adding pre-validation logic for an action, you’ll want to
implement both the performFullPreValidation() and
performLimitedPreValidation() methods. As mentioned in the previous sections
regarding limited pre-validation and full pre-validation, the implementations of
these two methods may be identical, or they may differ. The class on the next page
contains some skeleton implementations of these methods.
public class MyValidator extends DefaultUIComponentValidator{
@Override
public UIValidationResultSet performFullPreValidation()

Presenting Information in the UI 807


(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResultSet resultSet =
UIValidationResult.newInstance();

// perform your business logic here


// if you want to enable the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
// UIValidationStatus.ENABLED));
// if you want to disable the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
// UIValidationStatus.DISABLED));
// if you want to hide the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
UIValidationStatus.HIDDEN));

return resultSet;
}

@Override
public UIValidationResultSet performLimitedPreValidation()
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResultSet resultSet =
UIValidationResultSet.newInstance();

// perform your business logic here


// if you want to enable the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
// UIValidationStatus.ENABLED));
// if you want to disable the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
// UIValidationStatus.DISABLED));
// if you want to hide the action/component, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
UIValidationStatus.HIDDEN));

return resultSet;

808 Customization Guide


}
}

Registering Validators
Once you’ve created your validator and implemented the appropriate pre-
validation method(s), the only thing left to do is to register it. You need to register
your validator to associate it with the action or attribute it is intended to validate.
When registering a validator for an action, you may make the association using
the action name only, or using a combination of action name and object type. In
most cases, using just the action name to identify your validator is sufficient and
preferred. When registering a validator for an attribute, you make the association
using the attribute’s descriptor ID.
Basic Validator Registration
To register your validator (using only the action name for an action), you need to
add an entry to *service.properties.xconf like this:
<Service context="default"
name="com.ptc.core.ui.validation.UIComponentValidator">
<Option requestor="null" serviceClass="[your fully-qualified
Validator class]"
selector="[action name/attribute descriptor ID]" />
</Service>

Once propagated to *service.properties, it should produce an entry like this:


wt.services/svc/default/com.ptc.core.ui.vali
dation.UIComponentValidator/[action name/attribute descriptor ID]/null/0=[your fully-
qualified Validator class]/duplicate

• Note that in this case, the requestor attribute is null, meaning the action’s
object type is not used in the lookup.
Type-Based Validator Registration
If you feel you have a case where it makes sense to register your validator using
an action’s object-type in addition to action name, it is very similar to registering a
validator using only the action name. The difference lies in the requestor attribute
in the properties entry. For validators that do not use an object type, the requestor
attribute is set to null. For a validator to be registered using object type, the
requestor value will be the fully-qualified class name of the type it is to be
registered for.
The class name that is used in the requestor attribute corresponds to a class name
from actions.xml.
For example, consider this fragment of an actions.xml file (NOTE: some text
eliminated for readability):
<objecttype name="problemReport" class="wt.change2.WTChangeIssue"

Presenting Information in the UI 809


...>
<action name="create" >
...
</action>
...
</objecttype>

In this case, the action we're looking at is called create. Obviously, it's likely that
there will be multiple actions defined in the system named create. However, the
validation rules for each create action may be different, depending on the type of
object being created. Therefore, it might make sense to have separate validators
for the create action for, say, a Problem Report and the create action for a Part.
Suppose we have a validator defined called com.ptc.windchill.enterprise.change2.
validators.ChangeMgmtCreateWizardsValidator that we want to register for create
actions, but only if the action is to create a Problem Report.
We could look at the actions.xml entry above and see that the create action for a
Problem Report is actually defined for an objecttype whose name is
problemReport and, more importantly, whose class is wt.change2.
WTChangeIssue.
By using that class value from actions.xml as the requestor attribute in our
properties entry, we can tell the validation service that we only want to register our
validator (com.ptc.windchill.enterprise.change2.validators.
ChangeMgmtCreateWizardsValidator) for create actions whose object type is wt.
change2.WTChangeIssue, like this:
<Service context="default"
name="com.ptc.core.ui.validation.UIComponentValidator">
<Option

serviceClass="com.ptc.windchill.enterprise.change2.validators.Chan
geMgmtCreateWizardsValidator"
selector="create" requestor="wt.change2.WTChangeIssue" />
</Service>

That's really all there is to it. Basically, if you want to register your validator for
an action, but only if that action is associated with a certain object type (in actions.
xml), you use the class attribute from actions.xml as the requestor attribute in your
properties entry.

810 Customization Guide


A few notes:
• This type-based lookup is currently only available for actions defined in
actions.xml. It will not work for attributes or other UI components.
• For this to work, the class attribute from your actions.xml entry needs to be a
concrete class (not an interface - there are many cases where the class attribute
is currently set to wt.fc.Persistable). Changing an existing class attribute from
an interface to a concrete class is OK in most cases. But you should check
with the owner of the actions.xml file you're modifying before doing so.
Verifying Validator Registration
There is a command line report you can run to see which validators are registered
for a given action or attribute. If your validator is not appearing in this report, that
means it is not registered correctly, and will never get called.
Examples follow:
Finding a single validator (non-type based)
• Usage example 1 - find the validator registered for the pasteAsCopy action:
Y:\>java com.ptc.core.ui.validation.UIComponentValidatorFactory
pasteAsCopy

Registered validators:
pasteAsCopy ->
com.ptc.core.foundation.saveas.validators.PasteValidator

Finding multiple validators (non-type based)


• Usage example 2 - find the validators registered for the setState and
pasteAsCopy actions:
Y:\>java com.ptc.core.ui.validation.UIComponentValidatorFactory
setState pasteAsCopy

Registered validators:
setState ->
com.ptc.windchill.enterprise.lifecycle.validators.SetStateValid
ator

pasteAsCopy ->
com.ptc.core.foundation.saveas.validators.PasteValidator

Finding a single validator (type-based)


• Usage example 3 - find the validator registered for the create action whose
objecttype name attribute in actions.xml is problemReport. (Note: method
server must be running for type-based lookup)
Y:\>java com.ptc.core.ui.validation.UIComponentValidatorFactory

Presenting Information in the UI 811


create:problemReport

Registered validators:
create:problemReport(wt.change2.WTChangeIssue) ->
com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat
eWizardsValidator

Finding multiple validators (mix of type-based and non-type based)


• Usage example 4 - find the validator registered for the pasteAsCopy action
and the create action whose objecttype name attribute in actions.xml is
problemReport. (Note: method server must be running for type-based lookup)
Y:\>java com.ptc.core.ui.validation.UIComponentValidatorFactory
pasteAsCopy create:problemReport

Registered validators:
pasteAsCopy ->
com.ptc.core.foundation.saveas.validators.PasteValidator
create:problemReport(wt.change2.WTChangeIssue) ->
com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat
eWizardsValidator

812 Customization Guide


Procedures – Post-select Validation
Fortunately, the procedures for implementing post-select validation are much
simpler than for pre-validation. There is really only one point where post-select
validation can be implemented, and that is within a validator. It should also be
noted that post-select validation applies only to actions. There is no concept of
post-select validation for attributes or other UI components.

Creating a Validator
Creating a validator for post-select validation is exactly the same as creating a
validator for pre-validation. See Creating a Validator for details.

Implementing Post-Select Validation Methods


There are two post-select validation methods that can be implemented in a
validator – one for single-select actions and one for multi-select actions. The
respective names of these methods are validateSelectedAction() and
validateSelectedMultiSelectAction(). If you’re adding validation for an action that
could never be a multi-select action, you only need to implement the
validateSelectedAction() method. If your action could possibly be a mutli-select
action, you should implement both the validateSelectedAction() method and the
validateSelectedMultiSelectAction() method.
The only real distinction between the two methods is in the method signatures.
validateSelectedMultiSelectAction() returns a UIValidationResultSet, whereas
validateSelectedAction() returns a single result.
public class MyValidator extends DefaultUIComponentValidator{
@Override
public UIValidationResultSet performFullPreValidation()
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResultSet resultSet =
UIValidationResult.newInstance);

// perform your business logic here


// if you want to enable the action/component, do this:
// resultSet.addResult(UIValidationResult.newInstance(validationKey
UIValidationStatus.ENABLED));
// if you want to disable the action/component, do this:
// resultSet.addResult(UIValidationResult.newInstance(validationKey,
UIValidationStatus.DISABLED));
// if you want to hide the action/component, do this:
// resultSet.addResult(UIValidationResult.newInstance(validationKey
UIValidationStatus.HIDDEN));
return resultSet;
}

Presenting Information in the UI 813


@Override
public UIValidationResultSet validateSelectedMultiSelectAction
() (UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResultSet resultSet =
UIValidationResultSet.newInstance();

// perform your business logic here


// if you want to execute the action, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
//
UIValidationStatus.PERMITTED));
// // if you want to abort the action, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
// UIValidationStatus.DENIED));
// if you want to prompt the user for confirmation, do this:
//
resultSet.addResult(UIValidationResult.newInstance(validationKey,
//
UIValidationStatus. PROMPT_FOR_CONFIRMATION));

return resultSet;
}

How to Handle UIValidationStatus.PROMPT_FOR_CONFIRMATION


If your validator retuns PROMPT_FOR_CONFIRMATION status, it need to be
configured special way by using
PTC.validation.AJAXPostSelectValidation JavaScript function.
<action name="myAction" >
<command class="com.ptc.xxx" method="function" onClick="
PTC.validation.AJAXPostSelectValidation(event, validationKey)"/>
</action>
In this case, once you have made a/few selections and click myAction:

814 Customization Guide


• PTC.validation.AJAXPostSelectValidation function based on
the provided validationKey executes post-select functions on the mapped
validator.
• If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up will be
shown and based on your selection further processing will happen.
• If you opt for “yes” for the confirmation or the status was PERMITTED,
another request will be send to the server to do the operation. There is inbuilt
intelligence not to invoke your validator again for this request.

Presenting Information in the UI 815


Procedures – Post-Submit Validation
The procedures for implementing post-submit validation is much simpler than for
pre-validation and similar to post-select validation. There is really only one point
where post-submit validation can be implemented, and that is within a validator. It
should also be noted that post-submit validation applies only to wizard steps and
wizard submissions.

Creating a Validator
Creating a validator for post-submit validation is exactly the same as creating a
validator for pre-validation. See Creating a Validator for details.

Implementing Post-Submit Validation Methods


There is only one post-submit validation method that can be implemented in a
validator –The respective name of the method is validateFormSubmission(). This
method is intended to be called after a wizard "next" or "finish" action is invoked,
to determine whether or not the user-entered data is valid.
public class MyValidator extends DefaultUIComponentValidator{
@Override
public UIValidationResult validateFormSubmission
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale
locale) throws WTException {
UIValidationResult result =
UIValidationResult.newInstance(validationKey,

UIValidationStatus.NOT_VALIDATED);

// perform your business logic here


// if you want to execute the action, do this:
// result = UIValidationResult.newInstance(validationKey,
UIValidationStatus.PERMITTED);
// if you want to abort the action, do this:
// result = UIValidationResult.newInstance(validationKey,
UIValidationStatus.DENIED);
// if you want to prompt the user for confirmation, do this:
// result = UIValidationResult.newInstance(validationKey,
//
UIValidationStatus.PROMPT_FOR_CONFIRMATION);

return result;

816 Customization Guide


How to Handle UIValidationStatus.PROMPT_FOR_CONFIRMATION
If your validator retuns PROMPT_FOR_CONFIRMATION status, it needs to be
specially configured.
• Option 1: Use your own custom ok/apply wizard button by using
PTC.validation.AJAXValidateFormSubmission JavaScript
function.
<action name="myOkButton" id="PJL_wizard_ok" >
<command class="" method="" windowType="page" url=" javascript:PTC.
validation.AJAXValidateFormAndSubmit(validationKey)"/>
</action>

In this case, once you click myOkButton:


○ PTC.validation.AJAXValidateFormAndSubmit function based
on the provided validationKey executes post-submit functions on the
mapped validator.
○ If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up
will be shown and based on your selection further processing will happen.
○ If you opt for “yes” for the confirmation or the status was PERMITTED,
the form will be submitted. There is inbuilt intelligence not to invoke your
validator again for this request.
• Option 2: Add your own user submit function in your jsp (invoked when the
form is submitted) by using PTC.validation.AJAXValidateFormSubmission
JavaScript function.
<script type="text/javascript">
setUserSubmitFunction (function () {return PTC.validation.
AJAXValidateFormSubmission(validationKey);});
</script>

In this case, once you have ok/finish wizard button :


○ PTC.validation.AJAXValidateFormSubmission function
based on the provided validationKey executes post-submit functions on the
mapped validator.
○ If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up
will be shown and based on your selection further processing will happen.
○ If you opt for “yes” for the confirmation or the status was PERMITTED,
the ok/finish wizard button submits the form. There is inbuilt intelligence
not to invoke your validator again for this request.

Presenting Information in the UI 817


Miscellaneous Tips, Tricks, and Things to Avoid
This section contains the following topics:
• Working with Access Permissions on page 818
• Rule of Thumb: One Validator per Action/Attribute/Component on page 819
• Do Not Inflate WTReferences on page 820
• Handle Null Values on page 821
• Use the @Override Annotation on page 822
• UIValidationCriteria.toString() on page 822

Working with Access Permissions


There is an attribute on UIValidationCriteria that can be used to store access
permissions retrieved by one validator or filter, to be used by a subsequent
validator or filter. For example, suppose actionA, actionB, and actionC are all in
the same action model, and all need to know whether or not the user has modify
permissions in the current container. If the validator or filter for actionA is
invoked first, it can query the AccessControlManager for the permissions and then
store them in the UIValidationCriteria, so that the validators or filters for actionB
and actionC do not need to perform the same query again.
In general, if you need to check access permissions in a validator or filter, you
should do the following:
• Check to see if the permissions are already stored in the UIValidationCriteria
by calling the new UIValidationCriteria.getCachedAccessPermissions()
method.
• If getCachedAccessPermissions() returns a non-null value, you can use those
permissions for your validation checks
• If getCachedAccessPermissions() returns null, then you can query the
AccessControlManager to get the permissions you need, and then store them
in the UIValidationCriteria for subsequent validators by calling the
setCachedAccessPermissions() method.
The intent of the cachedAccessPermissions attribute in UIValidationCriteira is that
it store the result of AccessControlManager.getPermissions().
So in other words, you should write your validator or filter code to look like this:
// check to see if the access permissions have already been
calculated...
WTKeyedHashMap accessPermissions =
criteria.getCachedAccessPermissions();
// if the access permissions have not been calculated yet, get the
permissions and cache them for other
// validators to use
if (accessPermissions == null){

818 Customization Guide


accessPermissions = AccessControlManager.getPermissions(...);
criteria.setCachedAccessPermissions(accessPermissions);
}

Additional notes regarding access permissions:


• wt.access.AccessControlManager has the following APIs available in single-
and multi-object variants:
○ hasAccess - returns true if the principal has the given access permission,
otherwise returns false
○ checkAccess - throws a NotAuthorizedException and emits an event for
auditing purposes if the principal does not have the given access
permission
○ getPermissions - returns the set of permissions (AccessPermissionSet)
granted to a principal
• Use hasAccess or getPermissions to evaluate a users rights and continue (e.g.,
UI action validation code disables action based on the user’s rights)
• One way of checking to see if a user has access is to use one of the hasAccess
APIs. Another way would be to have anyone that needs to check permissions
for an object (or objects) call one of the two getPermissions APIs, and store
the result in the UIValidationCriteria, for use by other validators that also need
to check permissions for the same object(s) (assuming the domain, type &
state of the object and the current principal remain the same), rather than
calling hasAccess to evaluate access rights for each permission check. Even if
the result was not stored, the getPermissions API would be useful for any
validator that needs to check multiple permissions. AccessPermissionSet is a
collection, and has a method to check if a specified permission is in the set:
boolean includes(AccessPermission permission)
// Returns true if permissions in this set include rights for
the specified permission.
• The checkAccess APIs should NOT be used to see if the user has a specified
permission, unless the intent is that an exception is to be propagated to the end
user. If the NotAuthorizedException is caught and does not result in a user's
action failing due to the lack of access rights, auditing of the exception should
be disabled. See the Javadoc for more information.

Rule of Thumb: One Validator per Action/Attribute/Component


Don’t fall into the trap of having one validator registered for multiple unrelated
actions. The result is lots of if/else branching and some very large methods. This
can make maintenance difficult, and makes it much easier to introduce
regressions.
In general, the only times where you would use a single validator for multiple
actions/components would be if those components share the exact same validation
logic, or if you have an either/or scenario. What we mean by an either-or scenario

Presenting Information in the UI 819


is that in a given action menu, either actionA or actionB should appear, but
never both. For all other cases, the best practice is to register one validator per
action/component.

Do Not Inflate WTReferences


You may be tempted to write validation code like this. Don't do it.
@Override
public UIValidationResultSet performFullPreValidation
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException
{
Persistable contextObject =
validationCriteria.getContextObject().getObject();
WTContainer container =
validationCriteria.getParentContainer().getReferencedContainer();

if (!contextObject instanceof WTPart){


...
}
if (!container instanceof PDMLinkProduct){
...
}
}

The code above is performing a relatively costly operation of inflating the


WTReferences held in the UIValidationCriteria to Persistables.
There may be cases where inflating those objects is not avoidable, but there are
also many cases where it can be avoided. If all you really need to know is if the
context object or parent container is an instance of some class, you can use the
isAssignableFrom() method instead, like this:
@Override
public UIValidationResultSet performFullPreValidation
(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, Locale locale)
throws WTException
{
WTReference contextObjectRef =
validationCriteria.getContextObject();
WTContainerRef containerRef =
validationCriteria.getParentContainer();

if
(!WTPart.class.isAssignableFrom(contextObjectRef.getReferencedClas
s())){

820 Customization Guide


...
}
if (!PDMLinkProduct.class.isAssignableFrom(containerRef.getReferenced
Class())){
...
}
}

Handle Null Values


There may be cases where you are writing a validator or filter for a specific action
on a specific page in a product where you need one of the attributes from
UIValidationCriteria to perform your business logic. For example, suppose you're
working on a 3rd level table on an info page, and in that table's toolbar, you don't
want an action to appear if you're on an info page for a Generic Part. So you do
the following (do not duplicate this code, but for the sake of an example...):
if
(((WTPart)validationCriteria.getContextObject().getObject()).getGe
nericType()

.equals(GenericType.GENERIC)){
...

And that may work fine in your test cases where you're only testing an action on
part details pages. But what if that action also appears in the toolbar of one of the
tables on the home page, or on the products list page? Then the code above will
throw a NullPointerException from those pages, since validationCriteria.
getContextObject() will (correctly) return null.
There are a few things you can do to avoid this scenario. The first is to check and
make sure that the values you're getting from UIValidationCriteria are not null. If
a value is null, log a warning, and call super.[whatever method you're
implementing](key, criteria, locale);.
The other thing you can do is when performing comparisons, use the .equals
operation on the "expected" value. For example:
if
(ComponentType.WIZARD.equals(validationCriteria.getComponentType()
)

NOT
if
(validationCriteria.getComponentType().equals(ComponentType.WIZARD
))

In general, just because a null value doesn't allow validation to proceed in your
use case, that doesn't mean it should be a showstopper in every use case.

Presenting Information in the UI 821


Use the @Override Annotation
It’s highly encouraged to use the Override annotation, whenever you over-ride
methods of the ootb delivered classes.

UIValidationCriteria.toString()
UIValidationCriteria, the toString() is not over-ridden to give information of its
content. You can use the following method for logging.
public String toString_heavy(Logger logger, Level level)

If the Level of the Logger matches with the Level provided, the method will
return the information. Since the method performs some costly calculations, it’s
suggested to use this it wisely.

822 Customization Guide


URL Authorization
Objective
You want to use a consistent process for validating authorization to view a URL
and present a uniform error page when an unauthorized view is attempted.

Background
A framework is available in Windchill that can be used to apply additional access
control verification on JCA and Template Processor based pages. When this
validation process is enforced on a URL, unauthorized attempts to view the page
cause a consistent error page to display. This validation process is enforced on
utility pages out of the box. You can extend this capability to other Windchill
pages by authoring a custom URL validator.

Scope/Applicability/Assumptions
The URL validation process can be extended to JCA and Template Processor
pages only. Extending this functionality to GWT-based pages is not supported.

Intended Outcome
Before a page is displayed, you are able to determine whether or not the user is
authorized to view a page when they access it from a known URL. If they are
denied access, a consistent error page is displayed.

Solution
Author a custom URL validator for the page to which you want to extend the URL
validation process.

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of JCA or Template
Processor pages, depending on the type of the page for which you are creating a
custom URL validator. You will also need to know the Component ID for the
URL of the page for which you wish to restrict access.

Presenting Information in the UI 823


Solution Elements
• Your custom validator should extend
com.ptc.core.ui.validation.DefaultURLValidator
• You can override an existing out-of-the-box validator with your own custom
validator. To do this, register your validator for the URL in WT_HOME/
codebase/config/urlValidators/custom-validators.xml
• Override public UIValidationStatus preValidateAction (UIValidationKey
validationKey, UIValidationCriteria validationCriteria) method.
• UIValidationStatus.PERMITTED means that the URL is accessible
and all other statuses means the URL is not accessible
• Note that the URL Validation service will not execute other available methods
in DefaultURLValidator.
Possible attributes of urlvalidator elements are listed in the following table.
Parameter Default Value Possible Required? Description
Values
url n/a Any Yes The
combination of Component ID
alpha-numeric for the URL
characters for which the
validator need
to be
registered
requestor n/a A valid Java No The context
class type of the
validator. This
is required if
your request is
type-based (for
example,
/tcomp/
infoPage/)

824 Customization Guide


class n/a Validator class No Your validator
uicomponent n/a No References
entry in
roleacces
sprefs.xml
(uic.name) to
specify role-
based access.

Note
Either uicomponent or class is required, otherwise an error will log in the MS
server start-up.

Registering Validators

Configuration Files
The runtime location for the configuration files are in WT_HOME/codebase/
config/urlValidators and they should follow the naming convention of
*-validators.xml. The .dtd that is applied is urlValidators.dtd and
it is available in the same location, as well as custom-validators.xml,
which should be used for custom validators.

Structuring Validator Files


The validator files should be structured as indicated below:
<urlvalidators>
<urlvalidator url=”/tcomp/infoPage”
requestor =”wt.doc.WTDocument”
class =”com.ptc.DocInfoPageValidator”/>
<urlvalidator url=”/tcomp/infoPage”
requestor =”wt.part.WTPart”
class =”com.ptc.PartInfoPageValidator”/>
<urlvalidator url=”/comp/mycomponent”
uicomponent= “HOME_UTILITIES” />
<urlvalidator url=”/myfolder/myPage”
class =”com.ptc.MyPageValidator”/>
</urlvalidators>

Presenting Information in the UI 825


Customizing the Find Number Field
Outof-the-box, the Find Number Field of the Edit Structure Window in the
Product Structure browser will not accept values which contain spaces. However,
the Find Number field can be customized to accept values that include spaces,
including leading or trailing spaces.

Caution
If you perform this customization you must maintain and carry-forward this
customization when you move to a later release of Windchill.

Note
If you want to allow leading or trailing spaces, perform steps 1 and 3 below;
otherwise step 2 is sufficient.

1. The entry "wt.load.preserveSpace=true" has to be added to the file Windchill


\codebase\wt.properties to allow for leading/trailing spaces.
2. To customize the logic in this field, perform the following steps:
a. Implement the interface "ValidateFindNumberDelegate.java"
b. Override the 'validateFindNumbers (String[])' method as described in the
sample code provided below.
c. Ensure that the implementation throws a WTPropertyVetoException (as in
the example) if any of the contraints are violated.
d. Register this new delegate in Windchill\codebase\service.properties.xconf:
There is a section with the following entry in this file:
<!--
The wt.part.ValidateFindNumbersDelegate service.

Delegate validation for Find Numbers on WTPartUsageLink


objects subclasses thereof
-->
<Service context="default"
name="wt.part.ValidateFindNumbersDelegate">
<Option cardinality="duplicate" requestor="java.lang.Object"
serviceClass="wt.part.DefaultValidateFindNumbersDelegate"/>
</Service>

826 Customization Guide


Replace wt.part.DefaultValidateFindNumbersDelegate with the full path
and name of the new delegate that was just created.
e. Run "xconfmanager -Fpv" to propagate the changes.
f. Create an rbinfo entry with the message you want to display when an error
occurs.
3. If the customization rules pertaining to leading/trailing spaces have to be
obeyed while loading data from a load file as well, then the following code
samples provide an example of how to do this in the method "getValue(String,
Hashtable, HashTable, boolean)".
OOTB Implementation
protected static String getValue( String name, Hashtable nv,
Hashtable cmd_line, boolean required ) throws WTException {
String value =
LoadServerHelper.getValue(name,nv,cmd_line,required?LoadServerH
elper.REQUIRED:LoadServerHelper.NOT_REQUIRED);

if (value != null) {
value = value.trim();
if (value.equals("")) {
value = null;
}
}

return value;
}

Customized implementation allowing leading and trailing spaces while


loading from a file:
protected static String getValue( String name, Hashtable nv,
Hashtable cmd_line, boolean required ) throws WTException {
String value =
LoadServerHelper.getValue(name,nv,cmd_line,required?LoadServerH
elper.REQUIRED:LoadServerHelper.NOT_REQUIRED);

// Don't trim leading/trailing spaces if reading Find


Number field.
if(!name.equalsIgnoreCase("findNumber"))
{
if (value != null) {
value = value.trim();
if (value.equals("")) {

Presenting Information in the UI 827


value = null;
}
}
}

return value;
}

Sample Code
// Generated DefaultValidateFindNumbersDelegate%43C7A40F0161: Fri 03/07/08
10:41:32
/* bcwti
*
* Copyright (c) 2007 Parametric Technology Corporation (PTC). All Rights
* Reserved.
*
* This software is the confidential and proprietary information of PTC
* and is subject to the terms of a software license agreement. You shall
* not disclose such confidential information and shall use it only in acco
rdance
* with the terms of the license agreement.
*
* ecwti
*/

package wt.part;

import java.lang.String;
import wt.part.ValidateFindNumbersDelegate;
import wt.part.WTPartUsageLink;
import wt.util.WTException;

//##begin user.imports preserve=yes


import wt.util.WTPropertyVetoException; // Preserved unmodeled dependency
//##end user.imports

//##begin DefaultValidateFindNumbersDelegate%43C7A40F0161.doc preserve=no


/**
* Standard delegate to handle validation of Find Numbers, i.e., OOTB behavior,
* which is doing nothing.
*
* <BR><BR><B>Supported API: </B>true
* <BR><BR><B>Extendable: </B>true
*
* @version 1.0
**/
//##end DefaultValidateFindNumbersDelegate%43C7A40F0161.doc

828 Customization Guide


public class DefaultValidateFindNumbersDelegate implements
ValidateFindNumbersDelegate {

// --- Attribute Section ---

private static final String RESOURCE = "wt.part.partResource";


private static final String CLASSNAME =
DefaultValidateFindNumbersDelegate.class.getName();

//##begin user.attributes preserve=yes


//##end user.attributes

//##begin static.initialization preserve=yes


private static final String SPACE = " ";
private static final String HYPHEN = "-";
//##end static.initialization

// --- Operation Section ---

//##begin validateFindNumbers%43C6C7F300E8.doc preserve=no


/**
*
* <BR><BR><B>Supported API: </B>false
*
* @param partUsageLinks
* @exception wt.util.WTException
**/
//##end validateFindNumbers%43C6C7F300E8.doc

public void validateFindNumbers( WTPartUsageLink[] partUsageLinks )


throws WTException {
//##begin validateFindNumbers%43C6C7F300E8.body preserve=yes

//##end validateFindNumbers%43C6C7F300E8.body
}

//##begin validateFindNumbers%45A68DEC00D9.doc preserve=no


/**
*
* <BR><BR><B>Supported API: </B>false
*
* @param findNumbers
* @exception wt.util.WTException
**/
//##end validateFindNumbers%45A68DEC00D9.doc

public void validateFindNumbers( String[] findNumbers )


throws WTException {

Presenting Information in the UI 829


//##begin validateFindNumbers%45A68DEC00D9.body preserve=yes
try
{
doValidation(findNumbers);
}
catch (WTPropertyVetoException wtpe)
{
throw new WTException (wtpe);
}
//##end validateFindNumbers%45A68DEC00D9.body
}

//##begin user.operations preserve=yes


/**
* Method to validate if the format of the "Find Number" field is correct
* or not.
* The default logic allows only alphanumeric entries for this field.
* A WTPropertyVetoException is thrown if the format of the string in this
* field does not
* match the constraints imposed. The consequence of this Exception is that
* an error dialog
* will be displayed with a message as defined in the rbinfo file.
* This method can be customized to incorporate any constraint that the user
* might wish to impose on this field.
* @param findNumbersArray The value being entered (and validated) for the
* "Find Number" field
* @throws WTPropertyVetoException
*/
private void doValidation(String[] findNumbersArray)
throws WTPropertyVetoException
{
for(int j = 0; j < findNumbersArray.length; j++)
{
String a_FindNumber = findNumbersArray[j];
// Find Number can only be alphanumeric with the exception that the "Find
// Number"
// string can contain a space (" ") or a hyphen ("-") as part of it. The
// string can
// start or end with a space, but cannot start or end with an hyphen.

if (a_FindNumber != null) {
for (int i = 0; i < a_FindNumber.length(); i++) {
if(a_FindNumber.startsWith(HYPHEN) ||
(a_FindNumber.endsWith(HYPHEN)))
{
Object[] args = {a_FindNumber};
throw new WTPropertyVetoException( RESOURCE,
wt.part.partResource.FIND_NUMBER_NOT_ALPHANUMERICAL_ERROR, args,
new java.beans.PropertyChangeEvent( this, "findNumber",
a_FindNumber, a_FindNumber ));
}

830 Customization Guide


if (!Character.isLetterOrDigit(a_FindNumber.charAt(i))) {
if((a_FindNumber.substring(i, i + 1)).equals(SPACE) ||
(a_FindNumber.substring(i, i + 1)).equals(HYPHEN))
{
// We have already checked that the first and/or
// last character is not an hyphen
// in the if-condition above. So, if the code gets
// into this block, we can be sure
// that the hyphen is in the middle of the
// string and not at the beginning or end.
// Also, if the character is a space, we are
// allowing it, so we can continue.
continue;
}
else
{
Object[] args = {a_FindNumber};
throw new WTPropertyVetoException( RESOURCE,
wt.part.partResource.FIND_NUMBER_NOT_ALPHANUMERICAL_ERROR, args,
new java.beans.PropertyChangeEvent( this,
"findNumber", a_FindNumber, a_FindNumber ));
}
}
}
}
}
}
//##emd user.operations
}

Presenting Information in the UI 831


Inline Messaging
You can develop inline message to capture success or failure of certain user
actions. You can also use this to display warning or any informational message.
However, this cannot be used for any kind of message that requires user input.

Background
This topic details the information to needed to develop inline messages using out-
of-the-box components as building blocks.

Intended Outcome
An inline message is displayed in the browser to the end user with the intended
message(s).

Solution
Use common JavaScript and java class components to display inline message that
gives user feedback about success or failure or warning message(s) for their
actions.

Prerequisite Knowledge
To apply this process, you need to have an understanding of the following:
• Java programming
• Basic web development using JavaScript, JSPs , custom tags, and HTML
forms

832 Customization Guide


Solution Elements
Element Description
Java Method This method is called by
getSuccessFeedbackMessage() setResultNextAction() of
DefaultObjectFormProcessor
and is called when FormResult is
SUCCESS. This constructs the
FeedbackMessage with the message
title, additional messages and the info
page link for the object(s) that was
created.
If the object has no identity then only
Object icon and Object Type will show
up as info page link. This is then
displayed in UI as Inline Success
message informing user that object was
created successfully.
This method may be overridden by
subclasses desiring different behavior.
See the JavaDoc for more details.
Javascript A javascript method that renders the
PTC.messaging.showInlineMessage() inline message in the main window. It
takes the array of message JSON
objects as an argument. Each message
JSON object must have
MessageTitle, an array of messages
and the type of Message.
Valid Message Types are: SUCCESS,
FAILURE, WARNING, FATAL, INFO.
This should NOT be used for any
confirmational kind of messages.
See the JavaDoc for more details.
Location:
<Windchill>/codebase/
netmarkets/javascript/util

Customization Points
The out-of-the-box JCA framework has Inline Success message displayed in UI
for successful object creation.

Presenting Information in the UI 833


This inline message is shown for single object creation:

For Multi-object creation below inline message is shown in the UI:

How to customize the message title for successful object create?


In the above screen shot message title is CONFIRMATION: Create successful.
If an application needs to override the message title then in their object form
processor they need to override public WTMessage
getSuccessMessageTitle() method and provide their own localized
message title.

How to customize the message body for successful object create?


In the above screen shot of single object create, message body is The object was
created successfully.
If an application needs to override the message body for single object creation
then in their object form processor they need to override public WTMessage
getSuccessMessageBody() method and provide your own localized
message body.
For multiple objects creation the method to override the message body is public
WTMessage getSuccessMessageBodyForMulti() in the form
processor.

Sample Code
The sample code for showing inline message for message type SUCCESS using
JavaScript function:
PTC.messaging.showInlineMessage(
[{
MessageType:'SUCCESS',

834 Customization Guide


MessageTitle:'Confirmation: Create successful',
Messages:["Object created successfully."],
OidIdentity: [{oid: "OR:wt.part.WTPart:11021",
icon: "wtcore/images/part.gif", objType: "Part"}]
}]);

Additional Resources
The following customization topics contain related information:
• Windchill Client Architecture Overview on page 232
• Adding Custom Code to all Windchill Client Architecture Pages on page 255
• Javascript Functions Overview on page 248
• Customizing the UI with Ajax on page 291
• Constructing Wizards on page 837
• Constructing and Rendering a Table Using the JSP Framework on page 606

Presenting Information in the UI 835


17
Constructing Wizards
Windchill Client Architecture Wizard.......................................................................... 838
Wizard Processing .................................................................................................. 866
Building Wizards to Create a Single Object................................................................ 892
Building Wizards to Edit a Single Object .................................................................... 914
Customizing Reusable Wizard Steps ....................................................................... 928
Handling External Requests Using an MVC Controller................................................ 959
Client Generated Form Data .................................................................................... 964

This chapter describes how to construct wizards.

837
Windchill Client Architecture Wizard
Objective
You want to create or perform an operation on object(s) by collecting information
step by step.

Background
Wizards are popup windows that are used to guide you step by step through the
process of creating an object, or performing an operation on an object. A wizard is
a user interface consisting of a sequence of steps that lead the user through a
specific task one step at a time, the user clicks next to move through the steps. It
might not be necessary to complete all the steps present in a wizard. Once the
required information is provided, you can click FINISH / OK button to submit the
data to the server. A wizard can consist of one or many steps which must be
completed in a certain order.

838 Customization Guide


A clerk is a user interface consisting of a tab control that has two or more tabs.
Data can be entered and the user can complete tabs in any order. A user may
freely move from one tab to another, even if the current tab is not complete. A
clerk is not meant to guide users sequentially through a task, and is typically used
for frequent and easily accomplished tasks.

The layout for single step wizards and multi step wizards will be different. The
single step wizard will not have “Step icons”, “Step links” and “Back / Next
navigation buttons”.

Scope/Applicability/Assumptions
• A wizard should be used when you need to create / edit object(s) by
performing any operations on it after collecting required information in a
specific systematic manner.
• A table rendered within a wizard is JCA table and table rendered inside a
picker is a JSCA table.
• For the most part, clerks are implemented in the same fashion as that of
wizards and the instructions in this document are applicable to both. Any
differences are noted. Otherwise, the term "wizard" should be interpreted as
either a wizard or a clerk and "wizard step" should be interpreted as either a
wizard step or a clerk tab.

Constructing Wizards 839


Solution
Use a Wizard or Clerk component.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development, which involves HTML, JSP, Java, JavaScript and Custom
taglibs.
• Overview of Windchill Client Architecture tags.
• The actions framework in the Windchill client architecture.
• Action validation framework.

Solution Elements
Element Type Description
components.tld tld Tag Library
Descriptor (TLD)
file, which contains
Wizard Tag and
Wizard-Step Tag
definition
Run time Location:
<Windchill>
\codebase\WEB-
INF\tlds\
wizard.js Js Contains all the
necessary logic of
how to move from
one step to another
and how to call
methods defined for
each of the steps.
Run time Location:
<Windchill>
\codebase
\netmarkets\tlds
\javascript\compon
ents
<your_wizard_ page>.jsp jsp The jsp file in
which your wizard
implementation is

840 Customization Guide


Element Type Description
defined.
<your_wizard_ step>.jsp jsp The jsp file, which
contains contents of
the wizard step.
<*-actions>.xml xml The actions for the
wizard as well as
each wizard step
are defined in this
XML file.
actionmodels.xml xml The models for the
list of buttons, to be
displayed at the
bottom of the
wizard (i.e. the
navigation area) are
defined in this
XML file.
<resourceBundle>.rbInfo rbInfo This is another
option where you
can specify locale
specific Strings and
properties for
wizard step and
wizard actions.
formProcessorController java The java class,
which will be
executed after the
wizard, is
submitted. The
wizard framework
will pass on the
data / information
to this java class.
For more
information see
Building Wizards to
Create a Single
Object on page 892
and Building
Wizards to Edit a
Single Object on

Constructing Wizards 841


Element Type Description
page 914.
wizard Tag Specifies the action
pointing to the main
JSP for the wizard
and defines the
steps contained in
the wizard. Tag
handler: com/ptc/
core/components/
tags/components/
WizardTag
wizardStep Tag Specifies the action
pointing to the main
JSP for the step.

Procedure – Configuring Wizard Component

Create actions for Wizard as well as Wizard steps


Each step of the wizard and the wizard itself needs an action declaration for the
associated page. Actions are grouped together using object types. These object
types are declared inside of the <listofactions> tag contained in any one of the
*actions.xml files. For more details on how actions work please see Action
Framework for Windchill Client Architecture on page 512.
Windchill will expect all jsp pages related to this object type to be located in
<Windchill>\codebase\netmarkets\jsp\<objecttype>. For the
below specified example the location will be <Windchill>\codebase\
netmarkets\jsp\changeTask\.
The “create” action is defined for the wizard page. By default, the name attribute
of the action points to the main jsp page for your wizard relative to codebase/
netmarkets/jsp, unless a url attribute is specified on the command tag.
Therefore, for the action below Windchill will now expect “create.jsp” to be
located in <Windchill>\codebase\netmarkets\jsp\changeTask\
folder. Since this action is for the wizard, it is necessary to specify windowType as
“popup” inside the <command> tag. See Action Framework for Windchill Client
Architecture on page 512 for more details on the windowType attribute.

842 Customization Guide


The “affectedAndResultingItemsStep” action is defined for the wizard step. The
corresponding jsp should be located at <Windchill>\codebase\
netmarkets\jsp\changeTask\
affectedAndResultingItemsStep.jsp. Since this action is for the
wizard step, it is necessary to specify windowType as “wizard_step”.
<objecttype name="changeTask"
class="wt.change2.WTChangeActivity2">
<action name="create">
<command class=”<path to form processsor>" windowType="popup"/>
</action>

<action name="affectedAndResultingItemsStep">
<command windowType="wizard_step" />
</action>
</objecttype>

The command class is the java class that should be called to process the wizard
data. Typically, this will extend CreateObjectFormProcessor.
Note that it is not necessary to specify a “method” attribute in the command tag if
the form processor class extends DefaultObjectFormProcessor or
CreateObjectFormProcessor.
Note that the “windowType” attribute of the command subtag for steps should
always be set to “wizard_step.”
Optional action tag attributes are shown in the table below.

Constructing Wizards 843


Action tag Default value Possible Values Description
attribute
ajax None page Specifies what
component portion of the
parent page should
row
be refreshed when
the wizard
processing
completes.
The value “page”
refreshes the entire
page (equivalent to
not using ajax).
The value
“component”
refreshes the table
from which the
wizard was
launched.
The value “row”
refreshes one or
more table rows.
To use the value
“row” your form
processor must tell
the system which
rows (objects)
need to be added.
UIComponent None References an
entry in
roleaccessprefs.
xml (uic name)
used to specify
role-based access
to the wizard
action.
Here is an example action for launching a creation wizard for “MyPart” objects:
<objecttype name="myPart" class="ext.part.MyPart"
<action name="create" uicomponent="CREATE_MYPART" ajax="row">
<command class="com.ptc.windchill.enterprise.part.forms.
CreateMyPartFormProcessor"
onClick="validateCreateLocation(event)" windowType="popup"/>
</action>

844 Customization Guide


The validateCreateLocation() javascript method shown in the action above is
applicable to create wizards that can be launched from a folder browser. See
“Solution Elements” in Solution on page 840 for more information.
Refer to Adding Actions and Hooking Them Up in the UI on page 511 for more
information on actions and the command tag attributes.
In addition to creating the wizard action, you will need to create text for the action
name, wizard window title, action tooltip, etc. This is described in Adding Actions
and Hooking Them Up in the UI on page 511.

Create the Wizard page


Create a new jsp page inside <Windchill>\codebase\netmarkets\
jsp\ folder and name it as create.jsp.
Wizard steps that are not preloaded should include the following directives at the
top of the jsp page:
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>
Most wizard steps will also use tags in the components.tld tag library and so
will also need to include that as follows:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
Define the wizard using the <wizard> tag. All the steps for this wizard will be
defined inside <wizard> tag using <wizardStep> tag.
If a step is preloaded, none of these are required, but it is safe to include them. A
non-preloaded-step:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components" %>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:wizard >

<jca:wizardStep action="defineItemWizStep" type="object"/>


<jca:wizardStep action="setAttributesWizStep" type="object" />
<jca:wizardStep action="affectedAndResultingItemsStep"
type="changeTask" />
</jca:wizard>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Define a Clerk
Defining a clerk is exactly same as defining a wizard, the only difference in the
case of a clerk is that you define the type as "clerk".
<jca:wizard type="clerk">
<jca:wizardStep action="defineItemWizStep" type="object"/>
<jca:wizardStep action="setAttributesWizStep" type="object" />
<jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" />

Constructing Wizards 845


</jca:wizard>

After defining the wizard type as "clerk", the wizard will be displayed as per the
Clerk UI standards. Step indicators will not appear and step titles will be displayed
as tabs. The Next and Previous buttons will not be displayed for Clerk. The user
can navigate from any step to any step without entering the required fields. The
validation for required fields will be done when the user clicks on the "OK"
button. The user will be shown a message about required fields and will be taken
to the appropriate steps, where required fields are not populated.
The Clerk Component has a provision through which application developers can
call their specific validation logic.
For example: An application developer can write following code in jsp file to call
javascript() on “OK” Button.
<script>
Event.observe($("PJL_wizard_ok"), 'click', userdefinedjavascriptFunction );
</script>

Specify localized Strings / properties for wizard step and wizard actions
You can specify localized strings / properties in a
<resourceBundle>.rbInfo file.
The format of each entry should be
<objectType>.<action>.<property>.<type> = <value>. For
example, you can specify the height and width of the popup window in which the
wizard will be displayed, using the following property:
changeTask.create.moreurlinfo.value=width=800,height=
700
changeTask.create.description.value=New Change Task
changeTask.create.description.comment=Used as the label for the create action
changeTask.create.title.value=New Change Task
changeTask.create.title.comment=Used as the title for the create action
changeTask.create.tooltip.value=New Change Taskchange
Task.create.tooltip.comment=Used as the tooltip for the create action
changeTask.create.icon.value=../../wtcore/images/task_create.gif
changeTask.create.icon.comment=DO NOT TRANSLATE
changeTask.create.icon.pseudo=false
changeTask.create.moreurlinfo.value=width=800,height=700
changeTask.create.moreurlinfo.pseudo=false

Create the wizard step page


This can be any JSP page, and can contain any other component(s) as well as plain
HTML contents.
You do not have to create new steps if already existing steps will work. See
Customizing Reusable Wizard Steps on page 928 for steps available to reuse.

846 Customization Guide


Customization Points
This section contains the following topics:
• <action>.xml attributes on page 847
• <wizard> tag attributes on page 849
• <wizardStep> tag attributes on page 850
• Providing user defined buttons to Wizard on page 851
• Providing user defined form processor controller on page 852
• Providing server side validation before / after processing a wizard step on page
852
• Loading the wizard step content when it is visited on page 853
• Marking a wizard step as “required” on page 853
• Hiding a wizard step on page 854
• Displaying the hidden / dynamic step at runtime on page 855
• Providing user defined SUBMIT function on page 856
• Providing client side validations before a wizard step is displayed on page 857
• Providing client side validations after a wizard step is finished on page 857

<action>.xml attributes
Parameter Default Possible Values Req? Description
Value
name None Any string Yes The name of the action.
Used as the “name”
attribute on wizard step
tags.
id <type>. Any String No Overrides the id of the
<action> wizard step (default is
type.action). Used to
identify the step in
certain javascript
functions. If not
specified the id <action
type>.<action name>
will be used.
afterJS - Any String No Specify the javascript
function name to invoke
client side validation for
a wizard step when step
is finished and the user
clicks Next or OK on the

Constructing Wizards 847


Parameter Default Possible Values Req? Description
Value
wizard step. Can be used
to do client-side
validation of the form
data..
beforeJS - Any String No Specify the javascript
function name to invoke
client side validation for
a wizard step when step
is loaded.
beforeVK - Any String No Specify the server
validator name to invoke
server side validation for
a wizard step when step
is loaded when the user
navigates to the step
using the Previous or
Next button...
afterVK - Any String No Specify the server
validator name to invoke
server side validation for
a wizard step to be
called after the user
clicks Next, Previous or
Finish on the step. Can
be used to do server-side
validation of the form
data.
preloadWizar true false / true No Specifies that wizard
dPage step is to be downloaded
when wizard is launched
rather than when the
user navigates to the
step. Preloading wizard
steps will make it faster
to move to the next step.
However, do not preload
wizard steps that are
dependent on
information gathered in
previous steps..

848 Customization Guide


Parameter Default Possible Values Req? Description
Value
hidden false false / true No Specifies that wizard
step is to be hidden at
first, or for the action to
be rendered as non-
clickable.
required false false / true No Specifies that wizard
step is required.

<wizard> tag attributes


Parameter Default Possible Values Req? Description
Value
buttonList “Default Any String No The action model
Wizard- containing the list of
Bu ttons” buttons to display in the
wizard. The default set
is the
DefaultWizardButtons
action model. Another
commonly used set
isNoStepsWizardBut-
tons (for single-step
wizards)
Additional buttons sets
are available in actions.
xml and custom button
sets can be defined
formProcesso “DefaultF Any String No The
rController ormProce FormProcessorControl-
ssorContr ler class that should be
oller” used to process the
wizard when it is
submitted.
If not specified,
DefaultFormProcessor-
Co ntroller will be used.
title - Any String No The overriding title to
display instead of the
default title in the rbInfo
file or action.properties

Constructing Wizards 849


Parameter Default Possible Values Req? Description
Value
file. This title will not be
localized /
internationalized by
default. You need to take
care of passing a
localized title.
helpSelec- - Any String No The selector key to
torK ey identify help file from
services.properties file.
type wizard Wizard/clerk/dialog No Identifies whether
wizard is of type clerk or
not. If "clerk" is
specified, the wizard
will be displayed as per
clerk UI.
progressMess - Any String No This allows for text to be
age displayed above the
progress bar using the
UI standard.

<wizardStep> tag attributes


Parameter Default Possible Values Req? Description
Value
action - Any String Yes The name of the action
to include in the wizard
parent tag.
type - Any String Yes The type of the action to
include in the wizard
parent tag.
objectHandle - Any String No The object handle to
identify which object
this step corresponds to.
Only required if the
wizard needs to create
multiple objects.
By default, no object
handle is needed.

850 Customization Guide


Parameter Default Possible Values Req? Description
Value
label - Any String No The label for the step.
Note: Actions should
already have labels.
Only set this attribute if
you want to override the
action's label.
embedded- - Any String No A small text help button
Hel p to be displayed on top of
the wizard step content.
Optional.

Providing user defined buttons to Wizard


You can change / specify different types of buttons that are present at the bottom
of the wizard (i.e. the navigation area). The Wizard framework provides a default
button model, which consists of buttons like NEXT, PREVIOUS, OK, APPLY and
CANCEL. However, the Wizard framework also provides you the ability to
specify your own set of buttons with user-defined functionality.
In <your_wizard_page>.jsp
<jca:wizard buttonList="PreferenceWizardButtons" >
...
...
</jca:wizard>

You need to provide corresponding entry in actionmodels.xml file:


<actionmodels>
<model name="PreferenceWizardButtons">
<action name="revertButton" type="object"/>
<action name="okButton" type="object"/>
<action name="cancelButton" type="object"/>
</model>
</actionmodels>

Every button in the actionmodel should have a corresponding entry for its action
in actions.xml file. If there is a separate java class written to render that particular
button, than you can specify the name of that class and its method (which contains
the rendering code) using the “class” and “method” attributes of <command> tag.
For example:
<action name="revertButton" id="PJL_wizard_revert_to_default">
<command class="" method="" windowType="page"
url="javascript:revertToDefault()"/>
</action>

Constructing Wizards 851


Note
For a clerk, only the OK and Cancel buttons are displayed by default. If new
buttons are to be configured, the appropriate button model should be
configured.

Providing user defined form processor controller


You can specify a form processor controller, which would be executed when the
wizard is completed and the user clicks on OK, FINISH or APPLY button to
submit it. The form processor controller gets the data specified in all the wizard
steps, from Wizard framework, and processes it. After processing the data, a form
processor controller returns an object of FormResult, along with the status. Based
on the status (SUCCESS / FAILURE), which is returned, the wizard framework
will decide further action. For example:
In <your_wizard_page>.jsp
<jca:wizard formProcessorController =
"com.mycompany.MyUniqueFormProcessorController">y

...

</jca:wizard>

Note
For more information see the Wizard Processing on page 866 section.

Providing server side validation before / after processing a


wizard step
You can implement server side validations using specific java classes and
configuring the wizard to execute them before / after processing a wizard step.
You can achieve this by using “beforeVK” and “afterVK” attributes of <action>
tag. You need to provide a key as the value for these attributes. The corresponding
key should be declared in any <*-service>.properties file specifying the java class
which will perform the validations and return the result. For example:
<action name="setAttributesWizStepForCreateMultiPart" beforeVK =
"nameNumberValidation">
<command windowType="wizard_step"/>
</action>

852 Customization Guide


OR
<action name="setAttributesWizStepForCreateMultiPart" afterVK =
"nameNumberValidation">
<command windowType="wizard_step"/>
</action>

<Service context="default"
name="com.ptc.core.ui.validation.UIComponentValidator">
<Option requestor="null" selector="nameNumberValidation"
serviceClass="com.ptc.windchill.enterprise.part.validator.CreateMul
tiPartNameNumberValidator" />
</Service>

Loading the wizard step content when it is visited


By default, all of the wizard steps are downloaded at wizard execution time.
You can configure the wizard such that the content of any wizard step is not
loaded when the wizard is first initialized and loaded. You can load the contents of
a wizard step when you try to visit that step. You may need this feature when the
step is dependant on information gathered from a previous step.
You can use “preloadWizardPage” attribute of <action> tag to achieve this. By
default, the value of this attribute is “true”. For example:.
<action name="setClassificationAttributesWizStep
" preloadWizardPage="false">
<command windowType="wizard_step"/>
</action>

Note
In the case of a clerk, all the steps will be loaded by default. The clerk does
not have conditional display of steps (i.e. hidden steps), so all the steps would
be preloaded.

Marking a wizard step as “required”


You can mark a wizard step as “required”. By doing so, the wizard cannot be
submitted unless and until this required step is visited at least once. So the submit
buttons (like OK, FINISH or APPLY) would be enabled only after all the required
steps are completed / visited at least once. For example:
<action name="setClassificationAttributesWizStep" required="true">
<command windowType="wizard_step"/>
</action>

Constructing Wizards 853


You can also mark a wizard step as “required” at runtime. You need to use a
javascript function called “setStepRequired” which is defined in main.js file. You
need to pass the “id” of the step. The default id of the step is in the format
“<type>.<action>”. Use the value of the “id” attribute if it is defined explicitly
while defining wizard step action. For example:
<table border="0">
<tr>
<td align="left" valign="top" NOWRAP>
<w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>"
value="<%=NmObjectHelper.CB_COPY%>" checked="true"
onclick="setStepRequired(<type>.<action >);"/>
</td>
</tr>
</table>

Hiding a wizard step


There are two ways to hide a wizard step. First, you can hide a wizard step
initially when the wizard is launched. Secondly, you can hide the wizard step at
run time depending on certain criteria or certain user actions. In both the cases, it
is mandatory to register the wizard step while defining the wizard.
In <your_wizard_page>.jsp
<jca:wizard >
<jca:wizardStep action="defineItemWizStep" type="object"/>
<jca:wizardStep action=" setClassificationAttributesWizStep " type="object" />
<jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" />
</jca:wizard>

To implement first way of hiding a step, you can make use of the “hidden”
attribute of <action> tag. For example:
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" hidden="true">
<command windowType="wizard_step"/>
</action>

To hide a wizard step at runtime, you need to use a javascript function called
“removeStep” which is defined in main.js file. You need to pass the “id” of the
step that needs to be removed. The default id of the step is in the format “<type>.
<action>”. Use the value of the “id” attribute if it is defined explicitly while
defining wizard step action. For example:
In <your_wizardstep_page>.jsp
<table border="0">
<tr>
<td align="left" valign="top" NOWRAP>

854 Customization Guide


<w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>"
value="<%=NmObjectHelper.CB_COPY%>" checked="true"
onclick="removeStep(<type>.<action >);"/>
</td>
</tr>
</table>

Note
Clerk does not use the of conditional display of steps (i.e. hidden steps), so all
the steps will be preloaded and displayed to the user.

Displaying the hidden / dynamic step at runtime


You can show up the hidden wizard step at runtime using the javascript function
called “insertStep” which is defined in main.js file. You need to pass the “id” of
the step that needs to be inserted. The default id of the step is in the format
“<type>.<action>”. Use the value of the “id” attribute if it is defined explicitly
while defining wizard step action. It is mandatory to register the wizard step while
defining the wizard.
For example:
In <your_wizard_page>.jsp
<jca:wizard >
<jca:wizardStep action="defineItemWizStep" id=” defineItemWizStep”
type="object"/>
<jca:wizardStep action=" setClassificationAttributesWizStep " type="object" />
<jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" />
</jca:wizard>

In <*-actions>.xml
<action name="setClassificationAttributesWizStep" hidden="true">
<command windowType="wizard_step"/>
</action>

In <your_wizardstep_page>.jsp
<table border="0">
<tr>
<td align="left" valign="top" NOWRAP>
<w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>"
value="<%=NmObjectHelper.CB_COPY%>" checked="true"
onclick="insertStep(<type>.<action>);"/>
</td>
</tr>

Constructing Wizards 855


</table>

Will the Wizard Steps be Clickable?


The intended behavior for whether the steps in a multi-step wizard will be
clickable is determined by a number of factors, including whether a step has been
visited and/or completed, and whether a step is marked as required or not. The
following list summarizes the intended behavior:
• When a wizard has a combination of required and non-required or optional
steps, proper UX design dictates that all the required steps should appear
sequentially before the optional steps.
• The current active step should be clickable (call this step1). The term
'clickable' indicates the cursor changes to a pointing hand image when hovered
over the step number, and clicking the step performs an action, either
navigation or message.
• The step after the current active step should also be clickable (call this
step2). However, if there are any required fields yet to be completed on
step1, clicking step2 should provide a warning message about the missing
information and block the move. Essentially, the step after the current active
step should perform the same action as clicking the Next button.
• Once all of the required steps have been visited, (and the OK/Finish/Apply
button becomes enabled), the remaining optional steps should be clickable.
• Any time a given wizard step has been visited, that step should be clickable.
This applies for both forward and backward navigation, and need not be
single-step. For example, in a five step wizard, if you've completed the first
four steps, then wish to navigate back to verify something on the first step, you
can navigate there directly by clicking step1, then returning directly to
step4.
An example with all steps required is the "New ECAD Design" wizard, and an
example with only the first step required is the "New Change Request" wizard.

Providing user defined SUBMIT function


You can configure a user-defined javascript function, which will be called when
the wizard is submitted. You need to write you own submit functionality in some
javascript function and than pass the name of that function as an argument to
“setUserSubmitFunction” (provided by wizard framework). By doing so,
you are preventing the wizard framework to call the default submit function.
Based on the return value (true / false), the wizard framework will decide further
action. For example:
<script type="text/javascript">
function user_validate() {

856 Customization Guide


...
...
return true;
}

setUserSubmitFunction(user_validate);
</script>

Providing client side validations before a wizard step is


displayed
You can configure a user-defined javascript function, which will be called when a
wizard step is loaded but before it is displayed. You need to write you own
functionality in some javascript function and specify the name of function as the
value for the attribute "beforeJS" while defining the action for that particular
step. This particular step will only be displayed if the specified function returns
"true", else the wizard will move to the previous step. For example:
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" beforeJS ="
validatePreviousStep">
<command windowType="wizard_step"/>
</action>

In any JSP page or Javascript file accessible to wizard


<script type="text/javascript">
function validatePreviousStep() {
...
...
return true;
}
</script>

Providing client side validations after a wizard step is


finished
You can configure a user-defined javascript function, which will be called when a
wizard step is completed but before next step is loaded. You need to write you
own functionality in some javascript function and specify the name of function as
the value for the attribute "afterJS" while defining the action for that particular
step. The next step will only be displayed if the specified function returns "true".
For example:
In <*-actions>.xml
<action name="setClassificationAttributesWizStep" afterJS ="
validateStep">

Constructing Wizards 857


<command windowType="wizard_step"/>
</action>

In any JSP page or Javascript file accessible to wizard


<script type="text/javascript">
function validateStep() {
...
...
return true;
}
</script>

Configuring Wizard - Suppressing enter key


You can suppress form submission on enter key.
<script type="text/javascript">
// Supress form submission twice due to hiting enter
function wizardKeyUpListener(event) {
var target = Event.element(event);
if (event.keyCode == Event.KEY_RETURN || event.which ==
Event.KEY_RETURN) {
if (target != null && (target.tagName == "SELECT" ||
target.tagName == "TEXTAREA" || target.tagName == "INPUT")) {
Event.stop(event);
return false;
}
}
}

Configuring Wizard - Changing the Default Focus Element


You can change the default focus element in the wizard. Generally the
infrastructure will try to make the default focus element the first required field that
is editable (input, select, or textarea tag). This is very tricky and so the
infrastructure may not get it right in all cases.
If a different element is desired for the first focused element, or this behavior is
not working properly in your wizard then you can create some javascript code to
get your desired behavior.
• In a .js file included only by this wizard:
//First, Remove the current focus listener to avoid any race conditions. For
Example:
PTC.un('ready', PTC.wizard.focusOnReadyFunc);
//Create the new focus listener to select your desired component
function customFocusFunc {} {

858 Customization Guide


// Focus on a specific ID when it becomes available…

}
//Register your new listener on the page.
PTC.onReady( customFocusFunc );

Creating Data Validators for Your Steps


Validation of the data entered by users is done after each step and in some cases
after each input field is completed. It may be done on the client via javascript and/
or on the MethodServer via a Java class that extends UIComponentValidator.
The system automatically validates that all required attribute values are provided
if the input fields are generated by the standard renderers. The renderers add a
“class="required"” attribute to the input field and the wizard javascript checks to
make sure that each field with such an attribute has a value. You can do other
client validation in a javascript method by specifying the method as the value of
the afterJS attribute of the step action. See Adding Custom Code to all Windchill
Client Architecture Pages on page 255 for information on how to package your
custom javascript.
Validation of data values against constraints defined for the attributes in the Type
and Attribute Management utility must be done in the MethodServer. This is done
by implementing the validateFormSubmission() method on a subclass of
DefaultUIComponentValidator. You then specify the name of the selector key for
a service.properties entry pointing to your DefaultUIComponentValidator in the
afterVK attribute of your step action. The validateFormSubmission() method of
your validator class will be automatically called by the framework when the user
clicks the Next or OK button on a step. It is also called when the value of any
attribute in the driver attributes panel is changed.
Default server-side validators are available for the Set Context, driver attributes
table, and Set Attributes wizard steps. The selector keys and validator class paths
are specified in the following entries in components.service.properties.xconf:
<Service context="default" name="com.ptc.core.ui.validation.
UIComponentValidator">
<Option serviceClass="com.ptc.core.components.validators.
ContextWizardStepValidator" requestor="null" selector=
"setContextWizStep"/>
<Option requestor="null"
serviceClass="com.ptc.core.components.validators.
DefineObjectStepValidator" selector="defineItem" />
<Option serviceClass="com.ptc.core.components.validators.
SetAttributesStepValidator" requestor="null"
selector="setAttributesWizStep "/>
</Service>

Constructing Wizards 859


If the out-of-the-box validator classes meet your needs you can use them by
specifying the selector strings shown in the entries above as the values of the
afterVK attributes of your wizard step actions. If you need to do additional
validation, you can write your own validators, typically subclassing the standard
validators. Note that all the form data can be accessed from the
UIValidationCriteria parameter passed to the validator by calling
UIValidationCriteria.getFormData(). The validateFormSubmission() method
should return a UIValidationResult with a status of UIValidationStatus.
PERMITTED if all the form data is valid or a status of UIValidationStatus.
DENIED if one or more attribute values are not valid. In the latter case, the user
will be returned to the wizard step just completed to correct the invalid values.
Feedback messages to be displayed to the user should be added to the
UIValidationResult using the UIValidationResult.addFeedbackMsg() method.

Limitations
Windchill Wizard framework takes help from Windchill Action framework to pick
up the localized wizard title either from the related .rbInfo file or from a action_
<locale>.properties file. It uses the <objectType> and <action> to fetch the
required value. The problem arises when you try to use “url” attribute of
“command” tag (while defining the wizard action). If the value of the “url”
attribute points to a jsp page whose name matches with some another action, the
wizard framework will receive localized title corresponding to that action.
Consider the following scenario:
<action name="createPartWizard">
<command class="com.ptc.windchill.enterprise.part.forms.CreatePartFormProcessor"
method="execute" onClick="validateCreateLocation(event)"
windowType="popup"/>
</action>

<action name="createMultiPart" >


<command class =
"com.ptc.windchill.enterprise.part.forms.CreateMultiPartFormProcessor"
method="execute" onClick="validateCreateLocation(event)"
windowType="popup"
url="/netmarkets/jsp/part/createPartWizard.jsp?wizardType=multiPart" />
</action>

In the above specified case, the wizard title for the action “createMultiPart”
will be picked up from the property
“part.createPartWizard.title.value” and not from the property
“part.CreateMultiPart.title.value”.

860 Customization Guide


The workaround for this scenario is to use the “title” attribute of the wizard tag. If
this attribute is specified, the wizard framework will not try to look in to any
rbInfo or properties file. However, be sure that you provide a localized string as a
title to wizard tag. For example:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%>

<fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/>
<fmt:message var="createMultiplePartWizardTitle" key =
"part.createMultiPart.WIZARD_LABEL" />

<jca:wizard helpSelectorKey="PartMultipleCreate"
title="${createMultiplePartWizardTitle}">
...
...
</jca:wizard>

Limitations for Clerks


Clerks will execute only required fields validation for all the clerk steps. All the
other validations mentioned below should be provided by the respective clerk
developers:
• Valid Characters - Validate that the user has not entered any illegal characters
for a given field (e.g. alpha characters in a numeric field).
• Format - Validate that the user has entered values in an expected and
understandable format. Note that the UI should do as much as possible to
prevent the user from entering invalid formats in the first place (e.g. clearly
indicating what format is expected, allowing different formats to be entered).
See the Form Standard for more information.
• Length - Validate that the user has entered a value which is neither too long
nor too short for a given field.
• Uniqueness - Validate that data entered is unique with respect to existing data
in the system. For example, verifying that a given part number does not
already exist in the system.
In case of clerk, while navigating between steps any java code such as a validator
may not get the required fields so developers need to take care and apply logic
accordingly.( E.g. While creating a new document first step has required field
type (means type of document), since in clerk user is free to navigate between
other tabs while clicking on other tabs,user might not have selected required filed
type in first step. In that case server validator can’t get value of type attribute.)

Constructing Wizards 861


Sample Code

Examples of Usage in Windchill Code


• Create Part wizard:
<Windchill>\codebase\netmarkets\jsp\part\createPartWizard.jsp

• Create Folder wizard:


<Windchill>\codebase\netmarkets\jsp\folder\create.jsp

• Create Document wizard:


<Windchill>\codebase\netmarkets\jsp\document\create.jsp

• Create Multiple Documents wizard:


<Windchill>\codebase\netmarkets\jsp\document\createMulti.jsp

Packaged Samples
• Wizard Example One on page 862
• Wizard Example Two on page 863
• Clerk Example One on page 865

Packaged Samples
This section contains information on the sample code that is provided within the
system.

Wizard Example One


Description
This is an example of a wizard with three steps. The second and third steps are
conditionally displayed based on the content of the first step. The first step also
includes before and after JavaScript method.

Location of Example
To navigate to this example in the produce go to Customization >> Component
Catalog >> Wizard Component >> In the example section select the first “New
Wizard Description.”

Actions for this Example


• newWizardExampleOne
• setFirstWizStep

862 Customization Guide


• setThirdWizStep
• setSecondWizStep

Action Models for this Example


• None

Files Used in This Example


• \netmarkets\jsp\carambola\customization\examples\wizard
\newWizardExampleOne.jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setFirstWizStep.jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setSecondWizStep.
jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setThirdWizStep.
jsp

Wizard Example Two


Description
This is an example of a wizard with three steps. The second and third steps are
conditionally displayed based on the content of the first step. The first step also
includes before and after JavaScript method.
The steps in this wizard contain a table and a tree and illustrate how those
components can be included in a wizard step.

Location of Example
To navigate to this example in the produce go to Customization >> Component
Catalog >> Wizard Component >> In the example section select the second “New
Wizard Description.”

Actions for this Example


• newWizardExampleTwo
• setFourthWizStep
• setFifthWizStep
• setSixthWizStep

Constructing Wizards 863


Action Models for this Example
• None

Files Used in This Example


• \netmarkets\jsp\carambola\customization\examples\wizard
\wizardExampleTwo.jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setFourthWizStep.
jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setFifthWizStep.
jsp
• \netmarkets\jsp\carambola\customization\examples\wizard\setSixthWizStep.
jsp

864 Customization Guide


Clerk Example One
Description
This is an example of a clerk with three steps.

Location of Example
To navigate to this example in the product, from the Navigator open
Customization ▶ Component Catalog ▶ Wizard Component ▶ New Clerk Description.

Actions for this Example


• clerkExampleOne
• setFirstClerkStep
• setSecondClerkStep

Action Models for this Example


• None

Files Used in This Example


• \netmarkets\jsp\carambola\customization\examples\
wizard\clerkExampleOne.jsp
• \netmarkets\jsp\carambola\customization\examples\
wizard\setFirstClerkStep.jsp
• \netmarkets\jsp\carambola\customization\examples\
wizard\setSecondClerkStep.jsp

Constructing Wizards 865


Wizard Processing
Objective
You have created a JSP wizard to gather information from a user about one or
more object(s). You now need to create the code to process that information and
perform a database operation(s) on the object(s).

Background
If your wizard uses one of the built-in button sets, when a user clicks the Finish,
Apply, Save, or Check In button to submit the form, a javascript function is called
that invokes the processRequest() method of the ActionController.
The WizardServlet loads the HTTP form data and other wizard context
information, such as where the wizard was launched, into a NmCommandBean. It
then passes the NmCommandBean to the FormDispatcher class. The
FormDispatcher calls the FormProcessorController.
The FormProcessorController partitions the form data into
ObjectBeans. One ObjectBean is created for each target object of the
wizard. It contains all the form data specific to that object and any form data that
is common to all objects. The FormProcessorController then passes the
ObjectBeans to classes called ObjectFormProcessors that perform the
tasks appropriate to the wizard — for example, creating a new object in the
database, updating an object in the database, or checking in an object
ObjectFormProcessors, in turn, can call classes called
ObjectFormProcessorDelegates to perform one or more subtasks.
If your wizard is performing an operation on a single object you may need to
create your own ObjectFormProcessor and/or
ObjectFormProcessorDelegates to perform the tasks specific to your
wizard. However, if your wizard is creating or editing an object, you may be able
to take advantage of some processors that are delivered with the product for those
purposes.
See Building Wizards to Create a Single Object on page 892 and Building
Wizards to Edit a Single Object on page 914 for more information.
If your wizard has multiple target objects you may or may not also need to create
your own FormProcessorController to control the order in which objects
are processed.

Scope/Applicability/Assumptions
Assumes that you have already created the necessary JSPs, data utilities, GUI
components, and renderers to display your wizard. Also assumes that you have
created the necessary actions to hook up your wizard to the UI.

866 Customization Guide


Intended Outcome
Perform a database operation(s) related to one or more Windchill object.

Solution
Use the JSP client architecture framework and common components to process
wizard form data and perform the appropriate database tasks for one or more
object(s).

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Java programming
• Basic web development using HTML forms
• Familiarity with the Windchill service APIs or other APIs necessary to
perform the tasks appropriate to the wizard
Definition of terms used in this section:
Term Definition
target object Object(s) for which you are gathering data in your wizard. Some
operation(s) will typically be performed on these objects in your
wizard processing.

Solution Elements
Element Type Description
ActionController Java class This is the class to which wizard
form data gets posted and which
sends the response page sent back
to the browser after processing
completes.
Runtime location:
<Windchill>/srclib/
CommonComponents-web.jar
FormProcessor Java interface Classes implementing this interface
Controller instantiate and call
ObjectFormProcessor(s) to execute
wizard tasks.
Runtime location:
<Windchill>/srclib/

Constructing Wizards 867


Element Type Description
CommonComponents.jar
DefaultForm Java class A default implementation of
ProcessorController FormProcessorController that
should be sufficient for all single-
object wizards. This controller
partitions the HTML form data into
ObjectBeans and passes those beans
to ObjectFormProcessors.
Wizards with multiple target objects
may need to extend this class to
control the order in which objects
are processed.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar
ObjectForm Java interfacer Classes implementing this interface
Processor perform the database and related
tasks appropriate to the wizard
using the form data. Each wizard
will have only one
ObjectFormProcessor class but
multi-object wizards may have
multiple instances of that class.
ObjectFormProcessors may call
ObjectFormProcessor Delegates to
perform subtasks.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar
DefaultObject Java class A default implementation of
FormProcessor ObjectFormProcessor that contains
the logic to execute
ObjectFormProcessorDel egates
and perform several other common
tasks. This is the base class that
should be extended by wizard-
specific processors.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar

868 Customization Guide


Element Type Description
ObjectForm Java interface Classes implementing this interface
ProcessrDelegate are called by ObjectFormProcessors
to perform processing subtasks.
Multiple ObjectFormProcessorDel
egates may be called by one
processor and the same delegate
may be used by multiple processors
to handle a task common to
multiple wizards. These are
optional.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar
DefaultObject Java class A default implementation of
FormProcessor ObjectFormProcessorDelegate. This
Delegate provides no-op behavior for
methods a subclass may not need to
implement. This is the base class
that should be extended by task-
specific delegates.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar
ObjectBean Java class A container for the form data
specific to a specific target object
and the data common to all objects.
Provides methods to retrieve the
form data for a given object.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar

Constructing Wizards 869


Element Type Description
ProcessorBean Java class A container for ObjectBeans that
knows which ObjectBeans should
be processed by the same processor
instance and the order in which they
should be processed.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar
FormResult Java class A class used to pass method results
between server methods and from
the server to the WizardServet.
Runtime location:
<Windchill>/srclib/
CommonComponents.jar

The relationship between the main Java classes in the wizard processing
framework is shown in the UML diagram below.

Form Processing Task Flow


Frequently, multiple tasks are performed on wizard target object(s) when
processing the form data. These typically follow the following sequence:
1. Preprocessing

870 Customization Guide


During this phase the setup for the database operation is done. For example:
• for an object creation wizard, instances of the object(s) are created and
their attributes set from values in the form data
• for an object edit wizard, the object(s) are retrieved from the database and
their attributes are modified per the values in the form data
2. Start a database transaction block
3. Do the database operation. For example:
• for an object creation wizard, the object(s) would be stored in the database
• for an object edit wizard, the object(s) would be updated in the database
4. Postprocessing
Do database or other tasks that need to be done after the main database
operation but within the same transaction block so that the database operation
will be rolled back if these task fail. These tasks typically require that the
target object(s) be persisted beforehand. For example:
• share the object(s) to another container
• submit the object(s) to a workflow
5. End the database transaction block
6. Post-transaction processing
Do tasks that need to be done after the transaction block is closed so that the
entire database transaction will not be rolled back if the tasks fail. For
example:
• check out an object
Additional database operations may be performed in this phase if desired.
The tasks in each processing phase are performed by
ObjectFormProcessors and ObjectFormProcessorDelegates.
Every wizard must have an ObjectFormProcessor which should extend the
DefaultObjectFormProcessor. This is the primary class that controls and
performs the processing tasks appropriate to the wizard.
Wizards may or may not have one or more
ObjectFormProcessorDelegates that are called by the
ObjectFormProcessor (via the DefaultObjectFormProcessor) to
perform processing subtasks. ObjectFormProcessorDelegates should
extend the DefaultObjectFormProcessorDelegate class. See Create
any necessary ObjectFormProcessorDelegate classes for your wizard on page 884
for more information about ObjectFormProcessorDelegates.
Both ObjectFormProcessor and ObjectFormProcessorDelegate
classes have preProcess(), doOperation(), postProcess(), and
postTransactionProcess() methods for carrying out tasks during each

Constructing Wizards 871


processing phase. Not every wizard will have tasks in every phase, so it is not
necessary that every processor and every delegate implement all of these methods,
if they extend from the default classes DefaultObjectFormProcessor and
DefaultObjectFormProcessorDelegate, respectively. Those parent
classes provide default implementations of each method. If an
ObjectFormProcessor does implement one of these methods, it should call
the super() method of the DefaultObjectFormProcessor, which will
handle the calling of ObjectFormProcessorDelegates.
The HTML form data will be passed to ObjectFormProcessors and
ObjectFormProcessorDelegates in a list of ObjectBeans. An
ObjectBean contains the data specific to one target object and the data common
to all the target objects. For wizards with a single target object the list will contain
only one ObjectBean. For wizards with multiple target objects the list will
contain one ObjectBean for each target object and the ObjectBeans may be
organized into a tree structure representative of the relationship between the
objects and the order in which they should be processed. The creation of
ObjectBeans is handled by the FormProcessorController.
The FormProcessorController also handles the opening, closing, and, if
necessary, rollback of the database transaction and the calling of the
ObjectFormProcessors. For the latter, the
DefaultFormProcessorController uses objects called
ProcessorBeans. Target objects with the same parent object, which are of the
same type, and which have the same ObjectFormProcessorDelegates are
placed into the same ProcessorBean.
Each ProcessorBean also will have its own instances of the
ObjectFormProcessor and ObjectFormProcessorDelegates for the
ObjectBeans it contains. ProcessorBeans may be organized into a tree
structure to control the order in which objects are processed. (Wizards with a
single target object will have only one ProcessorBean. )
The task flow of the DefaultFormProcessorController is as follows:
1. Call the preProcess() method of ObjectFormProcessor for the root
ProcessorBean, passing it the ObjectBeans in the ProcessorBean.
Then call the preProcess() method of the processors for the children of
the root ProcessorBean, in the order in which they appear in the child list.
Then call the preProcess() method for the children of the children, and so
forth.
2. Do Transaction.start()
3. Call the doOperation() method of the ObjectFormProcessor for the
root ProcessorBean and its children in the same way as preProcess().
4. Call the postProcess() method of the ObjectFormProcessor for the
root ProcessorBean and its children in the same way as preProcess().

872 Customization Guide


5. If steps 1-4 are successful, do Transaction.commit()
6. Call the postTransactionProcess() method of the
ObjectFormProcessor for the root ProcessorBean and its children
in the same way as preProcess().
If any method returns a status of FormProcessingStatus.FAILURE, the
controller will call the setResultNextAction() method of the
ObjectFormProcessor that failed so it can set information needed for the
HTML response page.

Note
ObjectFormProcessors should not open/commit additional transaction
blocks in steps 3 or 4 as nesting of transactions is not recommended.

Wizards with Multiple Target Objects


Two types of multiple-object wizards are supported:
• wizards with multiple unrelated target objects
Example: create multiple parts
• wizards with a tree of related target objects
Example: create a change notice and related change tasks
The data specific to a given object should be contained either in a table row
specific to that object or in a wizard step specific to that object. An example table
where each row represents a part being created and each column is an attribute of
the part is shown below.

Each wizard step must display one of these types of data:


• data in tabular format where each row represents a different object
• data that is specific to one and only one of the objects created
• data that is common to all objects created

Constructing Wizards 873


A step cannot contain object-specific data for multiple objects unless it is in
tabular format.
In multiple-object wizards, the object to which an input field applies is identified
by an "objectHandle" embedded in the name attribute of the HTML input
field. For example:
<input id="null1188140328133"
name="<someFieldIdString>!~objectHandle~newRowObj_430512131997223~!
<someAdditionalText>" value="" size="60" maxlength="60"
type="text">

In the example above, "newRowObj_430512131997223" is the object


handle, "!~objectHandle~" is the required prefix, and "~!" is the required
suffix. The HTML name attribute in which the object handle is embedded can be
any string and the object handle may appear anywhere within the string.
When the DefaultFormProcessorController loads the form data in to
ObjectBeans, it will strip off the object handle (including the required prefix
and suffix) from the name attribute and use the resulting string as the key for the
value in the form data parameter maps. For example, to retrieve the form value for
the input field above you would call ObjectBean.getTextParameter()
with the following key:
<someFieldIdString><someAdditionalText>

The framework generates object handles on name attributes for you in one of two
ways:
• If data for the objects is being captured in tabular format, where each row
represents an object and each column an attribute of the object, the handle will
be dynamically generated for you if you set rowBasedObjectHandle=
true on the table config in the builder::
table.setRowBasedObjectHandle(true);

The object handle for each row will be based on the row’s OID.
objectHandle = CreateAndEditWizBean.getNewObjectHandle(next.getOid().toString());
• Where all the data on a given wizard step is for the same object, you specify
the object handle for that object on the wizard step action:
<jca:wizardStep action="setContextWizStep" type="object"
objectHandle="<your object handle string>" …

If data on the wizard step is common to all objects created, no object handle is
needed on the input fields. The object handle associated to the data in an
ObjectBean can be accessed by the ObjectBean.getObjectHandle()
method. The FormProcessorController controls the order in which
processors are called to process the ObjectBeans, as described in the sections

874 Customization Guide


below. Note that in the illustrations below, circles are used to represent
ObjectBeans. Circles representing objects of the same type will have the same
shading.

Multiple unrelated target objects


Typically, when a wizard has multiple unrelated target objects, the objects are the
same type:

An example of such a wizard is that in which you can create multiple parts. This
wizard has three steps:
1. Define Part
User enters the type of parts to be created and other attributes common to all
the parts being created.
2. Set Attributes
User enters the name and number of each part to be created in tabular format.
This table is dynamic in that the user can enter any number of parts.
3. Set Additional Attributes
User enters some additional attributes common to all of the parts.
If the user enters data for five parts, the
DefaultObjectFormProcessorController will create five
ObjectBeans. Each ObjectBean will contain the data from step 2 specific to
the part it represents and the data from steps 1 and 3. Because there is no
relationship between the parts and they can be created independently, none of the
ObjectBeans will have parents or children. Since the same
ObjectFormProcessor and ObjectFormProcessorDelegates will
be used to process all the ObjectBeans and all the objects are of the same type,
they will all be placed in the same ProcessorBean.

Constructing Wizards 875


Multiple related target objects
Other wizards may have multiple related target objects. For example, you might
have a wizard that creates a change notice and the change tasks related to that
change notice. To create the associations between the change notice and the
change tasks, the processor for the change notice will need to know how the
objects relate to each other.

The change notice ObjectBean has three child ObjectBeans. The change
task ObjectBeans have a parent ObjectBean and no children.
In this case, you would need to write your own FormProcessorController
to create the structure of ObjectBeans. This can be a subclass of the
DefaultFormProcessorController.
The default controller will create the ObjectBeans for you. You would override
its createObjectBeanStructure() method, which is given a flat list of all
the ObjectBeans. In that method you would set the parents and children of the
ObjectBeans. You pass back a list of all the root ObjectBeans. After you
have created the ObjectBean structure, the
DefaultFormProcessorController will call the
ProcessorBean.newCollection() method which will group the
ObjectBeans into ProcessorBeans as follows:

876 Customization Guide


In the diagram above the circles represent the ObjectBeans and the solid lines
the relationships between them. The rectangles represent the two
ProcessorBeans and the dotted line the relationship between them.
Each ProcessorBean will have its own instances of the
ObjectFormProcessor and the ObjectFormProcessorDelegates
needed for the objects in it. If the processor for the root ProcessorBean is
called "ProcessorInstance1" and the processor for the child
ProcessorBean is called "ProcessorInstance2", the processor methods
would be called as follows:
Method Task Performed
1 ProcessorInstance1.preProcess create an instance of a
(ObjectBean in Processor Bean 1) WTChangeOrder2 and store it in the
"object" attribute of the bean
2 ProcessorInstance2.preProcess create three instances of
(ObjectBeans in Processor Bean 2) WTChangeActivity2 and store them
in the "object" attributes of the beans
3 ProcessorInstance1.doOperation persist the WTChangeOrder2
(ObjectBean in Processor Bean 1)
4 ProcessorInstance2.doOperation persist the WTChangeActivity2
(ObjectBeans in Processor Bean 2) instances
5 ProcessorInstance1.postProcess create the associations between the
(ObjectBean in Processor Bean 1) change notice and the change tasks
6 ProcessorInstance2.postProcess none
(ObjectBeans in Processor Bean 2)
7 ProcessorInstance1. none
postTransactionProcess
(ObjectBean in Processor Bean 1)
8 ProcessorInstance2. none
postTransactionProcess
(ObjectBeans in Processor Bean 2)

The tasks could be arranged differently. For example, you could create the
associations in method 6 instead of method 5 with the same effect. Or, you could
create an ObjectFormProcessorDelegate to create the associations in its
postProcess() method. The framework offers the flexibility to modularize
your code as best fits your wizard. Just be sure to arrange your tasks correctly
relative to the start and end of the main transaction.

Constructing Wizards 877


Your structure of ObjectBeans could be more complex. For example:

As you can see from the diagram above, ObjectBeans will be placed in
different ProcessorBeans if any of the following is true:
• the object in the ObjectBeans are different types
• the ObjectBeans have a different ObjectFormProcessor
(Note: at this time all the ObjectBeans in the wizard must have the same
ObjectFormProcessor.)
• the ObjectBeans have a different list of
ObjectFormProcessorDelegates
• the ObjectBeans have a different parent ObjectBean
The DefaultFormProcessorController will call the processors
associated with each ProcessorBean starting at the root ProcessorBean
and proceeding down the tree to the leaf ProcessorBeans.

Procedure - Creating Your Wizard Processing Code


You have two options in creating your wizard processing code:
• Wizards with a Single Target Object on page 879
• Wizards with Multiple Target Objects on page 884

878 Customization Guide


Wizards with a Single Target Object
This process consists of the following steps:
• Create your processor class on page 879
• Specify the processor class for the wizard on the wizard action on page 881
• Create any necessary ObjectFormProcessorDelegate classes for your wizard
on page 882
• Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard on
page 883

Create your processor class


Three processors for handling object creation and editing wizards are delivered
with the product:
• com.ptc.core.components.forms.CreateObjectFormProces
sor
• com.ptc.core.components.forms.DefaultEditFormProces
sor
• com.ptc.core.components.forms.EditWorkableFormProces
sor
These processors may be used as is or extended for your own purposes.
If your wizard is not an object creation or editing wizard you will need to create
your own ObjectFormProcessor. ObjectFormProcessors should
extend the DefaultObjectFormProcessor class.
You should place your form processing logic into the preProcess(),
doOperation(), postProcess(), and postTransactionProcess()
methods of the processor, as appropriate. Your methods should call the
corresponding super method of the DefaultObjectFormProcessor, which
will handle the calling of ObjectFormProcessorDelegates. These
methods will be passed a single ObjectBean, which will contain all the form
data from the wizard. The form data can be accessed using the getter methods of
that object. The following getter methods are commonly used:
public Map<String,List<String>> getChangedComboBox()
public Map<String,String> getChangedRadio()
public Map<String,String> getChangedText()
public Map<String,String> getChangedTextArea()
public Map<String,List<String>> getChecked()
public Map<String,List<String>> getUnChecked()
public List getRemovedItemsByName(String paramName)
public List getAddedItemsByName(String paramName)
public String getTextParameter(String key)
public String[] getTextParameterValues String key)

Constructing Wizards 879


See the javadoc for more information.
The "object" attribute of the ObjectBean represents an instance of the target
object . Where appropriate, it should be set by one of your processor methods
(most likely preProcess()) for use by downstream methods. Other
information can be passed from one method to another using processor instance
variables.
The NmCommandBean object passed to these methods contains information
about the page from which the wizard was launched and the object selected on the
parent page when the wizard was launched. It also contains all the HTML form
data but you should use the methods on the ObjectBean rather than the
NmCommandBean to access that data. See the javadoc for NmCommandBean for
more information.
You pass the outcome of the preProcess(), doOperation(),
postProcess(), and postTransactionProcess() methods back to the
DefaultFormProcessorController using the
com.ptc.core.component.FormResult object. Before returning, each of
these methods should call FormResult.setStatus() to return the
processing status. Three options are available:
• FormProcessingStatus.SUCCESS - if the method executed without
error
• FormProcessingStatus.FAILURE - if the method encountered a fatal
errors FormProcessingStatus.NON_FATAL_ERROR - if the method
succeeded but encountered one or more problems that should be reported to
the user.
The DefaultFormProcessorController passes the returned
FormResult to its continueExecuting() method to determine whether
processing should continue to the next phase or be aborted. By default, it will
abort only if the status is FormProcessingStatus.FAILURE. If processing
is to be aborted or after all processing competes successfully, the controller will
call the setResultNextAction() method of the
ObjectFormProcessor to set information in the FormResult needed to
construct the response page sent back to the browser.
This method should convey the following information:
• The feedback messages should be displayed to the user, if any.
Determined from the feedbackMessages and exceptions variables.
Feedback messages, if any, are displayed before executing any window operations
or provided javascript.
Exception messages are only displayed if status is
FormProcessingStatus.FAILURE or
FormProcessingStatus.NON_FATAL_ERROR.

880 Customization Guide


See the javadoc for the FormResult and FormProcessingStatus classes
for more information.
It is also possible for your ObjectFormProcessor's preProcess(),
doOperation(), postProcess(), and postTransactionProcess()
methods to throw exceptions. In that case, control will be returned to the
ActionController which will set the variables of the FormResult as
follows:
• status - FormProcessingStatus.FAILURE
• exceptions - the thrown Exception
This will cause the response page to display the exception message in an alert
window and then close the wizard window.

How to get selected object(s) in form processor using NmCommandBean


There are four different form processing scenarios and to get the selected oid in
each scenario there is different API on NmCommandBean that can be used. See
the picture below for more details.

Specify the processor class for the wizard on the wizard action
You specify the ObjectFormProcessor class in the <command> subtag of
the <action> tag for the wizard. Your action tag will be contained in a
*actions.xml file.
Here is an example of how you would specify the
CreateDocFormProcessor class as your processor.
<action name="create">
<command

Constructing Wizards 881


class="com.ptc.core.components.forms.CreateObjectFormProcessor"

windowType="popup" />
</action>

Create any necessary ObjectFormProcessorDelegate classes for your


wizard
ObjectFormProcessorDelegates may be used to carry out one or more
subtasks in your wizard processing. Because the same delegate class may be
called by multiple ObjectFormProcessors, they are typically used for tasks
that are needed by multiple wizards. Here are some examples of how
ObjectFormProcessorDelegates are used in the delivered product:
• Several object creation wizards have a checkbox named "Keep checked out
after checkin." The ObjectFormProcessors for all these wizards call the
same ObjectFormProcessorDelegate class to handle this checkbox
and checkout the object after it is created if the box is checked.
• Wizards to create objects that are ContentHolders typically have a Set
Attachments step to specific the documents that should be attached to the
object. All these wizards call the same
ObjectFormProcessorDelegate class to handle the persistence of the
attachments.
• Many object creation wizards have an input field for a Location attribute to
specify the object's folder. Because the processing of this input field is
complex all these wizards call the same
ObjectFormProcessorDelegate to set the folder on the object being
created.
As shown in the examples above, a ObjectFormProcessorDelegate can
handle the processing of one or many input fields. If your wizard does not have
any HTML elements that are used in multiple wizards you may not need any
delegates. However, they can be useful for modularizing your processing code
also.
ObjectFormProcessorDelegates should extend the class
DefaultObjectFormProcessorDelegate.
ObjectFormProcessorDelegates are instantiated by the
DefaultFormProcessorController and passed to the
ObjectFormProcessor.
ObjectFormProcessorDelegates have preProcess(),
doOperation(), postProcess(), and postTransactionProcess()
methods just like ObjectFormProcessors. The delegates registered for the
wizard will be called by the DefaultObjectFormProcessor during the
different processing phases.

882 Customization Guide


The outcome of an ObjectFormProcessorDelegate method is passed
back to the ObjectFormProcessor using a FormResult, just as the
ObjectFormProcessor methods pass back their results to the
FormProcessorController.
Like ObjectFormProcessor methods,
ObjectFormProcessorDelegate methods can throw exceptions. How
these are handled depends on the ObjectFormProcessor calling it.

Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard


The names of the ObjectFormProcessorDelegate classes to be
instantiated by the DefaultObjectFormProcessor, if any, are
communicated in hidden input fields as follows:
<input name="FormProcessorDelegate"
value="com.ptc.core.components.forms.NumberPropertyProcessor"
type="hidden">

These hidden input fields can be created in several ways:


• If you have a delegate associated with a specific wizard step, the delegate can
be specified in the command subtag of in the wizard step action. For example:
<action name="attachmentsWizStep" postloadJS="preAttachmentsStep"
preloadWizardPage="false"
<command

class="com.ptc.windchill.enterprise.attachments.forms.Second
aryAttachmentsSubFormProcessor" windowType="wizard_step"/>
</action>

The wizard framework will then generate a hidden


FormProcessorDelegate field in the wizard for any wizard using this
step. If you have specified an object handle on the wizard step action, the
name attribute of the hidden field will include the object handle so that the
delegate will be called only for the target object associated with the step.
• If you have a specific input field that requires a delegate you can generate the
hidden field in the data utility that creates the GUI component for the input
field. It is recommended that the data utility return a subclass of
AbstractGuiComponent to take advantage of the
addHiddenField() method and the AbstractRenderer. After
creating the GUI component in the data utility, call the method
addHiddenField() in the AbstractGuiComponent class. For
example:
LocationInputGuiComponent guiComponent = new
LocationInputComponent(…);
guiComponent.addHiddenField
(CreateAndEditWizBean.FORM_PROCESSOR_DELEGATE, "com.

Constructing Wizards 883


ptc.windchill.enterprise.folder.LocationPropertyProcess
or");

The hidden input field will be generated for you by the


AbstractRenderer automatically. If the field is associated with a step or
table row that has an object handle, that object handle will be embedded in the
HTML name attribute of the hidden field. If you choose to return a GUI
component that does not extend AbstractGuiComponent, your GUI
component and renderer would have to know how to render the necessary
hidden field.
• You can include a hidden field for your delegate directly in your jsp file.
However, one of the first two methods is preferred because it encapsulates the
hidden field with its associated HTML input fields.

Wizards with Multiple Target Objects


This process consists of the following steps:
• Create your processor class on page 879
• Specify the processor class for the wizard on the wizard action on page 884
• Create any necessary ObjectFormProcessorDelegate classes for your wizard
on page 882
• Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard on
page 883
• Create a FormProcessorController, if needed on page 885
• Specify the FormProcessorController to be used in your wizard, if needed on
page 885

Create your processor class


The same as for a wizard with a single target object. See Create your processor
class on page 879.

Specify the processor class for the wizard on the wizard action
The same as for a wizard with a single target object. See Specify the processor
class for the wizard on the wizard action on page 881.

Create any necessary ObjectFormProcessorDelegate classes for your


wizard
The same as for a wizard with a single target object. See Create any necessary
ObjectFormProcessorDelegate classes for your wizard on page 882.

884 Customization Guide


Specify the ObjectFormProcessorDelegate(s) to be used in your wizard
The same as for a wizard with a single target object. See Specifying the
ObjectFormProcessorDelegate(s) to be used in your wizard on page 883.
Remember that an object handle must be embedded in the name attributes of the
hidden fields specifying the delegates if you want the delegate to be used only for
a given object.

Create a FormProcessorController, if needed


If the target objects of your wizard form a structure of related objects, you will
need to create your own FormProcessorController to create a structure of
the ObjectBeans. You should subclass the
DefaultFormProcessorController to leverage its ability to partition the
form data into ObjectBeans and ProcessorBeans and call the form
processors. Typically, the only method you will need to override is the
createObjectBeanStructure() method.

Specify the FormProcessorController to be used in your wizard, if needed


If you have created your own FormProcessorController, you should
specify the controller to be used for your wizard on the wizard tag in your main
JSP file for the wizard. For example:
<jca:wizard helpSelectorKey="change_createProblemReport"
buttonList="DefaultWizardButtonsWithSubmitPrompt"
formProcessorController="com.ptc.windchill.enterprise.change2.forms.
controllers.ChangeItemFormProcessorController">

Constructing Wizards 885


FormResult / Client-Side Post Form Processing
Starting with the Windchill 10.1 MR010 release, the form processing and the
action response handling have been separated. This means that the form processor
will still perform the work to update/add/delete the selected/affected objects, but
there is no need to specify the next action on the FormResult. The
FormResult will contain the OIDs of the objects that were updated/added/
deleted. These OIDs will be passed back to the client and the client will update the
components that are currently displaying those objects.

Setting up the FormResult


Starting with the Windchill 10.1 MR010 release there is no need to set the next
action (i.e. setNextAction(FormResultAction.REFRESH_OPENER)).
Only the OIDs the objects added/updated/removed should be added to the
FormResult object.
Example: formResult.addDynamicRefreshInfo new
DynamicRefreshInfo(newOid, oldOid,
NmCommandBean.DYNAMIC_UPD))
The ability to set a URL or Javascript function on the FormResult is still valid.
However, this should only be done when no other options are available. Because
multiple clients are potentially invoking these actions the URL javascript returned
may not be appropriate or may not reference valid code. Ideally, you want the
components to update themselves and not have individual actions update the
components on the page. If a URL is set on the FormResult, the
afteraction listener will not be called on the component where the action was
launched from. However, the objectsaffectedlistener will be called.

Refreshing/Updating JCA Components


There are two listeners that can be attached to components for objects updated via
actions. Most of the components (i.e. table, tree, info page, etc.) have a default
listener for both of the events.
• afteraction : This listener is responsible for updating the objects in the
component where the action was launched/executed from. For example, if the
checkout action was executed from the information page, the information page
afteraction listener is responsible for refreshing itself. Likewise, if the
checkout action was launched from a table, the table afteraction listener
will be responsible for updating the row in the table. This listener can be
attached to any Ext component by adding the afteraction event listener.
The listener will receive the FormResult JS object as a

886 Customization Guide


parameter.component.on(‘afteraction’,
someAfterActionListener);
• objectsaffected : This listener is responsible for updating the objects in
a component when the action is executed from a different component. For
example, if the checkout action was performed from the information page and
the search results table contained that same object, the objectsaffected
listener for the [search results] table will be responsible for updating the row
in the table. This listener is attached to the global PTC.action object:
component.mon(PTC.action,
‘objectsaffected’,someListener);

Examples of Custom Action Handling

Refreshing an entire component when any action occurs inside of it


me.on('afteraction', me.onAfterAction);
me.onAfterAction = function(formResult) {
me.refresh();
return true;//Stop further processing
};

Replacement for FormResultAction.FORWARD and LOAD_OPENER_


URL
Different components have different behavior and different client platforms have
different URL patterns so it is not supported to generically try and specify a URL
on the FormResult. Each component can decide how to do it individually and
the afterAction listeners on common components such as the infopage and
miniNavigator already have generic logic to refresh themselves. The
miniNavigator for example does not want to forward to the new URL
because that would break the user out of the current context and so it refreshes
itself instead.
See the checkout example below for how to have a component specific event
listener do something unique. See the
PTC.miniNavigator.onAfterAction and the
PTC.infoPage.onAfterAction code in the js files. If extra URL
parameters are needed to be passed down to construct the url on the client side
then the FormResult.extraData map can be used to pass down extra
information.
You can change how an object is handled for a specific table. For example add a
row to the checkouts table instead of adding a checkout glyph to an existing row
(from wip.jsfrag):
PTC.wip = {};
/**
* add/remove rows from the checkouts table for the wip actions
*/

Constructing Wizards 887


PTC.wip.checkoutsTableObjectsAffectedWrapper = function(original, formResult) {

if (formResult.actionName === 'checkout') {


var added_new_rows = formResult.getUpdatedOids();

if(added_new_rows.length > 0) {
clearActionFormData();

rowHandler.addRows(added_new_rows, this.id, null, {


doAjaxUpdate : true,
addSorted : true
});
}
return true;
}
return original.call(this, formResult);
};

PTC.wip.addCheckoutTableListeners = function (table) {


table.onObjectsAffected = table.onObjectsAffected.wrap
(PTC.wip.checkoutsTableObjectsAffectedWrapper);
};

Ext.ComponentMgr.onAvailable('checkedout.work.table',
PTC.wip.addCheckoutTableListeners);

Replacements for FormResultAction.JAVASCRIPT


In cases where extra javascript was needed to run to update specific components
in the page as the result of an action, it is better to add component specific
objectsaffected listeners instead that react to the specific action, such as the
checkout action example below. Some wizards may want to add a listener specific
to the wizard because the javascript is often times not needed in other pages.

Wizard Specific Handler


Actions that need to perform custom or specific code as the result of a wizard can
use a callback function for handling a successful submission. This
successFunc configuration parameter is passed to the
PTC.wizard.submitWizard function. This successFunc is then called
when the wizard receives the FormResult from the server and begins to fire the
afteraction and objectsaffected events. This allows an action owner
to control the flow and behavior of the wizard more specifically than needing to
modify how individual components handle the event name. For Example, the
checkin Button on the edit wizard has a success handler to launch the
checkin wizard once the attributes are successfully saved to the database.
In the sample code below, notice that the function passed to the wizard code:
<command onClick="onEditSubmit('checkinButton')"/>
function onEditSubmit(actionName){

888 Customization Guide


var params = {successFunc: PTC.wizard.launchCheckinWizard,
finished: actionName=='saveButton'};
PTC.wizard.submitWizard(params);
}

Change how an object is handled for a specific table


For example, you can add a row to the checkouts table instead of adding a
checkout glyph to an existing row (from wip.jsfrag):
PTC.wip = {};
/**
* add/remove rows from the checkouts table for the wip actions
*/
PTC.wip.checkoutsTableObjectsAffectedWrapper =
function(original, formResult) {

if (formResult.actionName === 'checkout') {


var added_new_rows = formResult.getUpdatedOids();

if(added_new_rows.length > 0) {
clearActionFormData();

rowHandler.addRows(added_new_rows, this.id, null, {


doAjaxUpdate : true,
addSorted : true
});
}
return true;
}
return original.call(this, formResult);
};

PTC.wip.addCheckoutTableListeners = function (table) {


table.onObjectsAffected = table.onObjectsAffected.wrap
(PTC.wip.checkoutsTableObjectsAffectedWrapper);
};

PTC.onAvailable('checkedout.work.table',
PTC.wip.addCheckoutTableListeners);

Replacement for FormResultAction.FORWARD and LOAD_OPENER_


URL
Different components have different behavior and different client platforms have
different URL patterns so it’s not supported to generically try and specify a URL
on the FormResult. Each component can decide how to do it individually and
the afterAction listeners on common components such as the infopage and
miniNavigator already have generic logic to refresh themselves. The

Constructing Wizards 889


miniNavigator for example does not want to forward to the new URL
because that would break the user out of the current context and so it refreshes
itself instead.
See the checkout example below for how to have a component specific event
listener do something unique. Also see the
PTC.miniNavigator.onAfterAction and the
PTC.infoPage.onAfterAction code in the js files. If extra URL
parameters are needed to be passed down to construct the url on the client side
then the FormResult.extraData map can be used to pass down extra
information. In most cases it is not necessary to auto-forward to the info page of
an object just created or modified. After create actions, an inline message appears
and contains a link to allow someone to go to the new objects info page. This is
how one might auto-forward after an action. Modify the component’s
onAfterAction method to include this code sequence:
if (formResult.actionName === 'checkout') {
PTC.infoPage.goTo(formResult.getUpdatedOids()[0]);
}
return true;
You can add a generic action handler to all possible components that will auto-
forward for a specific action. The following code example details this. However,
this is not necessarily recommended because some pages and components might
lose in-progress data.
PTC.action.on('objectsaffected', function (formResult) {
if (formResult.actionName === 'checkout') {
PTC.infoPage.goTo(formResult.getUpdatedOids()[0]);
}
return true;
});

Limitations
• Only one ObjectFormProcessor class per wizard is supported at this
time
• The framework does not support having data for multiple objects in the same
wizard step unless it is in tabular format. It also does not support having data
common to all the objects on the same step as object-specific data.

890 Customization Guide


Additional Resouces

Related Package/Class Javadoc


• com.ptc.core.components.forms.FormDispatcher
• com.ptc.core.components.forms.FormProcessorController
• com.ptc.core.components.forms.DefaultFormProcessorController
• com.ptc.core.components.forms.ObjectFormProcessor
• com.ptc.core.components.forms.DefaultObjectFormProcessor
• com.ptc.core.components.forms.CreateObjectFormProcessor
• com.ptc.core.components.forms.DefaultEditFormProcessor
• com.ptc.core.components.forms.EditWorkableFormProcessor
• com.ptc.core.components.forms.ObjectFormProcessorDelegate
• com.ptc.core.components.forms.DefaultObjectFormProcessorDelegate
• com.ptc.core.components.forms.FormResult
• com.ptc.core.components.forms.DynamicRefreshInfo
• com.ptc.core.components.forms.FormProcessingStatus
• com.ptc.core.components.util.FeedbackMessage
• com.ptc.core.ui.resources.FeedbackType

Constructing Wizards 891


Building Wizards to Create a Single
Object
Objective
You need to develop a wizard to capture user input and from that input create a
Windchill business object in the database.

Background
Windchill provides a framework for creating wizards and navigating between
wizard steps. It also provides data utilities, GUI components, renderers, and
validators for creating input elements in your wizard JSPs. Finally, it provides a
framework for processing the data sent to the server when the wizard form is
submitted. These frameworks and components are described in other documents
listed in Prerequisite Knowledge on page 894.
This document builds upon that information to describe how to develop and
process wizards designed specifically to create Windchill objects. It will tell you
how to use out-of-the-box components as building blocks to create your own
wizards. Components you will typically make use of are:
• action definitions for wizard steps that are common to multiple wizards
• jsp and jspf files for wizard steps that are common to multiple wizards
• custom tags for managing wizard data and displaying elements on the page
• Java classes for processing the wizard data after the user submits the wizard

Scope/Applicability/Assumptions
Assume you have created a custom Windchill business object class or subtype and
you want to develop a wizard that will allow users to create one instance of that
object type in the database.
The object to be created should be a Persistable. It may or may not implement the
Typed, Foldered, and/or Iterated interfaces. Where this document makes reference
to attributes that are not applicable to your object type it is correct to ignore those
implementation details.
This document describes the creation of a very basic wizard to create objects.
There are many reusable steps available to you out of the box. For more details on
adding these steps to a wizard see Customizing Reusable Wizard Steps on page
928.
Be aware that it may not be necessary to develop your own custom wizard to
create instances of a custom type. If your type is a Windchill business class for
which a wizard with a type picker is already available, it may be possible to use
the out-of-the-box wizard for the type. The out-of-the-box wizards will

892 Customization Guide


automatically find subclasses and subtypes of a given base type such as WTPart or
WTDocument and display those subtypes in the type picker so that a user can
create instances of them. For example, if you have created a soft subtype of
WTPart called PBPart, it will be displayed in the New Part wizard as follows:

You need to specify any non association attributes you have defined for your sub
type in the Type and Attribute Management utility Layout for them to appear as
Input fields in the non driver attributes table. Attributes will be displayed in the UI
exactly as you specify them in the Type and Attribute Management utility.
If you want to order the attributes on this step differently, you will need to create a
new jsp for this step specifically for your subtype but you can still use the New
Part wizard.
However, if you need to associate other objects to your new object or require
additional wizard steps, you will likely need to develop a custom wizard.
This document describes the process of developing a wizard that creates a single
object. See Building Wizards to Edit a Single Object on page 914 for information
on constructing a wizard to edit an object.

Intended Outcome
Add a single- or multi-step HTML wizard to the product that allows a user to
create a business object in the database. The arrangement of steps and presentation
of attributes within the wizard should be similar to that of other Windchill wizards
to provide a consistent user experience.

Constructing Wizards 893


Solution
Use common jsp, tag, JavaScript, and Java class components built on top of the
jsp wizard framework to create a wizard for capturing user input and for
processing that input and creating the object in the database.

Prerequisite Knowledge
To apply this process, you need to have an understanding of the following:
• Java programming
• Basic web development using JSPs , custom tags, and HTML forms
• How to create hard or soft Windchill business object types.
See the following chapters for more information on creating your business
object classes:
○ Getting Started With Windchill Customization on page 55
○ System Generation
See the “Type and Attribute Management utility” chapter of the Windchill
Business Administrator's Guide for more information on creating subtypes and
attributes.
• The use of actions to launch jsp pages and wizards.
See Adding Actions and Hooking Them Up in the UI on page 511 for
information on how to create actions.
• The Windchill framework for creating wizards and processing wizard data.
See Constructing Wizards on page 837 for more information on this topic.
• The use of tables and property panels to present information in the UI and how
to acquire the data for these components. For more information see
○ Customizing HTML Clients Using the Windchill JSP Framework on page
289
○ Gathering the Data for the UI on page 583
○ Presenting Information in the UI on page 603
• The use of data utilities, gui components, and renderers to create HTML
elements for presenting and editing object attributes within tables and property
panels. See Presenting Information in the UI on page 603 for more
information.
• The use of the UI Validation Service for validating the user’s ability to
perform actions and for validating the data entered in wizards. See Adding
Validation Logic for Actions and Properties on page 442 for more information.

894 Customization Guide


• The Windchill service APIs or other APIs necessary to perform the data
processing tasks appropriate to the wizard
• Attribute Layout
See Attribute Customization on page 658 for more information.
This document will build on this knowledge and provide additional
information on the components available to help you create and process
wizards for the specific purpose of creating a Windchill business object in the
database.

Definition of Terms Used in This Section


Term Definition
base type A hard or subtype class that is the root type of the
wizard's type picker. If the wizard does not have a
type picker, this is the type of object that will be
created. The base type is used to look up the
correct JSPs for wizard steps that have different
jsp variants for different subtypes until a specific
type is selected by the user.
dependent attribute An attribute whose value and/or display
characteristics are wholly or partially determined
by the value of another attribute (called the
"driver attribute") via an object initialization rule
(OIR), access control policy, or other mechanism.
driver attribute An attribute whose value drives the value and/or
display characteristics of another attribute (called
a "dependent" attribute) via an object initialization
rule (OIR), access control policy, or other
mechanism.
hard attribute An object attribute defined in a Java class.
hard type An object type defined in a Java class. Hard types
are typically created in java classes using
annotations and may extend out-of-the-box
Windchill business object classes.
object type A Java class or subtype defining the attributes and
behavior of the business object(s) you want to
create.
global attribute An attribute of the object defined in the Windchill
Type and Attribute Management client. These
attributes are not defined in the Java business
object class and are stored in database tables

Constructing Wizards 895


Term Definition
separate from the table for the business class.
subtype An object type defined using the Type and
Attribute Management utility rather than in a Java
class. subtypes may extend other soft types but all
have a hard type as their root type.
target object The object you are creating in your wizard.

Solution Elements
Element Type Description
JSPs
The following jsp and jspf files can be used to create and display components
common to many create wizards. Unless otherwise noted, they are located in the
<Windchill>/codebase/netmar kets/jsp/object and <Windchill>/codebase/netmar
kets/jsp/components directories.
createEditUIText jsp file Contains some UI text common
to create and edit wizards.
includeWizBean jsp file Defines the
CreateAndEditWizBean called
during the generation of jsp
pages to access wizard data.
Beans
CreateAndEditWizBean Java class This bean is available to your
jsps if you include the
includeWizBean jspf file. It has
getter methods for wizard data
set by the initializeItem tag such
as the operation, default
container, the base type, and so
forth.
Javascript
validateCreateLocation A javascript method you can
specify on the onClick
parameter of the wizard action
for wizards that can be launched
from a folder browser toolbar.
This checks to make sure that
the user does not have more
than one folder checked and that
the user has not checked an

896 Customization Guide


Element Type Description
object that is not a folder. If
either is the case, a popup error
message is displayed.
Location: <Windchill>/
codebase/netmar kets/javascript/
util
Java Classes
You can use the classes below to help create and process your wizard. They are
located in the <Windchill>/codebase/WEB- INF/lib/wncWeb.jar file.
CreateAndEditModelGetter Java class A class that may be called via a
getModel tag to generate the
data for property panels and
attributes tables in create
wizards.
CreateObjectFormProcessor Java class A class that may be used or
extended to process your wizard
form data. Extends
DefaultObjectFormProcessor.
DefaultObjectFormProcessor- Java class A class that may be extended to
Delegate implement various processing
subtasks.
ObjectBean Java class A container for the form data
specific to one target object and
for the data common to all
objects. Provides methods to
retrieve the form data for the
associated object. A wizard
creating only one object will
have only one ObjectBean.
FormResult Java class; A class used to pass method
runs in the results between server processor
Method methods and from the server to
Server and the WizardServlet.
client

Procedure — Creating Your Wizard


You will need to perform the following tasks to create your wizard:
• Create an Action for the wizard on page 898
• Create a main jsp file for your wizard on page 898

Constructing Wizards 897


• Create your first custom step on page 899
• Select Reusable Steps on page 900

Create an Action for the wizard


You will need an action to launch your new wizard. For more details on the
options available for this action see the Wizard Processing on page 866. A simple
action could look like this:
<objecttype name="Novel">
<action name="create">
<command class="com.ptc.core.components.forms.CreateObjectFormProcessor"
method="execute"
url="netmarkets/jsp/carambola/customization/examples/wizard/
wizardExampleTwo.jsp"
windowType="popup"/>
</action>
</objecttype>

Note
If you follow the standard naming convention for actions and place your jsp in
the <objecttype>\<actionname>.jsp location you do not need the url parameter.
The pretend object types for the examples do not follow that in order to avoid
cluttering your system.

We recommend that you name your action (and main wizard jsp file) “create.” If
you will have more than one create action for your objecttype based on launch
point or other criteria, you can add a suffix to the action name to qualify it, as
shown below:
createFrom<launch point>
Example: createFromWorkspace
create<type of object>
Example: createSharedDocument
Add this action to an action model so that you can access it on your system.

Create a main jsp file for your wizard


You will need to create a jsp which describes your create wizard. To start with we
will put in just the wizard tag. This does not specify enough information for the
wizard to work but at this point you can click the action and see the wizard open.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

898 Customization Guide


<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:wizard title="Create Literature">


</jca:wizard>

<%@include file="/netmarkets/jsp/util/end.jspf"%>
At this point, if you launch your wizard, you should see the message “No Valid
Actions to Display” as we have not yet defined any steps.
For additional information on the customizations you can make to your main
wizard jsp see the Wizard Processing on page 866 and Sample Code on page 911.

Create your first custom step


A custom wizard step is also made up of an action and a jsp.
Action:
<action name="createNovelStep">
<label>Welcome to your Create Novel Wizard</label>
<command url="netmarkets/jsp/carambola/customization/examples/
wizard/createNovelStep.jsp"
windowType="wizard_step"/>
</action>

Initial JSP content: Hello World.


Update the WizardTag to include your step:
<jca:wizard title="Create Literature">
<jca:wizardStep action="createLiteratureStep" type="fakeLiterature"/>
</jca:wizard>

Constructing Wizards 899


At this point you have created a simple wizard and when you launch it you should
see:

You can now develop your own jsp files for your unique steps using the same
table, property panel, and javascript components used in the jsp files for common
steps.

Select Reusable Steps


When you are unable to use one of the out of the box wizards for you object type,
you can still reuse some of the out of the box steps.
For this example, we will add the defineItemAttributesWizStep and the
attachments step. For full details on all the options available for these steps see
Attachments on page 337 and Customizing Reusable Wizard Steps on page 928.
Update the create.jsp to include these steps:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:initializeItem operation="${createBean.create}" baseTypeName=


"wt.doc.WTDocument|org.example.FakeLiterature"/>
<jca:wizard buttonList="DefaultWizardButtons" helpSelectorKey="AssignView_help"
title="Create Literature">
<jca:wizardStep action="createLiteratureStep" type="fakeLiterature"/>
<jca:wizardStep action="defineItemAttributesWizStep" type="object"/>

900 Customization Guide


<jca:wizardStep action="attachments_step" type="attachments" />
</jca:wizard>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

Note
For the defineItemAttributesWizStep we also had to include the initializeItem
tag to setup the type we are creating. For more details on this tag and on the
other options available when using this step see Customizing Reusable Wizard
Steps on page 928.

At this point your wizard can create FakeLiterature objects. There are many
variations on this basic setup. For more information see the customizations below,
the sample code below, the Wizard Processing on page 866 and Customizing
Reusable Wizard Steps on page 928.

Customization Points

Creating Your Form Processor and Form Processor


Delegates
This section assumes you are familiar with the standard wizard processing
framework described in the Wizard Processing on page 866.

Constructing Wizards 901


The class
com.ptc.core.components.forms.CreateObjectFormProcessor
is available as a default form processor for wizards creating Persistable objects.
This class may be extended as necessary to meet your purposes.

The CreateObjectFormProcessor does the following:

902 Customization Guide


preprocess() method
• extracts all of the ObjectBean form data that has a special name attribute as
described in Attribute Tables on page 737.
• creates a TypeInstance for the new object and applies the attribute values from
the form to it, validating the values against any constraints defined for the
attributes in the Type and Attribute Management utility
• converts the TypeInstance into a Persistable and sets it as the “object” attribute
on the ObjectBean
• calls super.preProcess() to call the preprocess() methods of any
FormProcessorDelegates registered for the wizard
doOperation() method
• calls super.doOperation() to call the doOperation() methods of any
FormProcessorDelegates registered for the wizard
• calls PersistenceHelper.manager.store() to store the Persistable in the database
• getSuccessFeedbackMessage() method (called by setResultNextAction())

◆ This method is called when FormResult is SUCCESS.This constructs
the FeedbackMessage see Inline Messaging for more information on
configuring message content.
In the UI this inline message is shown as below for single object creation:

For Multi-object create the UI as shown below:

Note the CreateObjectFormProcessor does not implement postProcess() or


postTransactionProcess() methods so these are inherited from the
DefaultObjectFormProcessor. See the javadoc for more information.

Constructing Wizards 903


If you are extending an existing Windchill business class, there may be a
processor specific to that class that you should use or extend instead of
CreateObjectFormProcessor. These are shown in the table below. Consult the
javadoc for these classes for more information on their behavior.
If your class Use processor class:
extends:
WTPart If creating a wizard to be launched from a workspace:
com.ptc.windchill.enterprise.part.forms.CreatePartFromW
orkspaceFormProcessor
If creating a wizard to be launched from the Edit Structure
client:
com.ptc.windchill.enterprise.part.forms.CreatePartFromTa
bularInputProcessor
All other single-object creation wizards:
com.ptc.windchill.enterprise.part.forms.
CreatePartFormPro cessor
WTDocument For creating a document from a template:
com.ptc.windchill.enterprise.doc.forms.CreateDocFromTe
mplateFormProcessor
For creating a document template:
com.ptc.windchill.enterprise.doc.forms.CreateDocTemplat
eFormProcessor
For all other single-object create wizards:
com.ptc.core.windchill.enterprise.doc.forms.CreateDocFor
mProcessor
WTChangeIssues com.ptc.windchill.enterprise.change2.forms.processors.
Cre ateProblemReportFormProcessor
WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.processors.
Cre ateChangeRequestFormProcessor
WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.processors.
Cre ateChangeNoticeFormProcessor
WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.processors.
Cre ateChangeTaskFormProcessor
WTVariance com.ptc.windchill.enterprise.change2.forms.processors.
Cre ateVarianceFormProcessor.
If the behavior of one of the provided form processors meets your needs, you do
not need to write your own processor, just specify that processor as the value of
the class attribute of the command subtag of your wizard action. If it does not

904 Customization Guide


meet your needs, you should write a subclass of it to process the wizard form data.
Note that you do not need to create your own processor if you only want to
provide special code for setting an attribute. In that case, you need only to write a
FormProcessorDelegate to handle this task. Remember to register the
FormProcessorDelegate in a hidden form field and make sure that the attribute
input field does NOT have a special name attribute that will be recognized by the
CreateObjectFormProcessor. See Attribute Tables on page 737 for more
information.
Note that you do not need to create your own processor if you only want to
provide special code for setting an attribute. In that case, you need only to write a
FormProcessorDelegate to handle this task. Remember to register the
FormProcessorDelegate in a hidden form field and make sure that the attribute
input field does NOT have a special name attribute that will be recognized by the
CreateObjectFormProcessor.
The FormProcessorDelegate should extend from
DefaultObjectFormProcessorDelegate. NumberPropertyProcessor and
KeepCheckedOutDelegate are examples of custom FormProcessorDelegates
available out of the box. The class structure for FormProcessorDelegates is shown
below.

If you create your own processor, be aware that its preProcess() method will be
called by the standard validator classes after each wizard step. Make sure you do
not modify the database in this method.
Here are some of the more common cases where you may need to write your own
ObjectFormProcessor class and the methods you would override to handle them:

Constructing Wizards 905


Case 1: You need to perform a different action when the wizard
closes.
For example, perhaps you want to load a new page when the wizard closes instead
of refreshing the launch page. Or, perhaps your wizard can be launched from
multiple points and you want refresh the launch page in one case and load a new
page in another case.
Solution: Subclass the out-of-the-box processor and override the
setResultNextAction method. From the NmCommand.getCompContext() method
you can obtain information about the launch context of the wizard. Here is an
example of how this is done for the create baseline client:
String compContext = cb.getCompContext();
if (compContext != null) {
try {
NmContext compContextObj = NmContext.fromString(compContext);
Stack<NmContextItem> contextItems = compContextObj.getContextItems();
for (NmContextItem contextItem : contextItems) {
String action = contextItem.getAction();
if ("addToBaseline".equals(action) ||
"addToBaselineSingle".equals(action) ||
"addToBaselineStep".equals(action)) {

< set some next action >


}
}
.
.
.

Note that if your wizard is launched from a table and you have specified “ajax=
”row”” on the wizard action, you must set the refreshInfo attribute on the
FormResult to tell the system what rows to refresh. Typically, the attributes of the
DynamicRefreshInfo object will be as follows:
action = NmCommandBean.DYNAMIC_ADD
oid = the NmOid of the object that was created
location = the NmOid of the table object containing the new row. Typically, this
will be a folder.
If you have used an ajax attribute of “page” or “component” you do not need to
set the refreshInfo attribute.
See the Customizing the UI with Ajax on page 291 section in the Customizing
HTML Clients Using the Windchill JSP Framework on page 289 chapter and the
javadoc for the FormResult and FormProcessingStatus classes for more
information.

906 Customization Guide


Case 2: You need to do some post processing after the object is
persisted.
For example, change object wizards have a dialog to allow the user to submit the
object to workflow immediately after creation. For this, they need to perform
another operation after the object is created. In some cases, this kind of
requirement can be handled by creating an ObjectFormProcessorDelegate for the
input field and implementing a postProcess() or postTransactionProcess() method
on it that will be called automatically by the infrastructure. However, in other
cases you may prefer for your form processor to handle this. For example, you
cannot control the order in which FormProcessorDelegates are called so if
operation ordering is a requirement you would need to do the operations in the
form processor.
Solution: Subclass the CreateObjectFormProcessor and override the postProcess()
or postTransactionProcess() method (which are inherited from
DefaultObjectFormProcessor) to perform your operation.
(Note that if you put a “Keep checked out checkbox” in your wizard by including
the keepCheckedOutCheckbox.jspf file, this will be processed automatically by
the KeepCheckedOutDelegate. You do not need to handle this).

Case 3: You need to use a special API to persist the object.


For example, change objects are persisted using the StandardChangeService2
class, which handles some life cycle and foldering tasks in addition to persisting
the object.
Solution: Subclass the out-of-the-box processor and override the doOperation()
method. In your method you can’t call the super method, but you should still make
sure the doOperation() method of any registered FormProcessorDelegates are
called. You can accomplish that by calling the processDelegates() method
inherited from DefaultObjectFormProcessor. For example:
FormResult doOperationResult = new FormResult();
doOperationResult.setStatus(FormProcessingStatus.SUCCESS);
doOperationResult = processDelegates (DO_OPERATION, clientData,
objectBeanList);
if (!continueProcessing(doOperationResult)) {
return doOperationResult;
}

try
{
< persist the object >
}
catch(WTException e)
{
< do error handling >

Constructing Wizards 907


}
return doOperationResult;

Note that delegates are called after form processor tasks in most processing
phases, but in the doOperation phase they should be called before the form
processor does its tasks. This is to allow delegates to perform operations after all
attributes have been set but before the object is persisted.

Case 4: You need to set attributes on the new object programmatically


You may have attributes that you need to set on the object before it is persisted
which are not exposed in the UI.
Solution: There are alternate ways to handle this.
• Create a FormProcessorDelegate and implement its preProcess() method. In
that method, set the attribute values on the object in the ObjectBean. Add a
hidden form field to your wizard jsp specifying the name of your delegate,
which will be automatically instantiated by the framework. For example:
<input type="hidden" name="
${createBean.formProcessorDelegateConstant}" value=" <path name
of your delegate> ">
• Subclass the out-of-the-box processor and override the preProcess() method.
You can call the createItemInstance() method of the superclass to create the
Persistable for you and then set the attributes you desire on the Persistable. For
example:
FormResult preProcessResult = new
FormResult(FormProcessingStatus.SUCCESS);
for (ObjectBean objBean: objectBeans) {
FormResult objectResult =
new FormResult(FormProcessingStatus.SUCCESS);
objBean.setObject(createItemInstance(clientData,
objBean, objectResult));
preProcessResult =
mergeIntermediateResult(phaseResult, objectResult);
if (!continueProcessing(preProcessResult)) {
return preProcessResult;
}
Object newObj = objBean.getObject();

< set additional attributes on the new object here>


}

// Call processDelegates() which will call registered


processor delegates
delegatesResult = processDelegates(DO_OPERATION,
clientData, objectBeanList);

908 Customization Guide


preProcessResult =
mergeIntermediateResult(preProcessResult, delegatesResult);

if (!continueProcessing(preProcessResult)) {
return preProcessResult;
}

Note that the above example is written so that the processor could be used for
wizards creating more than one object.
In general, it is probably preferable to use the delegate approach for setting your
attributes rather than the subclass approach as it will insulate you from any
modifications that might be made to the CreateObjectFormProcessor preprocess()
method in the future.

Limitations
When laying out the steps and attributes of a Windchill object creation wizard, it
is important to keep in mind the interdependencies between the object type,
container context, organization context, folder location, default life cycle, and,
possibly, other attributes of your new object. These interdependencies can result
from:
• type definitions
• object initialization rules (OIRs)
• access control policies (ACLs)

Type Definitions
Many wizards allow a user to create one of several object subtypes derived from a
given base type. You can define soft subtypes and global attributes in the Attribute
and Type and Attribute Management utility at the organization or site level. This
means that the organization container of the object must be known before the list
of available object types is displayed and the input fields for global attributes are
rendered. Also, the default type for some Windchill business types is determined
by preferences which can be set at the container, organization, and site levels so
these must also be known

Access Control Policies


The object types which a given user has permission to create are defined by the
access control policies for the administrative domain to which the object belongs
and by ad hoc rules. Administrative domain is typically, although not always,
determined by the object’s folder. In addition, access rules can be further refined
based on the initial state of the default life cycle for the object type.

Constructing Wizards 909


Object Initialization Rules
Object initialization rules are defined by object type at the site, org, and/or
container levels. Such rules can dictate whether or not the server assigns an
attribute’s value or it is entered by the user; what the default value of an attribute
is, if any; whether the value is editable; and other display characteristics of an
attribute. Attributes for which OIRs are defined in the out-of-the-box product
include:
• Organization
• Number
• Name (variant parts only)
• Folder location
• Life cycle template
• Team template1
• Versioning scheme
These OIRs may be modified or deleted by customizers and additional OIRs for
other attributes may be written by customizers. These actual and potential
interrelationships between properties are illustrated in the following diagram,
where the shaded boxes represent wizard elements.

As you can see from this diagram, the relationships between various object
properties can become complex and circular. For example, to display an input
field for folder location you must know the default folder set by the OIR, which
requires knowledge of the type of object being created. However, to display a
picker with the available object types you must know the administrative domain,
which is determined by the folder.

910 Customization Guide


This document will refer to attributes whose values affect the values of other
attributes as “driver attributes.” The affected attributes will be called “dependent”
attributes. Driver attribute values must be determined “upstream” of any attribute
values dependent on them. By “upstream” we mean either from the wizard launch
context, entered by the user on a previous wizard step, or, in some cases, entered
by the user in a table or panel on the same step but above that of dependent
attributes. Any time a driver attribute value is changed the downstream parts of
the wizard must be refreshed if they contain dependent attributes and have been
preloaded. (see Loading the wizard step content when it is visited on page 853 for
information on preloaded and non-preloaded steps.)
The exact nature of the interrelationships between attributes depends on how a site
defines its OIRs and access control policies. The wizards delivered by PTC are set
up to gather attribute information in an order consistent with the access control
rules and OIRs defined out-of-the-box and with anticipated common
customizations. They make certain assumptions about how a customer site has set
up its OIRs and ACLs. These include the following:
• A site has OIRs defining the default life cycle for different object types
• OIRs are only defined for base types such as WTPart or WTDocument and not
defined differently for subtypes of the base types
If these assumptions do not hold or your site introduces additional attribute
dependencies via its OIRs or access control policies, the layout of wizard steps
and attributes may need to be customized to ensure that driver attributes are
always upstream of their dependent attributes.

Sample Code

Main JSP for the New Baseline Wizard


Filename: /codebase/netmarkets/jsp/baseline/createBaseline.jsp
This is a one-step wizard so it uses the “NoStepsWizardButtons” actionmodel
defined in codebase/actionmodels.xml.
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<script src='netmarkets/javascript/baseline/baseline.js'></script>

<jca:initializeItem operation="${createBean.create}"
baseTypeName="wt.vc.baseline.ManagedBaseline"/>

<jca:wizard buttonList="NoStepsWizardButtons"
helpSelectorKey="baseline.createHelp">

Constructing Wizards 911


<jca:wizardStep action="setBaselineAttributesStep"
type="baseline" />
</jca:wizard>

%@include file="/netmarkets/jsp/util/end.jspf"%

Main JSP for the New Product Wizard


Filename: /codebase/netmarkets/jsp/baseline/create.jsp
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt"
prefix="fmt"%>

<%@ page import="com.ptc.windchill.enterprise.part.PartConstants"


%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<fmt:setBundle
basename="com.ptc.windchill.enterprise.product.productResourceClie
nt"/>

<jca:initializeItem operation="${createBean.create}"
baseTypeName="wt.pdmlink.PDMLinkProduct"

<jca:wizard helpSelectorKey="PDMAdminProdCreate_Help"
buttonList="DefaultWizardButtonsNoApply">

<jca:wizardStep action="defineItemWizStep" type="object" />


<jca:wizardStep action="setAttributesWizStep" type="object" />

</jca:wizard>

<SCRIPT language="javascript">
.
.
.

</SCRIPT>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

912 Customization Guide


Packaged Samples
Many out of the box Windchill wizards make use of these steps and can be
referenced as examples.

Basic Create Wizard


This is a simple example create wizard that creates an object of the Literature
type. The Literature Type is a Softtype of WTDocument which can be loaded
automatically. You will be prompted to load the type anytime you attempt to
access an Example that relies on the type. There are very few customizations in
this example but it does show how you can customize the type picker. The
attributes being displayed on the attributes step are loaded for you when you load
the type and can be configured through the Type and Attribute Management utility.

Location of Example
To navigate to this example in the produce go to Customization ▶ Component
Catalog ▶ Wizard ▶ Wizard Component ▶ Examples ▶ Basic Create Wizard.

Actions for this Example


• create, fakeLiterature
• setContexWizStep, object
• defineItemAttributesWizStep, object

Action Models for this Example


• None

Files Used in This Example


• \netmarkets\jsp\carambola\customization\examples\wizard\createLiterature.jsp
• /config/actions/Carambola-actions.xml

Constructing Wizards 913


Building Wizards to Edit a Single Object
Objective
You need to develop a wizard to allow a user to edit the attributes of a Windchill
business object and update the object in the database.

Background
Object edit wizards are typically launched by an action labeled “Edit” or “Check
Out and Edit.”
Developing a wizard to edit a business object is very similar to developing a
wizard to create that business object. Many of the components you will use are the
same. However, there are a few differences between create and edit wizards and
some of these require different components or different component configuration.
These differences include the following:
• Edit wizards do not allow users to change the container context, owning
organization, folder location, or type of an object
• Some edit wizards do not allow the user to change the identity attributes on the
master of an object (for example: name and/or number). Such changes must be
made via a Rename or Edit Common Attributes client. Other master attributes
may not be editable also.
• If the object being edited is a Workable and it is not checked out by the user
when the edit wizard is launched, the wizard should check out the object
automatically.
• The attribute input fields in edit wizards are pre-populated with the values that
exist in the database for the object rather than the default values defined in the
Java class or Attribute and Type and Attribute Management utility.
• Edit wizards for Workables have different navigation buttons. Instead of an
OK button they have Save and Check In buttons. The former saves the
changes to the working copy of the object without checking in or iterating it.
The second creates and checks in a new iteration of the object. Also, the
Cancel button pops up a message reminding the user that the object will
remain checked out.
Components available specifically for editing include:
• jsp and jspf files for wizard steps that are common to multiple wizards
• custom HTML tags for managing wizard data and displaying elements on the
page
• Java classes for processing the wizard data after the user submits the wizard

914 Customization Guide


Scope/Applicability/Assumptions
This section assume you have created a custom Persistable business object class or
subtype and you want to develop a wizard that will allow users to edit the
attributes of one instance of that object type.
The information in this document is applicable to editing both Workable and non-
Workable objects and both Typed and non-Typed objects.
This document describes the reusable common components upon which most
Windchill edit wizards are based. If your custom type extends an existing
Windchill business class, such as WTPart, WTDocument, or WTChangeIssue,
there may be components more specific to those classes that could or should be
used instead of the components described herein. These class-specific components
are built on top of the common components described in this document. A
discussion of those class-specific components is beyond the scope of this
document.
Be aware that you do not necessarily need to develop your own wizard to edit
instances of a custom type. If your type is a modeled or soft subtype of a
Windchill business class such as WTPart, WTDocument, or Problem Report
(WTChangeIssue) , you may be able to use the out-of-the-box edit wizard for your
purposes. The out-of-the-box wizards will automatically display input fields for
hard and global attributes of custom subtypes on the Set Attributes step.
Attributes in the table will be ordered as follows:
• Out-of-the-box attributes, ordered as listed in the JSP file
• Custom modeled attributes, ordered alphabetically by display name
• Custom global attributes, ordered alphabetically by display name
If you want to order the attributes on this step differently or require additional
fields on this step, you will need to create a new jsp for this step specifically for
your subtype. However, you can still use the Edit Part wizard.
If you want to add additional steps to an existing wizard , you will need to develop
a custom wizard , but may be able reuse many of the steps/components of the
existing wizard.

Intended Outcome
Add a single- or multi-step HTML wizard to the product that allows a user to
update a business object in the database. The arrangement of steps and
presentation of attributes within the wizard should be similar to that of other
Windchill wizards to provide a consistent user experience.

Constructing Wizards 915


Solution
Use common jsp, tag, JavaScript, and Java class components built on top of the
jsp wizard framework to create a wizard for capturing user input and for
processing that input and creating the object in the database.

Prerequisite knowledge
To achieve this objective, you need to be familiar with theBuilding Wizards to
Create a Single Object on page 892 topic, especially . on page 894

Solution Elements
Element Type Description
Tags
Note
All of the tags in the Solution Elements on page 896 section of the Building
Wizards to Create a Single Object on page 892 topic are also applicable to
edit wizards. This tag is in addition to those.
See Building Wizards to Create a Single Object on page 892 for more
information. (The Solution Elements on page 896 section.)
autoCheckOutItem Tag Checks out the object to the current user if
it is not already checked out. Adds an
object reference to the working copy as an
attribute of the current HTTPRequest, as a
parameter in HTTPRequestData parameter
map of the NmCommandBean, and as a
hidden field in the DOM. The key to the
working copy value is
CreateAndEditWizBean.WORKING_COP
Y_REF_PARAMETER_NAME.
This tag should be put in the main JSP for
the wizard immediately below the
initializeItem tag.
Tag library: <Windchill>/codebase/WEB-
INF/tlds/wo rkinprogress.tld
Tag handler: com.ptc.windchill.enterprise.
wip.tags.Auto CheckOutObjectTag
Beans
CreateAndEditWizBean Java class This bean is available to your jsps if you
include the includeWizBean jspf file. It has
getter methods for wizard data such as the

916 Customization Guide


Element Type Description
operation (create or edit) and working copy
object reference.
Java Classes You can use the classes below to help
create and process your wizard. They are
located in the <Windchill>/codebase/WEB-
INF/lib/wnc Web.jar file.
CreateAndEditModel- Java class A class that may be called via a getModel
Get ter tag to generate the data for property panels
and attributes tables in edit wizards.
DefaultEditFormProcess Java class A class that may be used or extended to
or process wizard form data for nonWorkable
objects. Extends
DefaultObjectFormProcessor.
EditWorkableFormProc Java class A class that may be used or extended to
essor process wizard form data for Workable
objects. Extends
DefaultObjectFormProcessor.

Procedure — Creating an Edit Wizard


The following tasks need to be performed to create the wizard:
• Create an Action for the Wizard on page 917
• Create a Main jsp for Your Wizard on page 918
• Create Custom Steps as Needed on page 919
• Select Reusable Steps on page 919
The tasks shown in bold are always required. The other tasks may or may not be
needed, depending on the requirements of the wizard.
If there are attributes in your wizard that cannot be displayed by the standard
Windchill dataUtilties, gui components, and renderers you also may need to write
Java classes for those functions.

Create an Action for the Wizard


An action is needed to launch your wizard. This task is very similar to creating an
action for a create wizard. The only difference is that your form processor,
specified on the class attribute of the command tag, will typically be one of the
processors listed in Solution Elements on page 916 or a subclass of one of those
classes.

Constructing Wizards 917


For more details on the options available for this action see <action>.xml
attributes on page 847. A simple action could look like this:
<objecttype name="FakeLiterature">
<action name="editLiterature">
<command class="com.ptc.core.components.forms.EditWorkableFormProcessor"
method="execute"
url="netmarkets/jsp/carambola/customization/examples/
wizard/exampleLiteratureEdit.jsp"
windowType="popup"/>
</action>
</objecttype>

It is recommended that the action (and main wizard jsp file) be named “edit.” If
there will be more than one edit action for the objecttype based on launch point or
other criteria, add a suffix to the action name to qualify it, as shown below:
editFrom<launch page or table> Ex: editFromAttributesTable
edit<name for a subset of attributes Ex: editAnnotations
being edited>

Add this action to an action model so that it can be accessed it on the Windchill
system.

Create a Main jsp for Your Wizard


Next, create a jsp which describes the edit wizard. At a minimum it is generally
necessary to put in just one step for editing attributes. For more details on
advanced configuration of the edit attributes step see Customizing Reusable
Wizard Steps on page 928.
<%-- This wizard is an example of using a read-only attributes panel in
an Edit wizard. --%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ taglib prefix="wip"
uri="http://www.ptc.com/windchill/taglib/workinprogress"%>
<%-- This tag checks out the document and sets magical form inputs
and data on the command bean. This makes sure that the command
bean's get oid methods return the oid of the working copy. --%>
<wip:autoCheckOutItem />
<jca:initializeItem operation="${createBean.edit}"/>
<jca:wizard buttonList="EditWizardButtons"
helpSelectorKey="DocMgmtDocEdit"
title="Example Literature Edit with Attribute Panels">
<jca:wizardStep action="editAttributesWizStep"
type="object" embeddedHelp="This is an example of a
simple Edit wizard. This wizard demonstrates how to
change the attributes in the read only

918 Customization Guide


attribute panel."/>
</jca:wizard>
<%@include file="/netmarkets/jsp/util/end.jspf"%>

AutoCheckOutItem Tag
If your target object is a Workable and your wizard can be launched for an object
that is not already checked out via a “Check Out and Edit” or other action, you
should include an autoCheckOutItem tag in your main jsp immediately below
the initializeItemTag.
<%@ taglib prefix="wip"
uri="http://www.ptc.com/windchill/taglib/workinprogress"%>
...
<wip:autoCheckOutItem/>
This tag will check out the object to the current user before opening the wizard.

Button Set
Typically, wizards for editing Workable objects will use one of the following two
button sets:
• “EditWizardButtons” (multiple-step wizards)
• “NoStepsEditWizardButtons” (single step wizards)
These include Save and Check In buttons.
For editing nonWorkable objects one of the following is usually used:
• DefaultWizardButtonsNoApply (multiple-step wizards)
• NoStepsWizardButtons (single step wizards)
These are all defined in <Windchill>/codebase/config/actions/
actionmodels.xml.

Create Custom Steps as Needed


Custom steps can also be created for edit wizards using the same techniques that
are described in Wizard Processing on page 866 and Building Wizards to Create a
Single Object on page 892.

Select Reusable Steps


In Create a Main jsp for Your Wizard on page 918 we already selected the
reusable step to edit object attributes. For more details on customizing this step
and for information on additional reusable steps available see Customizing
Reusable Wizard Steps on page 928.

Constructing Wizards 919


Customization Points

Creating Your Form Processor and Form Processor


Delegates
Two form processor classes are available for edit wizards:
com.ptc.core.components.forms.DefaultEditFormProcessor - for nonWorkable objects

com.ptc.core.components.forms.EditWorkableFormProcessor- for Workable objects

These classes may be extended as necessary to meet your purposes.

Both of these processors do the following:

920 Customization Guide


preProcess() method
• same as the preprocess() method of the
CreateObjectFormProcessor except that it creates a TypeInstance
for a persisted object

doOperation() method
• calls super.doOperation() to call the doOperation() methods of
any FormProcessorDelegates registered for the wizard
• calls PersistenceHelper.manager.save() to store the Persistable in
the database
The setResultNextAction() method is deprecated. Instead, the
FormProcessor should return a list of the Oids that were affected by the action
(if any), and let the components displayed in the UI request updates from the
server, as necessary.
If you are extending an existing Windchill business class, there may be a
processor specific to that class that you should use or extend instead of the
DefaultEditFormProcessor or EditWorkableFormProcessor.
These are shown in the table below. Consult the javadoc for these classes for more
information on their behavior.
If your class Use processor class
extents
WTChangeIssue com.ptc.windchill.enterprise.change2.forms.processors.Ed
itProblemReportFormProcessor
WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.processors.Ed
itChangeRequestFormProcessor
WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.processors.Ed
itChangeNoticeFormProcessor
WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.processors.Ed
itChangeTaskFormProcessor
WTVariance com.ptc.windchill.enterprise.change2.forms.processors.Ed
itVarianceFormProcessor
If one of the provided form processors meets your needs, you do not need to write
your own processor — just specify that processor as the value of the class attribute
of the command subtag of your wizard action. If they do not meet your needs, you
should write a subclass of one of them to process the wizard form data. See
Creating Your Form Processor and Form Processor Delegates on page 901 for
examples of cases where you may need to implement your own
processor.netmarkets/jsp/components/beginWizard.jspf

Constructing Wizards 921


If you create your own processor, be aware that its preProcess() method will
be called by the standard validator classes after each wizard step. Make sure you
do not modify the database in this method.

Sample Code

Main JSP for the Edit Product Wizard


Filename: <Windchill>/codebase/netmarkets/jsp/product/editProductWizard.jsp
Notes: This is a one-step wizard
<%@ page
import="com.ptc.windchill.enterprise.product.ProductClientRB"
%>
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components"%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>
<%@ include
file="/netmarkets/jsp/components/createEditUIText.jspf"%>

<%--> Get resource bundle. <--%>


<fmt:setLocale value="${localeBean.locale}"/>
<fmt:setBundle
basename="com.ptc.windchill.enterprise.product.productResource
Client" />

<fmt:message var="attributeStepLabel"
key="product.editProductAttributesWizStep.title" />

<jca:initializeItem operation="${createBean.edit}"/>

<jca:wizard buttonList="NoStepsWizardButtons"
helpSelectorKey="PDMAdminProdEdit_help">

<%-->
This step uses the common action definition. The JSP file for
the step is, however, product-specific and hooked up using
PartManagement-typedservices-properties.xconf
<--%>
<jca:wizardStep action="editAttributesWizStep" type="object"
label="${attributeStepLabel}"/>
</jca:wizard>

922 Customization Guide


%@include file="/netmarkets/jsp/util/end.jspf"%

Main JSP for the Edit Part Wizard


Filename: <Windchill>/codebase/netmarkets/jsp/part/
edit.jsp
Notes:
• This can be a single- or multi-step wizard, depending on the product modules
installed
• Illustrates how to include the Set Classification Attributes and Attachments
steps.
• This page calls the js function “onloadEditPart” when the page loads.
This function calls “loadClassificationStep” to load the
classification step if the part is classified and may perform some other UI
configurations depending on the wizard launch point.
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ taglib prefix="wip"
uri="http://www.ptc.com/windchill/taglib/workinprogress"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt"
prefix="fmt"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/attachments"
prefix="attachments" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>


<%@ include
file="/netmarkets/jsp/components/includeWizBean.jspf"%>
<%@ include
file="/netmarkets/jsp/components/createEditUIText.jspf"%>

<%-->
PartHelper.js contains the “onloadEditPartWizard” method
<--%>
<script language="JavaScript"
src="netmarkets/javascript/part/PartHelper.js"></script>

<% if(InstalledProperties.isInstalled(InstalledProperties.SCMI)) {
%>
<attachments:fileSelectionAndUploadApplet
forceApplet='${param.addAttachments != null }'/>
<% } %>

Constructing Wizards 923


<%-->

The onload javascript method dynamically loads the classification step if the
part is classified. It also disables the check in button when the wizard is
launched from a workspace.

<--%>

<script language="Javascript">

Event.observe(window, 'load', onloadEditPartWizard);

</script>

<fmt:setBundle
basename="com.ptc.windchill.enterprise.part.partResource"/>

<%--> Reuse the same labels as for create part <--%>

<fmt:message var="editAttributesWizStepLabel"
key="part.createPartWizard.SET_ATTRIBUTES_WIZ_STEP_LABEL" />

<fmt:message var="attachmentsWizStepLabel"
key="part.createPartWizard.ATTACHMENTS_WIZ_STEP_LABEL" />

<jca:initializeItem operation="${createBean.edit}"/>

<% if (request.getParameter("newInWorkspace") == null) { %>

<%--> The part is not new in workspace. Do autoCheckout <--%>

<wip:autoCheckOutItem/>

<% } %>

924 Customization Guide


<% if ((request.getParameter("newInWorkspace") != null) ||
(request.getParameter("checkedOutInWorkspace") != null)) { %>

<script
language="Javascript">newOrCheckedOutInWorkspace=true</script>

<% } %>

<%--Only if SCMI or PartsLink is installed do we use a multi-step wizard<--%>

<% if (InstalledProperties.isInstalled(InstalledProperties.SCMI) ||

InstalledProperties.isInstalled(InstalledProperties.PARTSLINK)) { %>

<c:set var="buttonSet" value="EditWizardButtons"/>

<% } else { %>

<c:set var="buttonSet" value="NoStepsEditWizardButtons"/>

<% } %>

<jca:wizard buttonList="${buttonSet}"
helpSelectorKey="PartEdit_help">

<%-->

The Set Attributes step uses the common action definition. The JSP file for the
step is, however, part
specific and hooked up using PartManagement-typedservices-properties.xconf

<--%>

<jca:wizardStep action="editAttributesWizStep"
label="${editAttributesWizStepLabel}" type="object"/>

<jca:wizardStep action="setClassificationAttributesWizStep" type="part"/>

Constructing Wizards 925


<%-->

The attachments step will get enabled or disabled based on the


AttachmentsStepAction
Validator hooked up to it

<--%>

<jca:wizardStep action="attachments_step"
label="${attachmentsWizStepLabel}" type="attachments" />

</jca:wizard>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

Additional Resources

Related Package/Class Javadoc


com.ptc.core.components.forms.DefaultEditFormProcessor
com.ptc.core.components.forms.EditWorkableFormProcessor
Also see the Sample Code on page 911 section in Building Wizards to Create a
Single Object on page 892.

Packaged Samples
This section contains information on the sample code that is provided within the
system.

Basic Edit Wizard


Location of Example
This example can be viewed in the Windchill product by navigating to
Customization -> Component Catalog -> Wizard -> Examples section -> Basic
Edit Wizard

926 Customization Guide


Actions for this Example
• editLiterature, fakeLiterature
• editAttributesWizStep, object

Action Models for this Example


• None

Files Used in This Example


• /netmarkets/jsp/carambola/customization/examples/wizard/
exampleLiteratureEdit.jsp
• com.ptc.mvc.builders.carambola.wizard.LiteratureEditDetailsWizStepBuilder.
java
• /config/actions/Carambola-actions.xml

Constructing Wizards 927


Customizing Reusable Wizard Steps
Overview
You need to develop a wizard to capture user input and from that input create or
edit a Windchill business object in the database. The wizard will have common
steps that already exist in other wizards and should not be duplicated.

Background
Windchill provides many reusable wizard steps that can be configured and added
to a custom wizard.
In many cases reusing a wizard step is as simple as adding the correct wizard step
tag specifying the wizard step action to your wizard tag. This document is not
intended to cover this simplest case. In some cases there can be additional
information required by a step or additional customizations you may want to do
on a step. This document describes a few available reusable steps that have some
additional required information or customization options. This section details
when and how to use these steps.

Scope/Applicability/Assumptions
Assume you have created a custom Windchill business object class or subtype and
you want to develop a wizard that will allow users to create or edit one instance of
that object type in the database.
This document describes common wizard steps that are available for reuse.
Additionally, if your custom type extends an existing Windchill business class,
such as WTPart, WTDocument, or WTChangeIssue, there may be
components more specific to those classes that could or should be used instead of
the components described herein. These class-specific components are built on top
of the common components described in this document. A discussion of those
class-specific components is beyond the scope of this document.

Intended Outcome
Add a preexisting step to the new wizard and configure the step.

Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:
• The Windchill framework for creating wizards, creating custom wizard steps,
and processing wizard data. For more information see:
○ Building Wizards to Create a Single Object on page 892

928 Customization Guide


○ Building Wizards to Edit a Single Object on page 914
These topics have multiple prerequisites of their own which you should also study.
This document will build on this knowledge and provide additional information
on the components available to help you create and process wizards for the
specific purpose of creating a Windchill business object in the database.

Definition of Terms Used


Term Definition
base type A hard or subtype class that is the root
type of the wizard's type picker. If the
wizard does not have a type picker, this
is the type of object that will be created.
The base type is used to look up the
correct JSPs for wizard steps that have
different jsp variants for different
subtypes until a specific type is selected
by the user.
classification attribute An attribute associated with a
classification node that has been
assigned to a part. Classification
Attributes are generally specified and
edited on a separate step from hard and
global attributes.
Context The container (Product, Library,
Project, etc.) in which the object(s) are
being created.
dependent attribute An attribute whose value and/or display
characteristics are wholly or partially
determined by the value of another
attribute (called the "driver attribute")
via an object initialization rule (OIR),
access control policy, or other
mechanism.
driver attribute An attribute whose value drives the
value and/or display characteristics of
another attribute (called a "dependent"
attribute) via an object initialization
rule (OIR), access control policy, or
other mechanism.
hard attribute An object attribute defined in a Java
class.
hard type An object type defined in a Java class.

Constructing Wizards 929


Term Definition
Hard types are typically created in java
classes using annotations and may
extend out-of-the-box Windchill
business object classes.
object type A Java class or subtype defining the
attributes and behavior of the business
object(s) being created.
global attribute An attribute of the object defined in the
Windchill Type and Attribute
Management utility. These attributes
are not defined in the Java business
object class and are stored in database
tables separate from the table for the
business class.
subtype An object type defined using the Type
and Attribute Management utility rather
than in a Java class. Subtypes may
extend other subtypes but all have a
hard type as their root type. The
Literature object created for the
examples at the end of this document is
an example of a subtype.

Reusable Wizard Steps


The following reusable wizard steps are available:
• defineItemAttributesWizStep on page 930
• editAttributesWizStep on page 945
• SetContextWizStep on page 948
• setClassificationAttributesWizStep on page 950
• attachments_step on page 951
• setAccessControlWizStep on page 951

defineItemAttributesWizStep
The body of this step typically contains four sections: a read-only context property
panel, a type picker, and a driver attributes property panel and the editable
attributes panel. It is configured using MVC framework and jsps. An MVC

930 Customization Guide


builder defines the content of and configures the (non-driver) attributes panel in
the step. The context panel, type picker, driver attributes panel, primary content
panel (if any), and other components are configured via jsps. Only the type picker
is required.

• Context panel
Read-only information about the object being created that is derived from the
launch context or entered on previous wizard steps. If the object is
WTContained this typically displays the container for the new object
• Driver attributes
This property panel displays input fields for attributes that can drive the values
of and/or constraints on other attributes to be entered by the user. If a value in
this panel is changed, all subsequent wizard steps are automatically refreshed
based on the new attribute value(s). Therefore it is important to place all driver
attributes in this section.
If the preference Display ▶ Expose Organization is set to true and the object is
OrganizationOwned, this panel should include a picker for the
organization attribute of the object. Although organization id does not drive

Constructing Wizards 931


the value of other attributes out-of-the-box, customers often want to set up
such dependencies.
The object type indicates which other attributes should be included, if any. See
How to create a step with additional driver attributes on page 944 for more
information.
• Editable Attributes Panel
Typically contains all the soft and hard attributes for the object type that were
not entered on previously, except for part classification attributes, which are
entered on a following step.

Note that one of the attributes typically presented in this list is folder location.
Folder location drives administrative domain which, in turn, drives access
control policies which, in turn, drives the list of object types available for
creation by the user. The list of types presented in the type picker is based on a
default folder derived from the launch context. The user could potentially
select a different folder location for which the access control policies vary.
Thus it is possible the user could select a folder for which they do not have
permission to create the selected type. If this happens, an error message will
be displayed when the user clicks OK.
• Checkboxes
This section contains checkboxes to provide processing instructions for the
new object. These include:
Checkbox label Applicability Description
Keep checked out Used for new If checked, the system
RevisionControlled checks out the object
objects after creation
Checkout and download Used for creating If checked, the new
documents from document is checked out
templates and downloaded
Enabled Used for creating If checked, the new
document templates template is immediately
available for use

Solution
Add the defineItemAttributesWizStep to the new wizard and correctly
configure the step.
When to use this step This step is intended for use for creating Typed objects. For
Edit Wizards see editAttributesWizStep.

932 Customization Guide


Solution Elements

Action
The action for this step is:
<action name="defineItemAttributesWizStep" afterVK="setAttributesWizStep"
id="defineItemAttributesWizStep " preloadWizardPage="false" required="true"
resourceBundle="com.ptc.core.ui.componentRB">
<component name=" defineItemAttributesWizStep"
typeBased="true" indowType="wizard_step"/>
</action>
Action file: <Windchill>/codebase/config/actions/actions.xml

Note
The action for this step has a component attribute instead of a command
attribute because it is created using a MVC builder Java class.

JSPs
View jsp page: <Windchill>/codebase/WEB-INF/jsp/netmarkets/
object/defineItemAttributesWizStep.jsp
This is the default JSP that defines the view for this step. This view includes a
read-only property panel for the context name, a type picker, the driver attributes
panel and the editable attributes panel for entering attribute values.
The OOTB view jsp includes other jsps that do some of the work. The table below
describes these sub-jsps
JSP Description
defineItemAttributesWizStep.jsp The view jsp for the Set Attributes step;
includes configureTypePicker tag for
presenting & configuring the type
picker, the driver attribures panel,
Primary Content Panel (if any), the
attribute table and check boxes(if
applicable).
defineItemReadOnlyPropertyPanel.jspf Contains the describePropertyPanel tag
for the read-only panel
defineItemReadOnlyProperties.jspf Contains describeProperty tags for the
attributes in the read-only panel
defineItem.jspf Looks up the JSP for the driver
attributes panel and gets the data for
and renders all the page elements.

Constructing Wizards 933


JSP Description
Contains a renderPropertyPanel tag that
contains the read-only subpanel, type
picker, and driver attributes subpanel;.
The type picker is configured to call a
js function that will refresh the driver
attributes panel, editable attributes
panel, and downstream non-preloaded
steps any time the type value is
changed.
driverAttributesSetup.jspf Makes an ajax call to the
TypeBasedIncludeServlet to get the JSP
containing the describePropertyPanel,
getModel, and renderPropertyPanel
tags for the driver attributes panel.
Unless overridden by a service.
properties entry for a specific type, one
of the following JSPs will be used:
• <Windchill>/codebase/netmarkets/
jsp/object/
defineItemAttributesPanel.jsp (for
OrganizationOwned objects)
○ This contains a component for
input of the owning
organization.
○ Note this is only displayed if the
preference Display -> Expose
Organization is set to true.
• <Windchill>/codebase/netmarkets/
jsp/object/
defineItemAttributesPanelEmpty.
jsp (for all other objects)
○ Empty
defineItemStepContextPanel.jspf Contains the getModel and
renderPropertyPanel tags for the read-
only attributes subpanel

Validator
The SetAttributesStepValidator is available to validate the data in the
set attirbutes wizard step.

934 Customization Guide


This class will validate whether or not alla the input attributes in the set attributes
step have valid values by checking constraints. This class does not do the
"required" attribute validation. That is done on the client with javascript.

Tags
All the tags below are defined in the <Windchill>/codebase/WEB-INF/
tlds/components.tld file.
See the javadoc for the Windchill Client Architecture Common Components tag
library and the javadoc for the tag handlers listed below for more information on
the tags and their attributes.
Element Description
initializeItem Initializes some data for the object
being created using attribute values
passed on the tag and the launch
context of the wizard. This data is
stored as hidden fields in the HTML
form data and in the HTTPRequestData
parameter map of the
NmCommandBean.
Tag handler: com/ptc/core/components/
tags/components/InitializeItemTag
attributesTableWizComponent Builds an attribute layout of object
attributes used for entering attribute
values. The layout contains a group of
name value pairs and is controlled by
Type and Attribute Management utility.

This tag only renders the attributes after


validation of the driver attributes and if
the driver attributes are valid.
WEB-INF\tags\mvc
\attributesTableWizComponent.tag
configureTypePicker Configures the type picker table for
more details see Configure the Type
Picker on page 939.
Tag handler: com/ptc/core/components/
tags/components/
ConfigureTypePickerTag

Constructing Wizards 935


Other Java Classes
These additional java classes are also involved in the creation of this step and
available for advanced customization.
• DefineItemAttributesWizStepBuilder : MVC Builder for the Set
Attributes step which includes the driver attributes and the attributes table.
• TypedAttributesPanelBuilder : MVC Builder for the attributes
panel.

Procedure – Configure the Step

Add the action to the wizard tag


To add this step to the wizard, use: <jca:wizardStep action=
"defineItemAttributesWizStep" type="object"/>

Add the initializeItemTag


The InitializeItem tag initializes some data for the object being created
from the launch context of the wizard and the attributes passed to the tag. This
information includes:
• type of operation (create or edit)
• the base type of the object being created
• default container
• initial value for the type picker
• type instance identifier for the object being created
• AttributePopulator class, if any
See Default view JSP for the Set Attributes Step on page 952 for the attributes of
this tag. The only required attribute is “operation”.
<jca:initializeItem operation="${createBean.create}"
baseTypeName=
"wt.doc.WTDocument|org.rnd.FakeLiterature"/>

Layout the attributes


The attributes displayed on this step are controlled in the Type and Attribute
Management utility. For details on laying out the attributes on this step see
Attribute Panels on page 348.

936 Customization Guide


Customizations
If the Set Attributes step is the first step in the wizard or nothing in this step is
affected by data on prior steps then it can be preloaded. Otherwise, specify it to
not be preloaded in the step action. If the wizard has a Set Context step and a type
picker, it should not be preloaded as the context will affect the content of the type
picker.
The sections below describe how to perform common customizations of this step.

Note
Please remember that you should always place your custom jsp and jspf files
in a directory under wtSafeArea, as described in Managing Customizations on
page 100.

<initializeItem> Tag Parameters


See the javadoc for com.ptc.core.components.tags.InitializeItemTag and the
Common Components tag library for the most up-to-date information on tag
parameters.

Constructing Wizards 937


Parameter Default Possible Req? Description
Value Values
operation None CreateAndE- Yes Indicates
ditWizBean. whether the
CREATE object is being
CreateAndE- created or
ditWizBean. edited.
EDIT
objectHandle Not used for
single-object
creation
wizards
baseType- the type any Windchill No The string
Name associated type identifier form of the
with the string Windchill type
wizard action identifier for
the class of
object to
create. For
example, "wt.
part.WTPart"
or "wt.part.
WTPart|
MySoftPart".
This class will
be the root
type in the
wizard's type
picker. It is
also used to
look up the
correct jsps for
wizard steps
that have
different
variants for
different
subclasses
until a specific
type is selected
in the type

938 Customization Guide


Parameter Default Possible Req? Description
Value Values
picker.
Optional. If
not specified,
the type
associated
with the
wizard action
will be used.

Configure the Type Picker


The base type for the wizard is derived from an attribute on the
InitializeItem tag or, if none, from the object type associated with the
wizard action. (More about the InitializeItem tag later.) If you want to allow users
to create either the base type or a subtype of the base type you would include a
type picker in your wizard.
The list of types available in the type picker is typically determined as follows:
1. Compute the list of hard and soft subtypes of the base type. Soft subtypes are
the instantiable subtypes defined for the base type in the given organization
container.
2. Determine the default life cycle and initial life cycle state for the base type and
each subtype based on the composite object initialization rules for the type in
the given container.
3. Determine a default folder location context for the new object. This is done as
follows:
4. If the renderer constraint “SelectGeneratedFolderByDefault” is defined in the
composite OIRs for the base type or the user is creating a shared object from
the shared-to container’s folder browser
• Use the folder defined by the OIRs for the base type in the target container
• If no OIR folder is defined, use the default cabinet for the target container
5. If no renderer constraint is defined and it is not a shared-to object
• Use the folder selected in the launch context. This could be the folder
checked in the folder browser table, the folder highlighted in the left pane
of the folder browser, or the folder associated with the business object
from whose info page the create action was launched.
• If no folder can be determined from the launch context, determine the
folder as shown under item i. above

Constructing Wizards 939


6. Based on the default initial life cycle state and the administrative domain of
the folder location, determine whether the user has create permission for each
type. If not, filter that type from the list.
7. Display the remaining types in the picker.
The default value for the type picker is determined from a preference for some
base types, as follows:
Base Type Preference
WTPart Create and Edit -> Part Create Default
Type
WTDocument Create and Edit -> Document Create
Default Type
WTChangeIssue (ProblemReport) Create and Edit -> Problem Report
Create Default Type
WTChangeRequest2 (Change Request) Create and Edit -> Change Request
Create Defaualt Type
WTChangeOrder2 (Change Notice) Create and Edit -> Change Notice
Create Default Type
WTChangeActivity2 (Change Task) Create and Edit -> Change Task Create
Default Type
WTVariance (Variance) Create and Edit -> Variance Create
Default Type

For all other wizards, the base type is used as the default type.
When the user selects a type in the type picker, javascript is executed that
refreshes the driver attributes panel below it and all following wizard steps. This is
necessary because object type can affect which jsps are used for subsequent steps
as well as the attribute input fields displayed.

How to reconfigure the type picker


The type picker can be modified to filter certain types from the list, specify a
different default value, etc. The configuration parameters are described in the
javadoc for the ConfigureTypePicker tag.
To specify different picker parameters you will need to:
1. In your wizard jsp,add the following line to the top of the file:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%>
2. Add the configureTypePickerTag
3. Add “pickerParam” subtags to the configureTypePicker tag as shown in the
javadoc for the ConfigureTypePickerTag.

940 Customization Guide


See Create Wizard Using Keep Checked Out Checkbox on page 956 for an
example.

<configureTypePicker> Tag Parameters


Parameters to this tag are in the form of pickerParam subtags. All of these
parameters are optional. Example syntax:
<jca:configureTypePicker>
<p:pickerParam name="seedType" value="wt.part.WTPart|org.r_and_d.
SoftPartType1/>
<p:pickerParam name="filterType"
value="wt.part.WTPart|org.r_and_d.SoftPartType1|org.r_and_d.
SoftPartType1B"/>
<p:pickerParam name="showRoot" value="false"/>
</jca:configureTypePicker>

Parameter Default Value Possible Values Description


seedType None any Windchill typeThe top-level type
identifier string that should be used
(logical or to generate the list
external) of types. For
example, "wt.part.
WTPart". May
include more than
one of these
parameters.
defaultType May be taken from any Windchill type The type that
a preference (see identifier string should be selected
table above) (logical or by default. For
For all other external) example, "wt.part.
wizards, the base WTPart." May be
type is used. a string, such as
"Select a Type"
rather than a type
name.
filterType None any Windchill type A type that should
identifier string be excluded from
(logical or the type list. For
external) example,
"SoftPartType1".
The descendants of
the filter type are
also excluded.
May include more

Constructing Wizards 941


Parameter Default Value Possible Values Description
than one of these
parameters.
displayHierarchy false true (to display Indicates whether
hierarchy) the type list should
false (to display be displayed as a
flat list) flat list or in
hierarchical form.
showRoot true true (to display Whether the
seed types) seedTypes should
false (to not not be displayed.
display seed types)
adminDomainRef- The domain any administrative String
String associated with the domain reference representation of
default folder string the administrative
location (see domain reference
Overview on page that should be used
928 for access-control
filtering of the type
list. For example,
"wt.admin.
AdministrativeDo-
main:7"
Type BOTH ROOT_TYPES Indicates the kind
(only seedTypes of types to be
will be displayed) displayed. Value
SOFT_TYPES should be one of
(only subtypes will the enum constants
be displayed) defined in com.ptc.
windchill.
MODELED_
TYPES (only enterprise.picker.
modeled types will type.server.
be displayed TypePickerTypes.
BOTH (both
modeled and
subtypes will be
displayed)

942 Customization Guide


How to add components to the step
To add components to the step (for example, additional checkboxes at the bottom)
do the following:
1. Create a new main jsp file for the step
2. Copy the contents of the file <Windchill>/netmarkets/jsp/object/
defineItemWizStep.jsp into the new file.
3. Add the desired components to the page as follows:
<div id='driverAttributesPane'>
...
</div>
Add components here if you want them to appear below the
drive attributes panel
<div id='setAttributesTablePane'></div>
Add components here if you want them to appear below the attributes panel
4. Create a new builder class for the step, overriding the getView() method to
specify the view jsp for the step.
The suggested Name for the builder class for this step is
<object type> DefineItemAttributesWizStepBuilder.java
The suggested name for view JSP for this step is:
defineItemAttributesWizStep.jsp
or
defineItemAttributesWizStep For<object type>.jsp (if there is
more than one in the directory)
If the object is RevisionControlled one example of additional information to
include is a Keep checked out checkbox, include the following jsp in the view jsp
to display it: /netmarkets/jsp/components/
keepCheckedOutCheckbox.jspf
See Default view JSP for the Set Attributes Step for WTPart on page 952 and
Create Wizard Using Keep Checked Out Checkbox on page 956 for examples.

How to remove components from the step


1. Create a new main jsp file for the step
2. Copy the contents of the file <Windchill>/netmarkets/jsp/
object/defineItemWizStep.jsp into the new file.
3. One component that one may want to remove is the read-only property panel.
To do this delete the following line from the file:
<%@ include file="/netmarkets/jsp/components/
defineItemReadOnlyPropertyPanel.jspf"%>

Constructing Wizards 943


How to modify the contents of the read-only property panel in the step
1. Create a new main jsp file for the step.
2. Copy the contents of the file <Windchill>/netmarkets/jsp/object/
defineItemWizStep.jsp into the new main jsp file.
3. Delete the following line and replace it with your custom
describePropertyPanel tag that includes the attributes you want to
display:
<%@ include file="/netmarkets/jsp/components/
defineItemReadOnlyPropertyPanel.jspf"%>
Be sure to set the following attributes on your describePropertyPanel tag:
Attribute Value
var “defineItemStepContextPanelDescrip-
tor”
id “defineItemStepContextPanelDescrip-
tor”
scope “request”
mode “VIEW”
Alternatively, you could include a new jspf file that contains your
describePropertyPanel tag instead of placing it in-line.
See JSP for the Defining the Define Item Panel for WTPart on page 953 for an
example.

How to create a step with no driver attributes


For this you do not need to create a new wizard step JSP.
Create an entry in a type-based service properties xconf file pointing to the jsp file
defineItemAttributesPanelEmpty, as follows:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor="<object type to be created>"
resource=”/netmarkets/jsp/object/defineItemAttributesPanelEmpty.jsp”
selector="defineItemAttributesPanel"/>
</Resource>

How to create a step with additional driver attributes


For this you do not need to create a new wizard step JSP, just a new sub-JSP file
for the driver attributes, as follows.
1. Create a new JSP file containing describePropertyPanel, getModel, and
renderPropertyPanel tags for your driver attributes. (Note this must be a .jsp
file and not a .jspf file.) Use the file <Windchill>/codebase/netmarkets/jsp/
object/defineItemAttributesPanel.jsp as an example and list the attributes you

944 Customization Guide


want to display in the describePropertyPanel tag. Because the output of this
jsp is parsed and inserted dynamically inserted into the page, it must not
contain any display text or HTML besides the three tags listed above.
2. Create an entry in a type-based service properties xconf file pointing to your
new jsp file as follows:
<Resource context="default"
name="com.ptc.netmarkets.util.misc.FilePathFactory">
<Option requestor="<object type to be created>"
resource=”<path to your jsp page ”>
selector="defineItemAttributesPanel"/>
</Resource>

editAttributesWizStep
This step is common to almost all edit wizards and is where the user edits most of
the object’s attributes. It generally contains a read-only context property panel and
an attribute input panel.
By default there are no read only attributes. The desired attributes vary by object
type. An MVC builder is used to configure the set of read only attributes to be
displayed foa given type when it is desired. Some typical attributes displayed in
the read only are are:
• the object type
• the container name (If the object is WTContained)
• the organization id (If the new object is OrganizationOwned and the
preference Display -> Expose Organization is set to true)
You will need to decide what, if any, information needs to be displayed in this
panel for your object type.
The attribute input panel typically contains input fields for all the editable soft and
hard attributes for the object type, it does not contain input fields for part
classification attributes. These are entered on a following step. The set of
attributes displayed in this panel is controlled by the Type and Attribute
Management utility.

Solution
Add the editAttributesWizStep to your new wizard and configure the step.

When to use this step


This step is intended for use for editing objects. For Creating objects see
defineItemAttributesWizStep on page 930.

Constructing Wizards 945


Solution Elements

Action
<action name="editAttributesWizStep" id="editAttributesWizStep"
preloadWizardPage="false"
required="true" afterVK="editAttributes" resourceBundle=
"com.ptc.core.ui.componentRB">
<component name="editAttributesWizStep" typeBased="true"
windowType="wizard_step"/>
</action>
Action file: <Windchill>/codebase/config/actions/actions.xml
Note that the editAttributesWizStep action specifies the page as non-preloaded in
case in is not the first step in the wizard and is dependent on an earlier step.
However, if it is the first step, the framework will preload it regardless of how it is
specified on the action.

JSP
View JSP Page: <Windchill>/codebase/netmarkets/jsp/object/
propertyAttributesWizStep.jsp

Validator
The EditAttributesStepValidator is available to validate the data entered in this
step. This class will validate whether or not all the input attributes in the edit
attributes step have valid values by checking constraints. The "required" attribute
validation will be done on the client with javascript.

Other Java Classes


These additional java classes are also involved in the creation of this step and
available for advanced customization.
• DefaultEditAttributesWizStepBuilder : MVC Builder for the Set Attributes
step which includes an empty read only attributes area and the editable
attributes panel. Extend this class to define a non empty set of read only
attributes.
• TypedAttributesPanelBuilder : MVC Builder for the attributes panel.

Procedure — Configure the Step

Add the Action to Your Wizard Tag


To add this step to your wizard you can use: <jca:wizardStep action=
"editAttributesWizStep" type="object"/>

946 Customization Guide


Add the initalizeItem Tag
Like the defineItemAttributesWizStep, editAttributesWizStep requires an
initializeItem tag. Instead of setting the operation attribute of this tag to
${createBean.create}, you should set it to ${createBean.edit}. The following tag
attributes are not applicable to edit wizards: objectHandle, baseTypeName.

Layout the Attributes


The attributes displayed on this step are controlled in the Type and Attribute
Management utility. For details on laying out the attributes on this step see
Attribute Panels on page 348.

Customization

How to Modify the Conents of the Read-Only Property Panel in the Step
To modify the read only attribute panel to have it contain some attribute, write an
EditAttributesWizStepBuilder. The new builder should extend from
DefaultEditAttributesWizStepBuilder and implement the
buildReadOnlyAttributePanelConfig method. In this method, create an
AttributePanelConfig containing the desired attributes. Use the TypeBased
annotation to specify the type the builder applies to. An Example builder can be
found in the Basic Edit Wizard example in Building Wizards to Edit a Single
Object on page 914.
A basic builder might look like the following:
@TypeBased(value = "FakeLiterature")
public class LiteratureEditDetailsWizStepBuilder extends
DefaultEditAttributesWizStepBuilder {
@Override
protected AttributePanelConfig buildReadOnlyAttributePanelConfig
(ComponentParams params) throws WTException {
ComponentConfigFactory factory = getComponentConfigFactory();
AttributePanelConfig attrPanel = factory.newAttributePanelConfig();
attrPanel.addComponent(getContainerAttributeConfig(params));
attrPanel.addComponent(factory.newAttributeConfig(DescriptorConstants.
ColumnIdentifiers.TYPE));
return attrPanel;
}
}

Constructing Wizards 947


SetContextWizStep
This step typically has only one input field, which is a picker for the owning
container of the object being created. The selected container will be used to select
the appropriate OIRs for other attributes.
In many cases, the container is determined from the launch context of the wizard
and this step is not needed. For example, if the wizard is launched from the folders
page of a product, the container is assumed to be that product.

Solution
Add the SetContextWizStep to your new wizard and configure the step.

When to use this step


This step is for WTContained objects only. This step contains a context
(container) picker and should be included in a create wizard for a WTContained
object if the container cannot be determined from the launch context and/or you
want to allow the user to choose a container.

Solution Elements

Action
<action name="setContextWizStep" id="setContextWizStep" preloadWizardPage="true"
required="true"
afterVK="setContextWizStep">
<command windowType="wizard_step"/>
</action>
Action file: <Windchill>/codebase/config/actions/actions.xml

JSP
View jsp page: <Windchill>/codebase/WEB-INF/jsp/netmarkets/
object/setContextWizStep.jsp

Validator
The ContextWizardStepValidator is available to validate the data in the set context
wizard step. The ContextWizardStepValidator just validates that the form data
contains a valid container object reference.
This validator also determines if the step should be displayed in the wizard. If the
context has been determined from the launch point the step will be skipped even
though it is included in the wizard.

948 Customization Guide


Procedure — Configure the Step

Add the Action to Your Wizard Tag


To add this step to your wizard you can use: <jca:wizardStep action=
"setContextWizStep" type="object"/>
When you are using this step it is recommended that this be the first step in your
wizard.

Customizations

Creating a Custom Set Context Step JSP Page


If a custom wizard has a Set Context step, the out-of-the-box step jsp listed above
will usually suffice. The only time it might be necessary to develop a custom step
jsp is if there is a need to capture additional attribute values before the display
attributes are presented on the Define Object step.
For example, assume that:
• The wizard launch point has no folder context
• There are not any OIRs that set a default folder location for new objects
• There are defined access control policies denying users create permission for
certain object subtypes. These policies are based on the administrative domain
associated with the folder in which the new object is located.
In this case, the object container will have no effect on folder selection and you
may want the user to select a folder location so the list of types available to him/
her can be accurately determined. In this case you may want to put a folder input
field on a step prior to the Define Object step. You could either add this input field
to the Set Context step or add additional step to the wizard to capture folder
location either before or after the Set Context step. (Either way, you will also need
your own JSP for the Define Object step so you set the administrative domain
parameter on the type picker based on the user’s folder selection in the Set
Context step.)
If a custom Set Context jsp is needed and it needs to have a container picker, it is
recommended that the out-of-the-box jsp is included in it rather than copying the
contents of the out-of-the-box jsp. This will ensure the custom page will continue
to behave correctly even if the context picker is modified in a future release.

Constructing Wizards 949


setClassificationAttributesWizStep

Solution
Add the setClassificationAttributesWizStep to your new wizard
and configure the step.

When to use this step


This step only applies to WTParts and subtypes thereof when PartsLink is
installed. It is a dynamic step that only appears if the part is classified. It allows
the user to modify the classification attributes of the part. It displays the
classification of the part in view mode at the top and then includes a table of input
fields for classification attributes. This step can be used for both creating and
editing objects.
Note that the Set Classification Attributes step is marked as hidden. It is
dynamically inserted into the
wizard if the user clicks the “Choose Classifications” radio button on the Set
Attributes step. It is dynamically removed if the user clicks the “Do Not Classify”
radio button to unclassify the part.

Solution Elements

Action
<action name="setClassificationAttributesWizStep"
id="setClassificationAttributesWizStep"
hidden="true" required="true" preloadWizardPage="false">
<command windowType="wizard_step"/>
</action>
Action file: <Windchill>/codebase/config/actions/
PartManagement-actions.xml

JSP
View JSP Page: <Windchill>/codebase/netmarkets/jsp/part/
setClassificationAttributesWizStep.jsp

Validator
The Set Classification Attributes step uses the same validator as the Set Attributes
step.

Procedure — Configure the Step


To add this step to your wizard you can use:
<jca:wizardStep action=" setClassificationAttributesWizStep" type="part"/>

950 Customization Guide


Add the Action to Your Wizard Step

Customizations

Using the Step in an Edit Wizard


When building an edit wizard that contains the Set Classification Attributes step
you will need to dynamically load that step if the part being edited is classified.
The js function “loadClassificationStep()” in <Windchill>/codebase/netmarkets/
javascript/part/PartHelper.js is available to do that. In most cases this should be
called indirectly by calling the “onloadEditPartWizard()” function when the
wizard loads your main wizard jsp, as follows:
<script language="JavaScript" src="netmarkets/javascript/part/PartHelper.js">
</script>

... full jsp contents, the following javascript


should be the last thing in the file...

<script language="Javascript">
PTC.onReady(onloadEditPartWizard);
</script>

The onloadEditPartWizard() function calls loadClassificationStep() and also does


some additional configuration for wizards launched from a workspace. You can
use it regardless of whether your wizard can be launched from a workspace.

attachments_step
This step is typically included when creating or editing objects that are
ContentHolders. It allows the user to attach documents, links, and other content to
the new object.
See Attachments on page 337 for information on the elements that must be
included to incorporate this step.
No validator is provided or needed for the attachments step.

setAccessControlWizStep
This step is typically included when you want to allow the user to make
modifications to the access permissions for the object.
See Component Access Control on page 330 for information on the elements that
must be included to incorporate this step.

Constructing Wizards 951


Sample Code

Default view JSP for the Set Attributes Step


This jsp is the MVC view for the “defineItemAttributesWizStep”
action for objecttype=object in <Windchill>/codebase/config/
actions/actions.xml. The MVC builder for the Set Attributes Step for any
object is DefineItemAttributesWizStepBuilder. The MVC view for
the builder is defined in WEB_INF/jsp/object/
defineItemAttributesWizStep.jsp
The next section Default view JSP for the Set Attributes Step for WTPart on page
952 illustrates having own view jsp for object type WTPart as WTPart need to
include a customized type picker and ReadOnlyPropertyPanel.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%Ok. W>

//The driver attribute panel that defines the top section that includes the read
only property panel for context, type picker and driver attributes
<div id='driverAttributesPane'>
<%@ include
file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.jspf"%>
<jca:configureTypePicker/>
<%@ include file="/netmarkets/jsp/components/defineItem.jspf"%>
</div>

//Include Attribute Panel defining the non driver attributes


<mvc:attributesTableWizComponent/>
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Default view JSP for the Set Attributes Step for WTPart
WTPart need to include a customized type picker, ReadOnlyPropertyPanel, and
custom information related to the CreateCadDocStep option. Hence we need to
define a builder for WTPart(PartDefineItemAttributesWizStepBuilder) to set the
view for the Set Attributes step (WEB_INF/jsp/part/
defineItemAttributesWizStep.jsp).
The only difference from the Generic one is that the jsps to render the driver
attributes is different.

952 Customization Guide


<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc1"%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%>
<%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/wrappers" prefix="wrap"%>

<%@ page import="com.ptc.windchill.enterprise.part.partResource" %>


<fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/>
<fmt:message var="createCADDocument" key="<%= partResource.CREATE_CAD_DOC_
FROM_NEW_PART_LABEL %>" />

<div id='${createBean.currentObjectHandle}driverAttributesPane'>
<%@ include file="/netmarkets/jsp/part/defineItem.jspf"%>
</div>

<mvc:attributesTableWizComponent/>

<c:if test='${param.showNewCADDocStep == "true"}'>


<wrap:checkBox name="createCADDocForPart" id="createCADDocForPart"
label="${createCADDocument}" renderLabel="true"
renderLabelOnRight="true" checked="false"
onclick="toggleCreateCADDocStep('part.defineItemAttributesWizStepForCADDoc!~
objectHandle~caddocHandle~!');" />
</c:if>

<br>
<c:if test='${param.invokedfrom != "workspace"}'>
<%@ include
file="/netmarkets/jsp/components/keepCheckedOutCheckbox.jspf"%>
</c:if>

<input id="selectedClfNodes" type="hidden" name="selectedClfNodes" >


<input id="selectedClfNodesDisplayName" type="hidden"
name="selectedClfNodesDisplayName" >
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Defining the Define Item Panel for WTPart
Filename: <Windchill>/codebase/ netmarkets/jsp/part/
defineItem.jspf
This example illustrates how to override the read-only context panel and to
reconfigure the type picker.
<%@ page import="com.ptc.windchill.enterprise.part.PartConstants" %>
<%@ page import="com.ptc.core.ui.componentRB" %>

<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"

Constructing Wizards 953


prefix="jca"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/partcomponents"
prefix="partcomp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%>

<jca:describePropertyPanel var="defineItemStepContextPanelDescriptor"
id="defineItemStepContextPanelDescriptor"
scope="request" mode="VIEW" type="wt.part.WTPart">

<jca:describeProperty id="containerName"
label="${createBean.containerLabel}"/>
</jca:describePropertyPanel>

<%-- Get the part types to filter from type picker selection list --%>
<partcomp:PartCreateHelper var="partTypesToFilter"
method="getPartTypesToFilter"/>

<c:choose>
<c:when test='${param.invokedfrom == "tabular_input"}' >

<!-- If New Part client is invoked from Edit Structure, association


constraints need to be enforced. (Please see the Javadoc for
DefaultAssociationConstraintIT for more details). The list of
creatable types needs to be filtered out to inlcude only the
types allowed by association constrains. This is achieved by
finding the list of valid (allowable) types using the
getSeedPartTypes below and then setting the type picker's
'type' parameter to 'ROOT_TYPES' -->

<!-- Get the seed part types. Usually, it is wt.part.WTPart but


it can be a bunch of types if association contraints
are in place -->
<partcomp:PartCreateHelper var="seedPartTypes" method="getSeedPartTypes"/>

<jca:configureTypePicker>
<%--
Type Picker picks up the default from Preferences.
It does not have be set here.
--%>
<c:forEach var="item" items="${seedPartTypes}">
<p:pickerParam name="seedType" value="${item}"/>
</c:forEach>
<c:forEach var="item" items="${partTypesToFilter}">
<p:pickerParam name="filterType" value="${item}"/>
</c:forEach>
<p:pickerParam name="type" value="ROOT_TYPES"/>
</jca:configureTypePicker>

</c:when>

954 Customization Guide


<c:when test='${param.invokedfrom == "config_link_table"}' >
<!-- The part types in the type picker must come from the
association constraints on the configurable link. -->

<clui:getRoleBTypesForNewAction var="roleBObjectTypes"
roleBBaseType="wt.part.WTPart"/>

<jca:configureTypePicker>

<c:forEach var="item" items="${roleBObjectTypes}">


<p:pickerParam name="seedType" value="${item}"/>
</c:forEach>

<c:forEach var="item" items="${partTypesToFilter}">


<p:pickerParam name="filterType" value="${item}"/>
</c:forEach>

<p:pickerParam name="type" value="ROOT_TYPES"/>


</jca:configureTypePicker>
</c:when>

<c:otherwise>

<jca:configureTypePicker>

<%--
Type Picker picks up the default from Preferences.
It does not have be set here.
--%>

<c:forEach var="item" items="${partTypesToFilter}">


<p:pickerParam name="filterType" value="${item}"/>
</c:forEach>

</jca:configureTypePicker>

</c:otherwise>
</c:choose>

<%@ include file="/netmarkets/jsp/components/defineItem.jspf"%>

Additional Resources

Constructing Wizards 955


Related Customization Documentation
• Windchill Client Architecture Wizard on page 838
• Wizard Processing on page 866
• Configuring a Context Picker on page 1015
• Configuring a Type Picker on page 1043
• Configuring an Organization Picker on page 1034
• Configuring a User Picker on page 1061
• Configuring an Item Picker on page 1025
• Building Wizards to Create a Single Object on page 892
• Building Wizards to Edit a Single Object on page 914
• Attachments on page 337
• Component Access Control on page 330
• Attribute Customization on page 658

Related Package/Class Javadoc


• com.ptc.core.components.tags.components..InitializeItemTag
• com.ptc.core.components.tags.components.ConfigureTypePickerTag
• Common Components Tag Lib Javadoc

Packaged Samples
Many out of the box Windchill wizards make use of these steps and can be
referenced as examples.

Create Wizard Using Keep Checked Out Checkbox


• Description :
This is an example of a wizard to create an object of the Literature type which
includes the Keep Checkedout Checkbox. The Literature Type is a Softtype of
WTDocument which can be loaded automatically. You will be prompted to
load the type anytime you attempt to access an Example that relies on the type.
This Example Illustrates a very basic create. It includes an example of creating

956 Customization Guide


an MVC Builder and a custom view for the defineItemAttributesWizardStep.
The attributes being displayed on the attributes step are loaded automatically
when the type is loaded through the UI and can be configured through the
Type and Attribute Management utility.
• Location of Example :
To navigate to this example in the produce go to Customization >>
Component Catalog >> Wizard Component >> In the example section select
“Create Wizard using Keep Checked Out Checkbox”
• Actions for this Example:
○ createLitCheckBox, fakeLiterature
○ setContexWizStep, object
○ defineItemAttributesWizStep, object
• Action Models for this Example : None
• Files Used in This Example
○ /netmarkets/jsp/carambola/customization/examples/wizard/
CreateLitCheckbox.jsp
○ /netmarkets/jsp/components/keepCheckedOutCheckbox.jspf
○ /netmarkets/jsp/carambola/attributePanel/
fakePoemDefineItemAttributesWizStep.jsp
○ com.ptc.mvc.builders.carambola.wizard.
FakePoemDefineItemAttributesWizStepBuilder
○ /config/actions/Carambola-actions.xml

Create Wizard Using Common Steps


• Description :
This is an example of a wizard to create an object of the Literature type which
includes some of the available out of the box steps. The attributes being
displayed on the attributes step are loaded for you when you load the type and
can be configured through the Type and Attribute Management utility. The
context picker step is included and will display when the context cannot be
determined. The attachments component is included for adding attachments to
the Literature object. A custom Step is also included to demonstrate how to
add any custom step jsp to a wizard.
• Location of Example :

Constructing Wizards 957


To navigate to this example in the produce go to Customization >>
Component Catalog >> Wizard Component >> In the example section select
“Create Wizard using Common Steps”
• Actions for this Example :
○ createLitCheckBox, fakeLiterature
○ setContexWizStep, object
○ defineItemAttributesWizStep, object
○ attachements_step, attachments
○ setClassificationAttributesWizStep, part
○ createLitCustomWizStep, fakeLiterature
• Action Models for this Example : None
• Files Used in This Example :
○ /netmarkets/jsp/carambola/customization/examples/wizard/
CreateLitOOTBSteps.jsp
○ /netmarkets/jsp/carambola/customization/examples/wizard/
CreateLitCustomWizStep.jsp
○ /config/actions/Carambola-actions.xml

958 Customization Guide


Handling External Requests Using an
MVC Controller
This section contains information on handling an external request for a JCA action
on a Windchill system from an external system (e.g.: Relex) capable of rendering
a web panel (i.e. Embedded browser window). The external system is aware of a
Windchill Server and has OIDs (object references) to a set of objects launch a
create JCA wizard for various PDMLink objects.

Scope/Applicability/Assumptions
In order to launch a JCA action from an external system users will need to be able
to provide login credentials to the Windchill system when prompted. Refer to the
following for more information on those tasks:
• Windchill Client Architecture Wizard on page 838
• Windchill Client Architecture Common Objects Overview on page 245 —
provides information on some common Java classes used in the UI, such as
NmCommandBean.
• Javascript Functions Overview on page 248
• Customizing the UI with Ajax on page 291

Intended Outcome
An external system POSTs a request to a Windchill MVC controller with
necessary action parameters (see the example below) which then redirects to
requested action. When object(s) on the Windchill server are created, a JSON
response containing the UFID(s) is generated and returned as a call back to the
External system.

Solution
From the external system, launch a new HTML window which makes a POST
request to the Windchill system and gets back the created objects IDs.

Prerequisite knowledge
To apply this process, you need to have an understanding of the following:

Constructing Wizards 959


• Basic web development using HTML forms

Sequence Diagram

• A user clicks a create action in the external system using registered Windchill
system using a new window from the external system.
• The URL redirects the call to the registered MVC controller which then
invokes the registered JSP and redirects the create JSP for the requested action
and object type.
• Once the Windchill object(s) is created, a JSON object is returned back to the
caller with key as “UFIDs”. The form method is “GET” the external URL will
have to read the URL query parameter.
See the example scenario below for details.

Limitations
• The operation is performed within the Windchill transaction block after the
action is invoked.
• The call back value will be based on browser support for “GET” form method.

960 Customization Guide


Call to the Windchill Server from an External System
Assumptions
1. The selected objects and the context object information are available to the
external system.
2. The user launching the URL has access to the action.
3. The input field for the context object should be encoded, a sample context
object for a container would look like
“OR%3Awt.pdmlink.PDMLinkProduct%3A38380”

Handling multiple selected objects


To handle multiple selected objects for populating the seed data in a create wizard
table, use the hidden field called “soidarray” using a “___” as a delimiter for
each object. In the example above the New Change Request wizard will populate
two parts in the affected objects table. The object identifiers should not be
encoded when posting a form data.

Considerations
The full domain name is required for access permission to the frame window.
Replace the Windchill system URL with the full domain URL. Example, if the
server is the server is on domain ptcnet.ptc.com the URL should include :
http://windchillServer.ptcnet.ptc.com/<web-app>/ptc1/externalRequest?
oid="+contextOid+"&action=create&type=changeRequest;"
and not :
http://myserver/Windchill...

Unauthorized Action Handling


In case, invalid action or type is provided or the user does not have access to
perform the operation on Windchill server, an error will be displayed to the
external system user.

Call back to the external system


When a request is made to the Windchill system, a form field with the name
externalURL is populated with the external URL information, please see
example below. If no information is provided Windchill object will be created
when a request is made, however no feedback of the newly created object will be
provided. A “GET” form method is used to pass back the data.

Constructing Wizards 961


Accessing the created Windchill objects
The external URL will be appended with a new parameter as “UFIDs” in the
caller server. The “UFIDs” parameter can be read to retrieve the values. The
values are on JSON format and the values can be accessed using the key “UFIDs”.

Assumptions
1. User is authorized with required credentials for the provided external URL.
2. The input field for the external URL should be provided with name=
externalURL. An example external URL would look like : http://
<externalURL>/<host-name>/ptc1/externalTest

Handling multiple creation of OIDs


The external call back feature supports returning multiple OIDs for the request
operation. In the JSONObject key “UFIDs” will contain UFID values.

Sample Code from the External System


The sample example HTML will allow external requests to the Windchill system.
<html>
<script>
launchJCAAction = function() {
var winName = "create";
var theForm = document.getElementById('JCAActionForm');
theForm.target = winName;
var contextOid = document.getElementById('contextOid').value;
theForm.action = "http://windchillHostname:port/<web-app>
/ptc1/externalRequest?oid=OR%3Awt.pdmlink.PDMLinkProduct
%3A36226&action=create&type=changeRequest";
var props = '';
var actionwin = window.open("", winName, props);
theForm.submit();
}

</script>
<body>
<form method="post" id="JCAActionForm"
onSubmit="return false;" target="_self">
Container Oid: <input type="text" id="contextOid"/>
External URL: <input type="text" name="externalURL"
value="http://externalHostname:port/<web-app>"/>
<input type="hidden" name="soidarray" value="OR:wt.part.WTPart:90740___
OR:wt.part.WTPart:547106"/>
<button onclick='launchJCAAction();'>Launch Action</button>
</form>

962 Customization Guide


</body>
</html>
An example UFID for the created Windchill object would look like:
“VR:wt.change2.WTChangeRequest2:188695:651462062-
1309389210495-20458805-192-14-253-
132@<windchillServer>”

Constructing Wizards 963


Client Generated Form Data
Using client-side logic (i.e., JavaScript), you want to add, modify, or delete hidden
form data associated with a table in a wizard.

Background
This information applies to any client-side generated form data, that is hidden (i.
e., not displayed in a table in the wizard). This is also known as “data store only”
data; it refers to data that exists in the data store on the client, but is not rendered
in the DOM, so it is not visible in the page.
The hidden data is generated by application-specific JavaScript logic on the client
and added as hidden input form data that is submitted to the server. It is also
possible to have hidden columns added to a table by the server-side table builder,
and then modify those values in the client-side JavaScript.

Scope/Applicability/Assumptions
• You have a wizard that contains one or more tables.
• Your code needs to add data to the form submitted by the wizard that is not
visible in UI.
• This data may originate on the client, or it may have default values provided
by the server when the table is created, and those default values are to be
manipulated by your application's client-side logic.
• There may be one or more values associated with each table appearing in the
wizard, or there may be one or more (hidden) columns associated with each
row in a table.

Intended Outcome
The wizard's form submission will include hidden data that is not visible to the
user and that has been created or modified by application-specific, client-side
logic.

Solution
The solution involves three or four application-provided parts:
1. Define hidden table columns for the tables that are to appear in the wizard and
supply default values for the cells in those columns (by associating an
appropriate data utility with those columns). You may use an existing data
utility if appropriate, but it is more likely that you will provide a new, custom,
application-specific data utility to fulfill this need.

964 Customization Guide


This step is optional and may be omitted in some cases. If your application
adds hidden values for table(s) that appear in your wizard, but those values are
associated with the entire table and not any specific row(s) in the table, then
there is no means by which to supply a server-generated default value, and you
will not need to perform this step. In that case, your client-side logic will add
one or more hidden input values to the form data, identifying each value as
pertaining to a specific table, if necessary.
If your application requires hidden input values that are associated with
specific rows in a table, you may define one or more hidden columns in that
table and have your client-side logic manipulate the values in the cells in those
columns. Your table builder must associate some data utility with each
column, and that data utility must return a non-null value for each object in the
table (otherwise, no corresponding field for the object will be present in the
client's data store). If you need to supply a per-object default value, then use a
data utility that returns the required value.
2. Add a <script/> block to your wizard's JSP file that loads an application-
provided JavaScript file which will contain your custom, hidden-data
manipulating logic.
3. Create the JavaScript file that contains your custom, hidden-data manipulating
logic.
4. Modify your wizard's form processor to extract the hidden data fields from the
submitted form and perform the required processing on those fields.

Prerequisite Knowledge
To achieve this result, you need to understand:
• Basic development of Windchill web pages
• JavaScript
• JCA/MVC table builders
• JCA Form Processing

Constructing Wizards 965


Solution Elements
Element Type Description
<MyTableBuilder.java> Java class This file defines the table
that appears in your
application's wizard. You
will modify this class to
include definitions for
hidden table columns for
which the server will
provide default values.
This element is optional,
and is not required if your
application does not need
per-table-row hidden
values.
<MyScript.js> JavaScript This file will contain your
application's client-side
logic that adds, modifies,
or removes hidden inputs
from the form data
submitted to the server.
<MyWizard.jsp> JSP This file defines your
wizard's page. You will
modify this file to include
a <script/> block that
loads your JavaScript file
containing the logic to
manipulate the hidden
data elements.
<MyFormProcessor. Java class This file will contain your
java> application's form
processor for the form
data sent by the wizard to
the server. In this class
you will extract and
process the hidden data
that was generated or
manipulated by your
client-side JavaScript
logic.

966 Customization Guide


Procedure – Submitted Client-generated hidden form data

Add default values for client-generated fields (Optional)

Note
If you do not need per-table-row hidden input values for your application, you
may skip this step.

If your application needs a hidden input value for each object appearing in a table,
add one or more column definitions in the wizard's table builder defining columns
that are 'data store only' and 'editable'. Use an appropriate data utility to generate
the default values. Give the columns unique names so they can be identified in
your event listener (e.g., “hiddenColumn1”).
TableConfig table = factory.newTableConfig();
table.setId ('MYTABLEID');
..
. <... other table configuration here ...>
.
ColumnConfig hiddenCol1 = factory.newColumnConfig ("hiddenColumn1", false);
hiddenCol1.setDataUtilityId ("SOME_DU_ID");
hiddenCol1.setNeed ("SOME_DU_ID");
hiddenCol1.setComponentMode (ComponentMode.EDIT);
hiddenCol1.setDataStoreOnly (true);
table.addComponent (hiddenCol1);

ColumnConfig hiddenCol2 = factory.newColumnConfig ("hiddenColumn2", false);


hiddenCol2.setDataUtilityId ("SOME_DU_ID");
hiddenCol2.setNeed ("SOME_DU_ID");
hiddenCol2.setComponentMode (ComponentMode.EDIT);
hiddenCol2.setDataStoreOnly (true);
table.addComponent (hiddenCol2);
Your hidden data columns must be defined as “editable” and “data store only” as
shown in the bold lines in the code above.
SOME_DU_ID is the ID of a suitable data utility that will provide the default
values for the column. It must return a non-null value for the objects in the
wizard's table; otherwise, there will be no corresponding field for the object's row
in the data store.

Add a <script/> block to the wizard's JSP file


In the JSP for your wizard, add a <script/> block that will load an application-
specific Javascript file, something like this:
<script type="text/javascript"
src="netmarkets/javascript/MYAPPLICATION/MYJSFILE.js">
</script>

Constructing Wizards 967


Add your application’s client-side logic
Create a new Javascript file, …/netmarkets/javascript/
MYAPPLICATION/MYJSFILE.js , that will contain the application's listener
for the 'submit' event that will be signaled for the wizard's table. Code should
follow this outline:
// Establish namespace
PTC.MYAPPLICATION={};

// Define wizard table 'submit' listener


PTC.MYAPPLICATION.MYLISTENER = function (table)
{
// see PTC.fakeLiterature.submitListener() code in
// /netmarkets/javascript/carambola/dataStoreOnlyExample.js};

// Add submit listener for wizard table once the table becomes 'available'
PTC.onAvailable
( 'MYTABLEID', function (table)
{
table.on ('submit', PTC.MYAPPLICATION.MYLISTENER);
});
}

In this example, the submit listener is adding hidden input data to the submitted
form, using JCAappendFormHiddenInput. In this example, the client-side
logic looks for two hidden properties that have been added to each row in the table
with ID 'MYTABLEID'. Those properties exist on each row in the data-store, but
are not included in the DOM of the table that appears in the UI. These properties
are named “hiddenColumn1” and “hiddenColumn2”. If either of these
hidden properties is found on an object, a hidden input field is generated that
identifies the object [row.get (“objectHandle”)] and the hidden value itself
(“hiddenColumn1”, etc.) and which specifies a not-very-useful constant value.
The example also shows how to add a hidden input value that is not associated
with any hidden column, but still identifies a specific object (see the second call to
JCAappendFormHiddenInput, above).
Of course, this same type of listener could be used to add, change, or remove any
desired data to the form before it is submitted; it is not limited to manipulating so-
called “data store only” fields.

Extract hidden input values in the wizard's FormProcessor


The final step is to extract the submitted hidden input values that were added by
the application's 'submit' listener, within a suitable method of the wizard's form
processor:
for (ObjectBean objBean : objectBeans)

968 Customization Guide


{
final String paramKeyFoo = "noColumn";
final String paramKeyCol1 = "hiddenColumn1";
final String paramKeyCol2 = "hiddenColumn2";

String paramFoo = objBean.getTextParameter (paramKeyFoo);


String paramCol1 = objBean.getTextParameter (paramKeyCol1);
String paramCol2 = objBean.getTextParameter (paramKeyCol2);

log.error ("\nkey = " + paramKeyFoo + "\nvalue = " + paramFoo);


log.error ("\nkey = " + paramKeyCol1 + "\nvalue = " + paramCol1);
log.error ("\nkey = " + paramKeyCol2 + "\nvalue = " + paramCol2);
}

This results in output which will include something like the following code, which
shows the three client-side generated values that were added to the object by the
Javascript 'submit' listener shown earlier.
KEY = noColumn
VALUE = FOO_BAR_BIZ_BAZ

KEY = hiddenColumn1
VALUE = HIDDEN_COLUMN_1_GENERATED_VALUE

KEY = hiddenColumn2
VALUE = HIDDEN_COLUMN_2_GENERATED_VALUE

Limitations
This information is limited to adding hidden form data that is associated with a
specific JCA table and that is identified by a specific table ('MYTABLEID') in
the example code above). The hidden data may be defined as one or more hidden
columns in the table, in which case a unique value may be submitted for every
row in the table, or it may be associated with the table itself and not connected
with any row or column, in which case one or more values may be submitted for
the entire table. These two approaches may be combined within a single form
submission or they may be used separately.
No provision is made for client-side generated hidden form data that is not
associated with a JCA table, as this technique relies upon the 'submit' event that is
signaled just before a JCA table that appears within a wizard (i.e., HTML
<form/>) is submitted to the server.

Constructing Wizards 969


Packaged Samples

Note
The customization utilities must be enabled to see the samples. See
Customization Tools Overview on page 404 for information on enabling the
customization utilities.

1. Navigate to Navigator ▶ CustomizationComponent Catalog ▶ Wizard ▶ Data


Store Only Column in Wizard Table Example.
2. Select a context on the first wizard step and click Next.
3. Select the Add Row – No Content action from the tool bar on the table.
4. Enter some text in the Name column of the row that has been added to the
table.
5. Click Finish.
A confirmation message will display indicating that an object has been created.
Also, in the Method Server's log you will see output similar to this:
KEY = noColumn
VALUE = FOO_BAR_BIZ_BAZ

KEY = hiddenColumn1
VALUE = HIDDEN_COLUMN_1_GENERATED_VALUE

KEY = hiddenColumn2
VALUE = HIDDEN_COLUMN_2_GENERATED_VALUE

970 Customization Guide


18
Information Pages
Customizing Information Page Components .............................................................. 972

This chapter describes how to customize information pages.

971
Customizing Information Page
Components
You want to create or modify an information page for a Windchill business object.

Scope/Applicability/Assumptions
This information should be applied by a developer or customizer who is
responsible for creating a information page for a new Windchill business object.
This documentation assumes that:
• You are familiar with the use of Java builder classes used to acquire the data
from the server as described in MVC Components on page 257.
• In prior releases the information was retrieved using the InfoPageBean
Java class. This is not the recommended approach any longer.

Intended Outcome
An Information Page.

The information page is made up of the following pieces, many of which are
configurable.
Title bar area:
• Go to latest link (only appears on info pages for non-latest versions)
• Actions Menu
• Commonspace/Workspace toggle
• Object Type icon
• Item Identification
• Status Glyphs (checkout, share, pending changes, etc)

972 Customization Guide


• State of item (only appears for LifeCycleManaged items)
• Help icon

Tab Set

• Out of the box tabs and tabs configured by administrators are displayed at the
top
• • “+” tab that allows the user to add custom tabs

Table of Contents Menu

Information tab table of contents links to drag ‘n’ drop for rearranging the content
of the tab:

Information Pages 973


Visualization and Attributes Panel
This panel is intended to have a small subset of attributes.

Attributes
The attributes option is intended to have the full set of attributes displayed as
panels or in a table

974 Customization Guide


Solution
Create a builder Java class, which extends
DefaultInfoComponentBuilder, that will define the elements to be
rendered on the information page for a specific business object type. The layout of
the attributes is controlled by the attribute layout manager in the Type and
Attribute Management utility.

Prerequisite Knowledge
To apply this information you need to have an understanding of the following:
• The MVC framework for creating the Java builder class (see MVC
Components on page 257)
• JSP-based client architecture framework in Windchill (see Windchill Client
Architecture Overview on page 232)
• The actions framework in the Windchill client architecture (see Action
Framework for Windchill Client Architecture on page 512)
• How to manage attribute layouts using the Type and Attribute
Management utility (see Type and Attribute Management utility)

Solution Elements
Using this component, a developer will need to create a builder by extending
DefaultInfoComponentBuilder.
Element Type Description
DefaultInfoComponent Java class The default builder that all other
Builder.java information page builders should extend
from. The builder is responsible for
gathering the required data from the
server.
The core elements used to generate the information page are shown below. These
are not expected to be overridden by a developer. The builder is where a developer
can control which items are displayed on the information page for a business
object and the Type and Attribute Management utility can be used to control the
layout of attributes.
Element Type Description
infoPage.jsp JSP The JSP that all information
page actions should invoke. It
calls begin.jspf/end.jspf and calls
the infoPage tag in the MVC
taglib.
infoPage.tag Tag , defined in Sets up the JSP context and
the MVC taglib creates the info page

Information Pages 975


Element Type Description
ComponentDefinition object. It
calls the renderInfoPageModel
tag in the components taglib and
calls the JavaScript renderer to
generate the HTML for the
information page.
RenderInfoPageModel Java tag, defined It constructs a JSON object (a.k.
Tag.java in the a. InfoModel) from the data in
components taglib the builder and writes out the
JSON object to its print stream.
infoPage.jsfrag JavaScript JavaScript renderer that takes in
fragment the JSON InfoModel object. It
generates the HTML for the
information page
myTab.jsfrag JavaScript Renders the top-level tabs and
fragment provides the ability to move
items around in the tab content
area.
Supporting Elements
Element Type Description
attributePanel.jsp JSP JSP to invoke to render an
Attributes Panel. The Attribute
Panel component is used to
display the “Attributes” and
“Visualization and Attributes”
widgets. The layout of the
attributes in an Attribute Panel is
controlled by the attribute layout
manager in the Type and
Attribute Management utility.
See Attribute Panels
on page 348 for more
information.
attributePanel.tag Tag , defined in Sets up the JSP context and
the creates the Attribute Panel
MVC taglib ComponentDefinition object. It
calls the renderAttributePanel tag
in the components taglib and
calls the JavaScript renderer to

976 Customization Guide


Element Type Description
generate the HTML for the
attribute panel.
RenderAttributePanel Java tag, defined It constructs a JSON object (a.k.
Tag.java in the a. InfoModel) from the data in
components taglib the builder and writes out the
JSON object to its print stream.
attributePanel.jsfrag JavaScript JavaScript render that takes in
fragment the JSON InfoModel object. It
generates the HTML for the
attribute panel.

Information Page Process Flow


The builder is called first to collect the necessary data from the server. The builder
forwards the request to the view (i.e. infoPage.jsp). The default view,
infoPage.jsp, includes the infoPage tag. The tag creates a JSON object,
known as the infoModel object, from the data it collected from the builder. The
infoModel is serialized (by writing it out as JSON string to the JSP writer) and
passed to the JavaScript render which ultimately generates the HTML.
Here is the process sequence for rendering the info page:

Information Pages 977


Information Page Builder Designer
When creating an information page for a new business object type, a developer
will have to create a builder that extends the
DefaultInfoComponentBuilder. The builder class needs to include the
following Java annotations so the correct builder gets called for that business
object type:
@ComponentBuilder(value = ComponentId.INFOPAGE_ID)
@TypeBased(value = "wt.part.WTPart")
public class PartInfoBuilder extends DefaultInfoComponentBuilder {
….

The annotation for the builder ID is specified in the super class


DefaultInfoComponentBuilder. Annotations are inherited, so when
extending this class, the ComponentBuilder annotation is not required. It will
not hurt anything if it is there and if you are not extending this class be sure to
include it.
See MVC Components on page 257 for details on how to register your builder
class or package.
The only method that needs to be overridden is the buildInfoConfig()
method. This method is where you would set which elements you would like to
have displayed on the information page for that business object type and calls the
necessary service API’s to collect the data for those elements. SeeCustomization
Options in Info Page Builder on page 980 for more information about those
elements.
The annotation for the builder can contain a hard type or a subtype:
@TypeBased(value = "wt.part.WTPart")
@TypeBased(value = " com.company.SoftType")

See TypeBased on page 265 in MVC Components Overview on page 258 for
more information.

978 Customization Guide


Information Pages 979
Customization Points
The default information page will just have a details tab and a ‘+’ new tab option.
The details tab is set up to show just the More Attributes panel. That attributes
panel layout will come from the layout definition in the Type and Attribute
Management utility. For details on customizing attribute layouts see Layouts Tab.
When you create a new tab only two options would be available in the Customize
menu on that tab. “More Attributes” and “Visualization and Attributes”. (or if
your object type does not have a visualization delegate registered you’d just get
“More Attributes” and “Attributes”)
To customize what is displayed in the info page you’ll need to create a builder as
defined above in the “Information Page Builder Designer” section of Solution on
page 975. Then, the instructions below describe how to customize various aspects
of the Info Page by overriding the buildInfoConfig() API in your custom
builder.

Customization Options in Info Page Builder


You can control what elements appear on the information page in your builder
class. For more information about the builder class, see the “Information Page
Builder Designer” section in Solution on page 975. The following options can be
set on the InfoConfig object:

980 Customization Guide


Information Method to Default Value Description
Page Item invoke on
Builder
InfoConfig
Tab Level Set setTabSet() "defaultInfoPage- Name of the action
TabSet" model to be used
for the top-level
tabs.
• Please refer
toCustomiza-
tion Options in
Info Page
Builder on
page 980 for
more
information
about
configuring the
tab set
• Please refer to
Configure the
Table of
Contents on
page 986
section for
more
information
about
configuring the
default tables
on a specific
tab.
Tab set saving setTabSetKey() The hard type of This tabSetKey
the business object will be used for
is used. For saving tab order,
example “wt.part. tab content and the
WTPart” last active tab. If
no tabSetKey is
specified by the
builder the hard
type of the
business object

Information Pages 981


Information Method to Default Value Description
Page Item invoke on
Builder
InfoConfig
will be used as the
tabSetKey. For
example, part info
page will end up
using a tab set key
of "wt.part.
WTPart".
Some info pages
change this
tabSetKey to share
behavior across
types. For
example, the
caddoc and saved
caddoc info pages
will both have
tabSetKey of "wt.
epm.
EPMDocument".
Other info pages
change this
tabSetKey to get
different behavior
for the same type.
For example, the
'Clash Job
Definition' info
page will have a
different
tabSetKey so that
tabs/tables added
to that page are not
added to the
WTDocument info
page.
Recommended tab
set keys would be:
• wt.part.
WTPart"
• WCTYPE|

982 Customization Guide


Information Method to Default Value Description
Page Item invoke on
Builder
InfoConfig
wt.part.
WTPart|
com.acme.
SoftPart
Be careful with
these keys from
release to release.
Since they are
persisted to the
database a
migrator will be
needed if the key
needs to change.
Action menu setActionListName Defined in an Name of the action
() actions model with model to be used
the “menufor” for the Actions
attribute set Menu. See Action
Framework for
Windchill Client
Architecture on
page 512 or
Defining Menus
on page 562 to
define the action
model. If no action
menu is desired
pass an empty
string (“”) to this
method.
Table of Contents Name of the action
(TOC) menu model to be used
for the Customize
Menu on a tab.
This is the same
action model that
was used to render
the third-level
action bar in prior
releases.

Information Pages 983


Information Method to Default Value Description
Page Item invoke on
Builder
InfoConfig
• Please refer to
Configure the
Table of
Contents on
page 986 for
more
information
about
configuring the
default tables
on a specific
tab
• See Action
Framework for
Windchill
Client
Architecture on
page 512 or
Defining
Menus
on page 562 to
define the
action model.

984 Customization Guide


Information Method to Default Value Description
Page Item invoke on
Builder
InfoConfig
Add a status glyph addComponent() Adds a status
glyph to the top of
the info page. See
Adding a Status
Glyph
on page 508 for
more information
about adding status
glyphs in the
builder.
Help Button setHelpContext() Sets the help
context to a
specific help page.
Workspace Toggle Not defined in the Set of buttons that
Button builder, see appear to the right
description for of the Actions
more details menu. This is
configured in
javascript and
added to the
infoModel JSON
object via the info
page
‘beforerender’
event. SeeAdding
a Status Glyph on
page 987 for more
information.

Configure a Top-Level Tab Set


If you would like to specify a top-level tab set for your information page, create an
action model and set the action model in the info page builder. For example, you
could define the following action model for a tab set:
<model name=”partInfoPageTabSet” resource=”com.ptc.core.ui.navigationRB”>
<action name=”productStructureGWT” type=”psb”/>
<submodel name=”partInfoDefaultDetails” type=”object”/>
</model>

Information Pages 985


Then, you would specify the tab set on the builder as follows:
InfoComponentConfigFactory f =
(InfoComponentConfigFactory)getComponentConfigFactory();
InfoConfig result = f.newInfoConfig();
result.setTabSet(“partInfoPageTabSet”);

For more information on configuring the tabs, and how to specify the content
(tables) for a particular tab, please refer to Tab Customizations on page 991. For
more details about defining tabs please refer to Client Tabs on page 311.

Configure the Table of Contents


The table of contents (TOC) is comprised of two items, the menu and the links.
They are shown below, circled in red.

TOC Menu
The TOC menu allows an end user to add or remove items from the tab. It will
only appear on tabs that the user has access to modify. For more information about
when tab contents can be modified, seeClient Tabs on page 311.
To specify the action model to use as the Table of Contents (TOC) menu, set the
action model in your info page builder, like the following :
public InfoConfig buildInfoConfig(ComponentParams params) throws WTException {
InfoComponentConfigFactory factory = getComponentConfigFactory();
InfoConfig infoConfig = factory.newInfoConfig();

// sets the action model for the TOC menu on the Tabs of the info page
infoConfig.setNavBarName("third level nav package");

...

return infoConfig;

986 Customization Guide


The action model for the TOC menu should contain the complete set of items that
can be added to any of the top level tabs.
The TOC menu is a replacement of the Third Level navigation toolbar items found
in prior releases:

TOC Links
The order of content items in a tab can be modified by dragging and dropping the
links in the TOC if the user has the permission to modify the tab contents. See
Client Tabs on page 311 for more information.

Adding a Status Glyph

You can add a status glyph to the information page for a particular business object
type. SeeAdding a Status Glyph on page 987 for more information,

Workspace / Common Space Toggle Buttons


Currently, the CAD Document info pages show Workspace and Common Space
toggle buttons between the Actions menu and the ‘Got to Latest’ link

If you would like to have the info page show the Workspace or Common space
toggle buttons (or any other set of buttons) for a another object type, you’ll need
to set the attribute “toggleButtonConfigs” on the infoModel object. The
attribute “toggleButtonConfigs” takes an array of button configs.

Example JavaScript Button Definition:


// add the buttons to the information page via the ‘beforerender’ event
PTC.infoPage.on("beforerender", addToggleButtons);

// function that adds the buttons to the infoModel object


function addToggleButtons(infoModel) {

Information Pages 987


var cs_button = {
id: 'commonspace_button',
icon: 'com/ptc/windchill/uwgm/cadx/images/csUnHilite.gif',
handler: function() {
var params = {
typeIdForTypeLookup: 'com.ptc.carambola.customization.examples.
infoPage.Carambola',
oid: extractParamValue(getWindow().location.href, 'oid')
};

PTC.infoPage.goTo('', params);
},
tooltip: 'toggle to commonspace'
};

var ws_button = {
id: 'workspace_button',
icon: 'com/ptc/windchill/uwgm/cadx/images/wsHilite.gif',
handler: function() {
var params = {
typeIdForTypeLookup: 'com.ptc.carambola.customization.examples.
infoPage.Carambola',
oid: extractParamValue(getWindow().location.href, 'oid'),
csName: 'Carambola Example',
};

PTC.infoPage.goTo('', params);
},
tooltip: 'toggle to workspace'
};

infoModel.toggleButtonConfigs = [cs_button, ws_button];


}

Help Button

The help button will appear in the upper right corner of the info page if you set a
help context in your info builder:
// sets the help topic to use from the Windchill Help Center
infoConfig.setHelpContext("InfoPageHelpTopic");

See Linking to Help Topics on page 1114 for more information.

988 Customization Guide


Configuration Options via the Type and Attribute Management Utility
The attribute layout for the Attributes panel as well as for the Visualization and
Attributes component is controlled via the layout manager in the Type and
Attribute Management utility.

The layout “More attributes layout” corresponds to the “Attributes” action on the
information page. Likewise, the layout “info page layout for primary attributes”
corresponds to the “Visualization and Attributes” action on the information page.

Attribute Customizations
Attributes v.s. Visualization and Attributes
There is a validator attached to the “Attributes” and “Visualization and Attributes”
TOC options. That validator will hide one or the other based on the visualization
delegate that is found for the object type. So even if both actions are specified in
your TOC action model you would only see one in the UI:
<model name="defaultTOC">
<action name="primaryAttributes" type="object"/>
<action name="visualizationAndAttributes" type="object"/>
</model>

Having both actions in the TOC model allows visualization to be hidden/shown


for a parent and sub types as needed at runtime.
You will not typically need to write a builder class for the Attributes panel, the
Visualization and Attributes component, or the More Attributes panel. You
configure the attributes panels using the Type and Attribute Management utility,

Information Pages 989


as described in n . They are displayed by the PrimaryAttributeBuilder
and VisualizationAttributesBuilder, and
TypedAttributesPanelBuilder classes, respectively.
You can customize the visualization component of the Visualiation and Attributes
panel by writing a custom visualization delegate. See the next section Configuring
the Visualization Component on page 990 for details of how to register a
visualization delegate.

Configuring the Visualization Component

Out of the box there should be a visualization component shown for


Representations, Representables, and Viewables. But there are a couple things that
need to be configured correctly for it to show up. First, make sure you’ve defined
your TOC in the info builder:
infoConfig.setNavBarName(“defaultTOC”)

Second, make sure you’ve included the “Visualization and Attributes” option in
your TOC action model:
<model name="defaultTOC">
<action name="primaryAttributes" type="object"/>
<action name="visualizationAndAttributes" type="object"/>
</model>

You can make a custom visualization delegate if your object type doesn’t have
visualization out of the box, or if you would like to define different visualization
for your object type.
First define a custom visualization delegate with the desired html:
import com.ptc.core.components.rendering.guicomponents.VisualizationComponent;
import com.ptc.core.components.visualization.VisualizationDelegate;

public class CarambolaVisualizationDelegate extends AbstractVisualizationDelegate {


public VisualizationComponent getVisualizationComponent(Object datum,
ServletRequest request) {
String html = "<div id=wvs_pview_div class=vizComponent><IMG src='netmarkets/
images/demodata/carambola.jpg'/></div>";
return new VisualizationComponent(html);
}
}

990 Customization Guide


The html could include javascript if needed. See the VisualizationComponent
javadoc for more details.
Second, register the custom visualization delegate with an typed services xconf
entry:
<Service context="default" name="com.ptc.core.components.visualization.
VisualizationDelegate">
<Option serviceClass="com.ptc.carambola.customization.examples.infoPage.
CarambolaVisualizationDelegate"
requestor="com.ptc.carambola.customization.examples.infoPage.
Carambola"
selector="visualization"
cardinality="singleton"/>
</Service>

Your html should appear in the visualization section. Note, currently the
visualization html is put into a panel with a hard coded width and height of
298x202.
There are some cases where visualization is shown for a parent type but needs to
be hidden for a sub type. For example, visualization is shown for EPMDocuments
but is hidden Notes which are a subtype of EPMDocument. In this case the
visualization component can be hidden for the sub type by registering the
DefaultVisualizationDelegate for that sub type. This will hide the
“visualizationAndAttributes” action from the TOC so you should make sure the
TOC action model for the sub type includes the “primaryAttributes” action:
<model name="defaultTOC">
<action name="primaryAttributes" type="object"/>
<action name="visualizationAndAttributes" type="object"/>
</model>

To see some logging about which delegate is found and when actions are hidden/
shown by that delegate you can enable a log4j logger named com.ptc.core.
components.validators.VisualizationAndAttributesFilter.

Tab Customizations
Configure a Tab with a Default Set of Tables
You can specify a tab to have a set of tables shown by default. To do this, you will
create an action model that contains the actions for the desired default tables. For
example, the “Details” tab on the part information page may define the following
default tables:
<model name="partInfoDefaultDetails" resourceBundle="com.ptc.core.ui.navigationRB">
<action name="visualizationAndAttributes" type="object"/>
<action name="whereUsed" type="object"/>
</model>

Information Pages 991


The tables won’t show up unless they are in the Table of Contents (TOC) action
model. See the Configure the Table of Contents on page 986 for more details.
Please Client Tabs on page 311 or Defining Menus on page 562 for more
information about defining the action model.

Hide/Show Tab Content with Validators


Validators can be used to hide/show tabs or to hide/show tables/panels within the
tabs.
Each tab is an action or action model. Each table or panel is an action. See the
validation documentation for details on how to hook up a validator to an action/
action model.

Load a specific tab or a particular table on a tab


Sometimes it’s necessary to have a specific tab loaded or to bring a user to a
particular table on a tab. Both of these scenarios can be achieved by adding
request parameters to the information page URL.

Load a Specific Tab


To have a particular tab selected when the user navigates to the information page,
set the following URL parameters (both need to be set):

992 Customization Guide


URL Parameter Description
tabAction Specifies the name of the ‘submodel’ or
‘action’ element in the tab set (action
model)
tabType Specifies the object type of the
‘submodel’ or ‘action’.
Submodel: If the tab is defined as a
‘submodel’ in the actionModels.xml
file, set the value of this parameter to
‘object’.
Actions: If the tab is defined as an
‘action’ in the actionModels.xml file,
set the value of this parameter to the
action’s type.
For example, the value for the action
below would be ‘part’:
<objecttype name="part" class=
"wt.part.WTPart">
<action name="createPart">
....
</action>
...
<objecttype>

Load a Specific Table


To bring the user to a specific table (on a certain tab) when the user navigates to
the information page, set the following URL parameters (both need to be set):
URL Parameters Description
tlnAction Specifies the action name that
corresponds to that item on the tab
tlnType Specifies the object type of the action.
For example, the value for the action
below would be ‘part’:
<objecttype name="part" class=
"wt.part.WTPart">
<action name="createPart">
....
</action>
...
<objecttype>

Information Pages 993


Supported Combinations of Tab and Table URL Parameters
Here are the supported combinations of the URL parameters listed in the previous
sections.
Tab Parameters on Tab Parameters not
URL on URL
Table Parameters on User is brought to the
1. If the table is found
URL specified tab and the page on a tab (any tab), the
is scrolled to the given user is brought to that
table tab and the page is
scrolled to the
specified table
2. If the table is not
currently on a tab, a
new tab is created and
the table is added to
that tab
3. If the table does not
exist, an error
message is displayed
Table Parameters not on User is brought to the
1. User is brought back
URL specified tab to the tab that they
recently visited
2. Default to the left
most tab if the user
has not visited the
information page
within the current
browser session.

Configuring tabs through the Windchill UI


The following information gives a high-level overview of how user and
administrator-created tabs can be configured. Please seeClient Tabs on page 311
for more information.

Adding additional tabs for users


Tabs on the information page can be configured by site and organization
administrators, per object type. Site administrators can create tabs that will be
visible for all users, per object type. Organization adminsitrators can create tabs
that will be visible for all members of that organization, per object type.

994 Customization Guide


For example, a site administrator can add a tab called "Site Tab" by navigating to
the information page of any part, and clicking the "+" tab to add a tab. The
administrator may further customize the tab by adding content to the tab, via the
customize link. Any user within this site will now see this "Site Tab" for every
part information page, with the content defined by the administrator. Users will
not be able to modify the tab or its contents, or close the tab
An organization administrator may configure tabs for all members of their
organization in the same way.
Non-administrator users may also create and configure their own tabs, per object
type. These tabs will not be available to other users.

Default Tab Set for End Users


The tabs that a user sees on an information page will be a combination of tabs
defined by the action model for that information page, any tabs configured by the
site administrator, any tabs defined by the organization administrator, and finally
any tabs defined by the user. All tab sets will be specific to an object type
The algorithm for retrieving the tabs for a given information page for a user is as
follows:
• Retrieve the tabs defined by the action model.
• Retrieve the tabs defined by the site administrator for the object type
• Retrieve the tabs defined by user’s organization administrator for the object
type
• Retrieve the tabs defined by user for the object type.

Object Type Icon Customizations

The object type icon is controlled outside of the Information Page component. It is
configurable. For information on configuring the icon see Icon Delegates on page
742.

Item Identifications Customization

The item identification information is controlled outside of the Information Page


component. It is configurable. Item Identification is controlled by the
DisplayIdentification service and its delegates. To configure different
identification information you can create your own
DisplayIdentification delegate that implements the
wt.identity.DisplayIdentification interface.

Information Pages 995


Information Page Stickiness Details
The information page stores its state both on the client (the user’s web browser)
and on the server. It uses client-side stickiness to maintain the currently active tab
and uses server-side stickiness to preserve the order of the top-level tabs. Tabs
created dynamically on the information page (by clicking the “+” tab) are stored
in the database (these may be defined for an entire site, an organization, or per
user).

Client Side Stickiness


The currently active (i.e., selected) tab on the information page is stored on the
client, using client-side stickiness, per object type (unless overridden, see
Overriding Stickiness Key on page 997). For example, if a user has “Tab A”
selected on a document information page, then navigates to the folder browser, the
next time the user goes back to any document information page, “Tab A” will be
the initially active tab.
The active tab will typically be stored for the length of the browser session, or
until the user clears their browser cache. When there is no active tab stored on the
client for a given object type, the left-most tab on the information page will
become the active tab.
Client-side stickiness uses the browser’s offline storage mechanism, and as such,
behavior may vary across different browsers. For more information on client-side
stickiness, please see Overriding Stickiness Key on page 997.

Server Side Stickiness


Much like the client side stickiness, server side stickiness is stored per business
object type (unless overridden, see the see the “Overriding Stickiness Key”
section). That is, the tab order on the information page tabs for Documents is
stored in a different key than the tab order on the page for Parts. As tabs are re-
ordered on each page, the ordering of the tabs is stored on the server via User
Preferences. It will be stored in a separate key for each user. Since the keys are
stored in user preferences on the server, the order of tabs on the page will be
maintained across browser sessions. If a user changes the tab ordering on a
Document information page, those changes will not affect the information for a
Part. However, if a user changes the tab order for Document1, then navigates to
the information page for Document2, the tab order will be the same as
Document1. The server side stickiness can be reset (i.e. cleared) by the end user
by navigating to http://<machine_name>/<Windchill> app/#ptc1/
user/utilitiesList and clicking the link to reset the server side stickiness.
For more information about server-side stickiness, please see Overriding
Stickiness Key on page 997.

996 Customization Guide


User Created Tabs
The contents of a user defined tab are stored per object type (unless overridden,
see Overriding Stickiness Key on page 997). Therefore, a new tab on a Document
information page, “New Tab 1”, could contain different items than a tab on a Part
information page named “New Tab 1”.
As items on a tab are added, removed, and re-ordered, the ordering of the items
are stored on the server in the ClientTab database table. Each tab will be stored in
a separate row for each user. Since tabs are stored in the database, the items
contained on the tab will be maintained across browser sessions.
For more information about how user-created tabs are persisted, see Client Tabs
on page 311.

Overriding Stickiness Key


The stickiness key (or 'tabSetKey') will be used for saving tab order, tab content
and the last active tab. If no tabSetKey is specified by the builder the hard type of
the business object will be used as the tabSetKey. For example, part info page will
end up using a tab set key of "wt.part.WTPart".
Some info pages change this tabSetKey to share behavior across types. For
example, the caddoc and saved caddoc info pages will both have tabSetKey of
"wt.epm.EPMDocument".
Other info pages change this tabSetKey to get different behavior for the same
type. For example, the 'Clash Job Definition' info page will have a different
tabSetKey so that tabs/tables added to that page are not added to the
WTDocument info page.
Be careful with these keys from release to release. Since they are persisted to the
database a migrator will be needed if the key needs to change.

Sample Code

Example implementation for the InfoPageComponent


This example can be viewed in the Windchill product by navigating to
Customization -> Example Information Page. The Customization tab is hidden
out-of-the-box but can be enabled via the “Client Customization” preference
available in Site->Utilities->Preferences Manager.
This example shows an info page for an object of the new type “Carambola.”. The
Carambola object type is a simple Java class with an icon and various attributes.
The example illustrates how to:
• create a set of tabs
• define a tab customization menu (tab actions)
• define an action dropdown menu

Information Pages 997


• display status glyphs next to the object name
• add a help topic
• construct a custom VisualizationDelegate
• use a custom view jsp that adds toggle buttons for commonspace/ workspace
and a Go to Latest link.
Two of the tabs displayed on the info page illustrate what happens when the server
encounters errors when producing a page. The tab “Error Page With Generic
Exception” shows how exception messages are displayed when java or scriplet
code executed on a jsp page throws an exception. The tab “404 error” shows how
a HTTP 404 response code is displayed when the jsp page specified in an action
could not be found. The action “Action Has Invalid Onclick” in the Actions menu
illustrates the message that is provided when the javascript provided in the
“onclick” attribute of an action command subtag is invalid.
The action “Action Has Complex Onclick” illustrates another action with an
invalid “onclick” attribute. Onclick attributes should contain a single javascript
function call. In this case, the onclick attribute has multiple function calls. The
action framework wraps the multiple statements in one function call to prevent the
page display from aborting.
The panels and tables available for display on the info page tabs via the Customize
link are ones created for other examples in the Customization tab, such as the
Attribute Panel, Property Panel, and Table examples.

998 Customization Guide


Files Used in this Example
Action Models Used in this Example
Action Model File Action Model Names
Name: CustEx_infoPage_tabset
Carambola- carambola_details
actionModels.xml
CustEx_default_myTab
Codebase path:
codebase/config/actions CustEx_error_on_page
CustEx_error_404
CustEx_infoPage_third_level
_navigation
CustEx_submodel_simpleTable
CustEx_submodel_
advancedTable
CustEx_InfoPage_attributes
carambola_info_page
carambola_sub_model

Actions Used in this Example


Action File Action Names
Name: CustEx_simpleTable1
Carambola-actions.xml CustEx_simpleTable2
Codebase path: CustEx_simpleTable3
codebase/config/actions
CustEx_advancedTable1
CustEx_advancedTable_custom
_oid_actions
CustEx_error_on_page
CustEx_error_404
propertyPanel
attributePanel
visualizationAndAttributes
primaryAttributes
onclickIsInvalid
onclickToBeWrapped

Information Pages 999


Files Used in this Example
File Description
Carambola.jar “Carambola” object class
Source code examples are located in
the Carambola-java.jar file
in the <Windchill>\
Windchill\srclib\wnc
diretory.
CarambolaVisualizationDe Delegate that creates the content for the
legate.java VisualizationComponent on the page
Source code examples are located in
the Carambola-java.jar file
in the <Windchill>\
Windchill\srclib\wnc
diretory.
CarambolaInfoBuilder.ja Info page builder class for object type
va “Carambola”
Source code examples are located in
the Carambola-java.jar file
in the <Windchill>\
Windchill\srclib\wnc
diretory.
CarambolaVizAndAttrBuil Builder for the Visualization and Attributes
der.java penel. You do not typically need to write a
Source code examples are located in builder for this panel. Such a builder was
the Carambola-java.jar file required for this example only because the
in the <Windchill>\ “Carambola” object type is not a type
Windchill\srclib\wnc exposed in the Type Manager.
diretory.
carambolaInfoPage.jsp View (jsp) for the page with javascript to
Source code examples are located in produce toggle buttons and Go to Latest
the Carambola-java.jar file link.
in the <Windchill>\
Windchill\srclib\wnc
diretory.
<Windchill>\Windchill\ VisualizationDelegate service property
codebase\com\ptc\
carambola\
carambola.service.proper
ties.xconf

1000 Customization Guide


Updating Legacy information Pages
If you have an info page jsp using describeInfoPage and infoPage.jspf here are the
steps to convert to the new design:
1. Create an InfoBuilder.
a. Many of the attributes on the describeInfoPage tag should have a
corresponding setter on the InfoConfig.
i. id, helpContext, actionListName, navBarName,
b. The propertyPanel, moreAttributesActionName,
moreAttributesActionType attributes (and the addPropertyPanel tag) are
obsolete. See step 4 for how to create your attribute layouts.
c. The describeStatusGlyph tags will become properties on the InfoConfig.
(see Adding a Status Glyph on page 987)
2. Configure the Help Button if necessary (see Help Button on page 988)
3. Configure Visualization if necessary (see Configuring the Visualization
Component on page 990)
4. Create an attribute layout for your object type using one of these 3 options:
a. Through the Type and Attribute Management utility. (see Type and
Attribute Management)
b. Through the Type and Attribute Management utility. (see the “Type and
Attribute Management” online help topic for more information)
c. With a load file.
d. With a custom attribute panel builder. See the Packaged Samples.
5. Delete the xconf entry for your info page jsp
a. If there is an xconf entry for your object type, that will be used instead of
the InfoPageBuilder.
6. Delete the describeInfoPage tag and infoPage.jspf include from your info.jsp
7. If there is something left in your jsp that you want displayed on the info page
(some tables or property panels), move those tables/property panels into the
third level nav bar (which becomes the Table of Contents). This way the
tables/panels shown can be configured by admins and the end user.
a. Create a separate action for each table/panel. See the Actions Framework
documentation for more info on actions/action models.
i. Preferred – create a builder for each table/panel. See the MVC table
documentation. The resulting actions.xml entry will be something like:
<action name="myTable">
<component name="myTable" typeBased="true" windowType="page"/>
</action>

Information Pages 1001


ii. Legacy way – create a separate jsp for each table/panel. The resulting
actions.xml entry will be something like:
<action name="myTable">
<command windowType="page"/>
</action>
b. Add those actions to your navBarName action model. Make sure you have
set that navBarName in the InfoBuilder. (see the Configure the Table of
Contents on page 986 for more details. )
c. Configure which tables/panels are shown out of the box on the Details tab.
See Tab Customizations on page 991 for more information.

Debugging
Add jcaDebug=true to the URL to see some debug info displayed on the info
page. http://<hostName>/<webApp>/app/#ptc1/tcomp/
infoPage?typeIdForTypeLookup=
com.ptc.carambola.customization.examples.infoPage.Caram
bola&jcaDebug=true In particular, at the top of the page jcaDebugdisplays
whether a ComponentConfigBuilder or a jsp produced the page.
Also available are which action models were used for the Actions menu, the top
tab set and the Customize option that lets you add tables to the tabs. See the
jcaDebug documentation for more details about what is displayed and where to
find it.

Log4J
The following log4J loggers are available to provide you more information when
debugging your Information Page implementation:
Logger Description
com.ptc.core.components. Logs information related to the hiding
validators. and showing of the primaryAttributes
VisualizationAndAttributesFilter or visualizationAndAttributes
components. See Attributes v.s.
Visualization and Attributes
com.ptc.jca.mvc.components. Logs information related to finding the
AbstractInfoComponentBuilder context object for the information page.

1002 Customization Guide


Logger Description
com.ptc.mvc.components. Logs information related to the view
AbstractInfoConfigBuilder chosen for the information page. This
may be useful if you are trying to set a
custom view.
com.ptc.jca.mvc.controllers. Logs information related to determining
TypeBasedIncludeController whether the requested information page
is being rendered with a legacy jsp or
an MVC builder.

Log4javascript
Log4javascript is also available for debugging within the browser. You can turn
this on by adding a parameter to the end of the url. “&jsLog=PTC”. This will turn
on all the JavaScript logging. You will then see the logging information in the FF/
Chrome console or in a separate console which opens when you add the parameter
in IE browsers. The following loggers can also be turned on individually by
setting jsLog=<loggername>.
Logger Description
PTC.infoPage Logs information about errors
encountered when rendering an info
page as well as, information related to
refreshing the top area of the page.
PTC.infoPage.ActiveTab Logs information related to selecting
the active tab based on defaults,
stickiness and potential overrides.
PTC.jca.state.ClientStateStore Logs information related to the
stickiness information being stored and
retrieved for client side stickiness.
PTC.infoPageTableMgr Logs information about the adding and
removing of tables from the tabs on an
information page.
PTC.jca.manager Logs information about the adding and
removing of tables from the tabs on an
information page and about the adding
and removing of tabs.

Information Pages 1003


19
Incorporating Pickers in JSP
Clients
Configuring Pickers ............................................................................................... 1006
Configuring a Context Picker .................................................................................. 1015
Configuring an Item Picker ..................................................................................... 1025
Configuring an Organization Picker......................................................................... 1034
Configuring a Type Picker ...................................................................................... 1043
Configuring a User Picker ...................................................................................... 1061
Configuring a Participant Picker in JCA ................................................................... 1068
Configuring a Participant Picker in AngularJS .......................................................... 1083

This chapter describes how to customize and configure pickers.

1005
Configuring Pickers
Solution
Write a custom JSP page and use the Item Picker tag to display the picker.
Configure the search criteria fields to be included in the picker using the
PickerAttributes.xml file. Configure the object types and containers to be
searched using parameters on the itemPicker tag.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving HTML forms, JSP, XML.
• Picker common components
• Table common component
• View creation

Solution Elements
Element Type Description
pickerAttributes.xml XML Runtime location:
<Windchill>\codebase\picker
Attributes.xml
SearchResultsTable Xconf Runtime location:
.properties.xconf <Windchill> \codebase\com
\ptc\netmarkets\search\
SearchResultsTable.
properties.xconf
This file can be used to configure table
view definition.

1006 Customization Guide


Procedure - Launching the picker and defining the object
types to be searched
The picker can be launched from your JSP by calling the itemPicker tag:
<wctags:itemPicker id="customized_item_picker" objectType="WCTYPE|
wt.part.WTPart|org.r_and_d.mypart" componentId="customizedItemPicker
ForSoftPart "/>

The objectType parameter indicates that the search should be limited to


objects of type org.r_and_d_mypart.
The value of the id parameter should be an identifier that is unique for the given
page.
The value of the componentId parameter is a key that will be used to look up
the search criteria to be presented in the picker. This is described in the next
section.

Procedure - Customizing the Picker Search Criteria


The search criteria for a picker can be customized using the file
pickerAttributes.xml. First define a new component id for the picker
using the componentID parameter on the picker tag, as shown above, and then
define the object attributes to be used as search criteria in the xml file as shown
below.
<ComponentID id="customizedItemPickerForSoftPart">
<ObjectType id="WCTYPE|wt.part.WTPart|org.r_and_d.mypart">
<SearchCriteriaAttributes>
<Attributes>
<Name>name</Name>
<DisplayName>NAME_LABEL</DisplayName>
<IsSearchable>true</IsSearchable>
</Attributes>
</SearchCriteriaAttributes>
</ObjectType>
</ComponentID>
If the componentID attribute is not specified or if you do not define search
criteria in pickerAttributes.xml, by default pickerSearch
componentId is used to display the search criteria. The
pickerAttributes.xml files can be modified by customers and is the only
file to be modified in this regard. This file contains only search criteria and not the
object types. Prefix WCTYPE is allowed in this xml file. It is required in case of
subtypes. For hard types only object type is required.
In this example, the component id is the component id defined for our picker on
the picker tag (see Procedure - Launching the picker and defining the object types
to be searched on page 1007). We have defined a single attribute to be searchable,
which is the attribute nameon the object type org.r_and_d.mypart.

Incorporating Pickers in JSP Clients 1007


${domain} is specific to EPM document. It is generic and not internal to
developers.
This xml file contains search criteria input fields and not types.
If you were searching for more than one object type, you will have to add entries
for other object types after first object type under same component id.
In case of multiple type searches, generic (persistable object type) criteria will be
displayed.
Common Customization Points are listed in following tables:
Parameter Default Possible Req? Description
Value Values
Id Anything that Yes An ID is associated
is unique in a with every picker in
page Scope of the calling
application. This ID
has to be unique for
all pickers,
irrespective of type
on one page.
The id should not
contain "." (Dot) in
the name.
componentId pickerSearch Any valid No componentId
component id determines the
specified in attributes that
pickerAttri- should appear in
butes.xml search criteria panel
for the given picker.
pickerCallback Generated at Name of the No Name of the
runtime if user callback customized callback
has not function javascript function
specified this that a user would
parameter have to implement.
It’s recommended
that you should
specify
pickerCallback
function in custom.
js file
“” (blank) Any values No Default value for
defaultValue
textbox rendered by

1008 Customization Guide


Parameter Default Possible Req? Description
Value Values
the picker.
Label Context Picker Any value No Label of the picker.

displayAttri- Name Any attribute No Name of the


bute attribute that should
be the displayed in
the picker textbox
after selecting result
from the item
picker.
containerRef “” (blank) Any container No Value of the
containerRef in
which a user wants
to restrict the
search.
baseWhere “” (blank) Any valid I*E No Additional where
Clause where clause clause if you want
query to filter search
results on some
specific criteria
regardless of user
input. This where
clause will get
“ANDed” with the
internal where
clause.
pickerTitle Contexts Any value No Default value of the
hidden textbox
associated with the
picker.
pickedData <WebApp>/ URL location No URL of the data
Fetcher netmarkets/jsp/ of the fetcher fetcher file that will
search/picked file be used by the
Data.jsp AJAX call to
process the selected
results.
Editable True true/false No This attribute
defines whether you
want to have find

Incorporating Pickers in JSP Clients 1009


Parameter Default Possible Req? Description
Value Values
icon along with the
textbox.
readOnlyPic False true/false No This attribute
kerTextBox defines whether the
picker text box
should be editable
or not.
Inline False true/false No You should specify
this parameter with
value as true when
you want to launch
picker as a table
level action or
inline.
pickedAtt Name Any comma No This parameter
ributes separated list contains a comma
of valid separated list of the
attributes attributes that a user
wants a picker to
fetch. This is
applicable only if
inline is “true”.
pickerType search search/picker No This parameter
defines the picker
type i.e. “search”
picker or “picker”
picker. In search
picker, you will see
search criteria in the
picker and then you
have to click the
search button to see
the results however
in case of “picker”
picker you will
directly see the
results table without
any search criteria.

1010 Customization Guide


Parameter Default Possible Req? Description
Value Values
pickerText 25 Any numeric No This parameter
BoxLength value defines the length
of the picker text
box.
searchResults “”(blank) Any valid No This parameter
ViewId view id allows user to
define custom view
id for the picker
search results table.

Incorporating Pickers in JSP Clients 1011


Procedure - Defining the containers to be searched
To confine the search to objects in certain containers, use the
containerRefparameter on the picker tag. The value of this parameter should
be a comma-separated list of one or more WTContainerRef objects, in string
format, for the containers you want to search.
The WTContainerRefs for the containers can be fetched by querying for the
containers and getting the WTContainerRef for each from the WTContainer
object.
If no containerRef parameter is provided, all containers will be searched.
<wctags: itemPicker id=" customized_item_picker”
objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart"
containerRef=" OR: wt.pdmlink.PDMLinkProduct:33707”
componentId="customizedItemPickerForSoftPart" />

Procedure - Customizing the search result table view


Search result tables use the table common component and hence the column
display can be configured by creating a new table view.
You will first need to create a new JCAConfigurableTable Java class
defining your table view.
Then create a service property entry in a *.properties.xconf file that can
be used to look up your table view class based on an identifier you choose called
the “selector.” For example, if your table view class was
CustomizedPartView, your service property entry might look like this:
<Service context="default"
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">
<Option
serviceClass="com.ptc.netmarkets.search.views.CustomizedPartView"
requestor="java.lang.Object"
selector="wt.part.WTPart.customizedSearchView "/>
</Service>

Finally, pass the selector as below to the picker tag, as shown below, and the
search results table will be rendered with this view.
<wctags: itemPicker id=" customized_item_picker"
objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart"
containerRef="<OR: wt.pdmlink.PDMLinkProduct:33707”
componentId="customizedItemPickerForSoftPart"
searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

1012 Customization Guide


Sample Code
<html>
<body>
<table>
<tr>
<%-- launching user picker--%>
<wctags:userPicker id="testUserPicker" label="MyUserPicker"
readOnlyPickerTextBox="false" editable="true" showSuggestion="true"
suggestMinChars="5" />
</tr>

<tr>
<%-- launching organization picker--%>
<wctags: organizationPicker id="orgPicker" label="MyOrgPicker"
readOnlyPickerTextBox="false" editable="true" showSuggestion="true"
suggestMinChars="3"/>
</tr>

<tr>
<%-- launching context picker--%>
<wctags: contextPicker id="contextPicker" label="MyContextPicker"
pickerTitle="ContextPicker" />
</tr>

<tr>
<%-- launching Item picker--%>
<wctags:itemPicker id="itemPicker" label="MyItemPicker"
pickerTitle="ItemPicker"/>
</tr>

<tr>
<%-- launching Item picker with exclude sub types and access
controller --%>
<wctags:itemPicker id="CustomizedItemPicker" label="CustomizedItemPicker"
pickerTitle="CustomizedItemPicker"excludeSubTypes="WCTYPE|wt.doc.WTDocument|
org.rnd.Minutes,WCTYPE|wt.doc.WTDocument|org.rnd.General"
customAccessController="com.ptc.windchill.
enterprise.search.server.LatestVersionAccessController"/>
</tr>

<tr>
<%-- launching Item Masterpicker--%>
<wctags:itemMasterPicker id="itemMasterPicker"
label="MyItemMasterPicker"/>
</tr>

<tr>
<%-- launching Item Masterpicker--%>
<wctags:genericPicker id="genericPicker"objectType="wt.part.WTPart"label
="Part Picker using generic" />
</tr>

Incorporating Pickers in JSP Clients 1013


<tr>
<%-- launching Item Masterpicker--%>
<wctags:genericPicker id="viewPicker" objectType="wt.vc.views.View" label="
View Picker
using generic" pickerType="tree" />
</tr>

<tr>
<%-- launching Recently Visited Context Picker- Single Select--%>
<wctags:contextPicker id="containerTypeListSingleSelect" label="
Recently Visited Context Picker-
Single Select" pickerTitle="ContextPicker" showRecentlyUsed="true"
displayAttribute="containerInfo.name"/>
</tr>

<tr>
<%-- launching Recently Visited Context Picker- Multi Select--%>
<wctags:contextPicker id="containerTypeListMultiSelect" label="Recently
Visited Context Picker- Multi Select" pickerTitle="ContextPicker"
showRecentlyUsed="true" displayAttribute="containerInfo.name"
showMultiSelectRecentlyUsed="true"/>
</tr>
</table>
</body>
</html>

1014 Customization Guide


Configuring a Context Picker
Objective
You want to add a context picker to a custom UI and need to configure the picker
to:
• Search only for objects of certain type(s)
• Search only for objects in certain container(s)
• Display certain search criteria input fields
• Display certain attributes of the objects in the search results table

Background
The context picker is used when you have a requirement to perform an operation
that is based on certain context.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are putting tag
includes “/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/
beginPopuf.jspf” file and “/netmarkets/jsp/end.jspf” files.

Intended Outcome
You should see a text box and a Find icon along with the specified label after
using the tags for context picker. After clicking the Find icon, the context picker
will be launched.

Incorporating Pickers in JSP Clients 1015


On clicking Find icon you should see a Context Picker for Project as follows:

Solution
Use the Context Picker Common Component in your JSP file to include Context
Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving JSP, JavaScript, Custom taglibs
• The management of resource bundle file customizations
• Windchill xconfmanager concepts

Solution Elements
Element Type Description
PickerAttributes.xml XML You should use this file to
customize the search criteria
attributes for an object type
for your picker.
Runtime location:
<Windchill>\codebase\
pickerAttributes.xml
searchClientResource.java Resource bundle file You should use this file to
localize the contents of the
pickers.
contextPicker.tag Custom JSP tag file This file contains the

1016 Customization Guide


Element Type Description
information about the
supported parameters for
this tag.
Runtime location:
<Windchill>\codebase\
WEB-INF\tags\Context
Picker.tag
SearchableTypes.properties xconf Properties file You should specify
.Xconf component Id and
corresponding object types
in this file and then run
xconfmanager.
Runtime location:
<Windchill>\codebase\
com\ptc\windchill\enterprise
\
search\server\Searchable
Types.properties.xconf
custom.js JavaScript file You should specify custom
pickerCallback function for
picker in this file.
Runtime location:
<Windchill>\codebase\
netmarkets\jsp\search\
custom.js

Note
You want to disable the type picker in the Context Picker.

Procedure – Including a Context Picker in a jsp page


The context picker can be launched from your JSP by calling the
contextPicker tag:
<tr>
<wctags:contextPicker id="contextPickerId" />
</tr>

Incorporating Pickers in JSP Clients 1017


Customization Points
Customization Points are listed in following tables:
Parameter Default Possible Req? Description
Value Values
Id Anything False An ID is associated
that’s unique with every picker in
in a page the calling
application. This ID
has to be unique for
all pickers, whether
of different types or
same type, in one
page. The id should
not contain "." (dot)
in the name.
componentId pickerSearch Any valid No componentId
component id determines the
specified in attributes that
picker should appear in
Attributes.xml search criteria panel
of the given picker.
pickerCallback Generated at Name of the No Name of the
runtime if user callback customized callback
has not function function that a user
specified this would have to
parameter implement. It’s
recommended that
you specify
pickerCallback
function in custom.
js file
defaultValue “” (blank) Any values No Default value for
textbox rendered by
the picker.
defaultHidden “” (blank) Any values No Default value of the
Value hidden textbox
associated with the
picker.
pickedData <WebApp>/ URL location No URL of the data
Fetcher netmarkets/ of the fetcher fetcher file that will
jsp/search/ file be used by the

1018 Customization Guide


Parameter Default Possible Req? Description
Value Values
pickedData.jsp AJAX call to
process the selected
results.
Label Context Picker Any value No Label of the picker.
displayAttri- Name Any attribute No Name of the
bute attribute that should
be the displayed in
the picker textbox
after selecting result
from the context
picker
containerRef “” (blank) Any container No Value of the
containerRef in
which a user wants
to restrict the
search.
baseWhere “” (blank) Any valid I*E No Additional where
Clause where clause clause if you want
query to filter search
results on some
specific criteria
regardless of user
input. This where
clause will just get
“ANDed” with the
internal where
clause.
pickerTitle Contexts Any value No Title of the picker.
pickedData <WebApp>/ URL location No URL of the data
Fetcher netmarkets of the fetcher fetcher file that will
/jsp/search/ file be used by the
pickedData.jsp AJAX call to
process the selected
results.
Editable True true/false No This attribute
defines whether you
want to have Find
icon along with the
textbox or not.
False true/false No This attribute

Incorporating Pickers in JSP Clients 1019


Parameter Default Possible Req? Description
Value Values
readOnlyPick- defines whether the
er picker text box
TextBox should be editable
or not.
typeComp Foundation. Any valid No This parameter is
onentId contextPicker componentId passed to define set
specified in of types that can be
Searchable shown in Type
Types. Picker
properties file
Inline False true/false No You should specify
this parameter with
value as true when
you want to launch
picker from a table
level action or
inline.
pickedAttri- Name Any comma No This parameter
butes separated list contains a comma
of valid separated list of the
attributes attributes that a user
wants a picker to
fetch. This is
applicable only if
inline is “true”.
showType- true true/false No This parameter
Picker should be used to
enable type picker
in the picker.
pickerType search search/picker No This parameter
defines the picker
type i.e. “search”
picker or “picker”
picker. In search
picker, you will see
search criteria in the
picker and then you
have to hit the
search button to see
the results however

1020 Customization Guide


Parameter Default Possible Req? Description
Value Values
in case of “picker”
picker you will
directly see the
results table without
any search criteria.
pickerTextBox 25 Any numeric No This parameter
Length value defines the length of
the picker text box.
searchResults “”(blank) Any valid No This parameter
ViewId view id allows user to define
custom view id for
the picker search
results table.
customAccess “” (blank) Any valid No This parameter is
Controller name used to define your
own custom access
controller. This
parameter would
accept the complete
class name as the
value. To specify
multiple
customAccess
Controller you can
pass on comma (,)
separated list of the
class names.
excludeSub “” (blank) Any valid No This parameter is
Types subtypes used to exclude sub
types from the
search.
extraSuggest emailId Any field user False This parameter is
Attribute wants to used to specify the
search on extra attributes that
are to be used for
auto-suggest
showSugges- false True/false False This property is
tion used to enable auto-
suggest to the
picker.

Incorporating Pickers in JSP Clients 1021


Parameter Default Possible Req? Description
Value Values
suggestMin 1 integer False This parameter is
Chars used to specify the
min. character on
which auto-suggest
initiates if enabled
suggestService Picker specific userPicker, False Key for selecting
Key partPicker etc. suggestable class (e.
g. ContextService
PickerSuggestable)
which in turn call
query service.Key
needs to be present
in search-service.
properties.xconf
file.
mergeContain- False The passed
er container types will
Types be merged in
recently visited
combo box though
they are not part of
recently visited list.
This property must
be used only for
search page for
pickers do not use
this property.
onChangeFor False This depends on
RecentlyUsed showRecently
Used=true. User can
provide the custom
onchange function
for recently used
combo.

1022 Customization Guide


Parameter Default Possible Req? Description
Value Values
showMember false True/false False The two checkboxes
OfCheckBoxes 'I am member of'
and 'In my
organization' will be
shown if this
property is made
true.
showMulti false True/false False If this property is
SelectRecently made true multi
Used select recently used
context picker will
be shown. In this
case you need to
modify your
callback function
and onchange
function. Default
value is false.
Implemented for
search page only.

Configuring Context Picker without type picker


<wctags:contextPicker id="contextPickerId"
showTypePicker="false"/>

Configuring Context Picker with multi select option in


results table
<wctags:contextPicker id="contextPickerId" multiSelect="true" />

Configuring Context Picker with your own


typeComponentId in the type picker
<wctags:contextPicker id="contextPickerId" typeComponentId="
Foundation.myContextPickerComponentId" />
where Foundation.myPickerComponentId is available in
SearchableTypes.properties file.

Configuring baseWhereClause in Context picker


<wctags:contextPicker id="contextPickerId"
baseWhereClause="(name=’demo*’)" />

Incorporating Pickers in JSP Clients 1023


Configuring pickerCallback function in Context picker
<wctags:contextPicker id="contextPickerId"
pickerCallback="myPickerCallback" />
myPickerCallback function can be like:
function myPickerCallback(objects, pickerID)

var updateHiddenField = document.getElementById(pickerID);

var updateDisplayField = document.getElementById(pickerID +


"$label$");

var myJSONObjects = objects.pickedObject;

for(var i=0; i< myJSONObjects.length;i++) {

var oid = myJSONObjects[i].oid;

// Here “name” is the displayAttribute requested

var displayAttr = eval("myJSONObjects[i].name");

updateHiddenField.value=oid;

updateDisplayField.value=displayAttr;

1024 Customization Guide


Configuring an Item Picker
Objective
You want to pick instance(s) of Windchill business objects.

Background
The item picker is used when you have a requirement to select specific business
object(s) depending upon certain criteria and use them in your application.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are putting tag includes
“/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/
beginPopuf.jspf” file and “/netmarkets/jsp/end.jspf” files.

Intended Outcome
You should see a text box and Find button along with the specified label after
using the tags for item picker. After clicking the Find button, the item picker will
be launched.

Incorporating Pickers in JSP Clients 1025


On clicking the Find button you should an Item Picker as:

Solution
Use the Item Picker Common Component in your JSP file to include Item Picker
in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving JSP, JavaScript, Custom taglibs
• The management of resource bundle file customizations
• Windchill xconfmanager concepts

Solution Elements
Element Type Description
pickerAttributes.xml XML file You should use this file to customize
the search criteria attributes for an
object type for your picker.
Runtime location:
<Windchill>\codebase\picker
Attributes.xml
searchClient Resource bundle You should use this file to localize
Resource.java file the contents of the pickers.

1026 Customization Guide


Element Type Description
itemPicker.tag Custom JSP tag This file contains information about
file the supported parameters for this tag.
Runtime location:
<Windchill>\codebase\WEB-INF\
tags\itemPicker.tag
SearchableTypes. xconf Properties You should specify component Id
properties.xconf file and corresponding object types in
this file and then run xconfmanager.
Runtime location:
<Windchill>\codebase\com\ptc\
windchill\enterprise\search\server\
SearchableTypes.properties.xconf
custom.js JavaScript file You should specify custom
pickerCallback function for picker in
this file.
Runtime location:
<Windchill>\codebase\netmarkets\
jsp\search\custom.js

Note
You want to disable the type picker in the Item Picker.

Procedure – Including an Item Picker in a jsp page


Configure basic item picker:
<tr>

<wctags:itemPicker id="itemPickerId" />

</tr>

Incorporating Pickers in JSP Clients 1027


Customization Points
Parameter Default Possible Req? Description
Value Values
Id Anything Yes An ID is associated
that’s unique with every picker in
in a page the calling
application. This ID
has to be unique for
all pickers, whether of
different types or
same type, in one
page. The id should
not contain "." (dot) in
the name.
componentId pickerSearch Any valid No componentId
component id determines the
specified in attributes that should
picker appear in search
Attributes.xml criteria panel of the
given picker.
pickerCallback Generated at Name of the No Name of the
runtime if user callback customized callback
has not function function that a user
specified this would have to
parameter implement. It’s
recommended that
you specify
pickerCallback
function in custom.js
file
defaultValue “” (blank) Any values No Default value for
textbox rendered by
the picker.
defaultHidden “” (blank) Any values No Default value of the
Value hidden textbox
associated with the
picker.
Label Item Picker Any value No Label of the picker.
displayAttri- Name Any attribute No Name of the attribute
bute that should be
displayed in the picker

1028 Customization Guide


Parameter Default Possible Req? Description
Value Values
textbox after selecting
result from the item
picker
containerRef “” (blank) Any container No Value of the
containerRef in which
a user wants to restrict
the search.
baseWhere “” (blank) Any valid I*E No Additional where
Clause where clause clause if you want to
query filter search results on
some specific criteria
regardless of user
input. This where
clause will just get
“ANDed” with the
internal where clause.
pickerTitle Item Any value No Title of the picker.
pickedData <WebApp>/ URL location No URL of the data
Fetcher netmarkets/ of the fetcher fetcher file that will
jsp/search/ file be used by the AJAX
pickedData.jsp call to process the
selected results.
Editable True true/false No This attribute defines
whether you want to
have the Find icon
along with the textbox
or not.
readOnly False true/false No This attribute defines
PickerTextBox whether the picker
text box should be
editable or not.
typeCompon Foundation. Any valid No This parameter is
entId contextPicker componentId passed to define set of
specified in types that can be
Searchable shown in Type Picker
Types.
properties file
Inline False true/false No You should specify
this parameter with
value as true when

Incorporating Pickers in JSP Clients 1029


Parameter Default Possible Req? Description
Value Values
you want to launch
picker from a table
level action or inline.
picked Name Any comma No This parameter
Attributes separated list contains a comma
of valid separated list of the
attributes attributes that a user
wants a picker to
fetch. This is
applicable only if
inline is “true”.
showType True true/false No This parameter should
Picker be used to enable type
picker in the picker.
pickerType search search/picker No This parameter
defines the picker type
i.e. “search” picker or
“picker” picker. In
search picker, you will
see search criteria in
the picker and then
you have to hit the
search button to see
the results however in
case of “picker”
picker you will
directly see the results
table without any
search criteria.
pickerText 25 Any numeric No This parameter
BoxLength value defines the length of
the picker text box.
searchResults “”(blank) Any valid No This parameter allows
ViewId view id user to define custom
view id for the picker
search results table.
customAccess “” (blank) Any valid No This parameter is used
Controller name to define your own
custom access
controller. This

1030 Customization Guide


Parameter Default Possible Req? Description
Value Values
parameter would
accept the complete
class name as the
value. To specify
multiple
customAccess
Controller you can
pass on comma (,)
separated list of the
class names.
objectType wt.fc. wt.part. No Name of object type
Persistable WTPart that should be present
as the default object
type
excludeSub “” (blank) Any valid No This parameter is used
Types subtypes to exclude sub
types from the search.
defaultItera- ALL ALL No Value of iteration field
tion that should be set.
Value Default value is ALL
defaultVersion ALL ALL No Value of revision field
Value that should be set.
Default value is ALL
typePicker No Format of type picker.
Format Value should one of
*dropdown*, *table*,
*tree*
singleSelect No This parameter is used
TypePicker for setting type picker
for single or multi
select
typePicker No This parameter is used
ObjectList to for setting list of
object type based on
certain relation in type
picker
typePicker No This parameter is used
DefaultType for setting default
selected type in type

Incorporating Pickers in JSP Clients 1031


Parameter Default Possible Req? Description
Value Values
picker
typePicker No This parameter is used
SubTypeDis- for showing or hiding
play subtypes.Possible
values are ROOT_
TYPES (only
seedTypes will be
displayed), SOFT_
TYPES (only SOFT
Types will be
displayed), BOTH
(MODELED & SOFT
Types will be
displayed)
typePicker No This parameter is used
ShowRoot for setting Shows the
seedTypes as I level
elements
showAll No This parameter is used
ObjectTypes for showing All
Applicable Object
Type in type picker
excludeRef A Comma No This parameter is used
separated list to specify comma
of object refs separated list object
to be excluded ref to be excluded
from search from search results.

Configuring Item Picker without type picker


<wctags:itemPicker id="itemPicker" showTypePicker="false"/>

Configuring Item Picker with default object type


<wctags:itemPicker id="itemPicker" objectType="wt.part.WTPart" />

Configuring Item Picker with multi select option in results


table
<wctags:itemPicker id="itemPicker" multiSelect="true" />

1032 Customization Guide


Configuring Item Picker with your own typeComponentId in
the type picker
<wctags:itemPicker id="itemPicker" typeComponentId="
Foundation.myPickerComponentId" />
where Foundation.myPickerComponentId is available in
SearchableTypes.properties file.

Configuring baseWhereClause in Item picker


<wctags:itemPicker id="itemPicker"
baseWhereClause="(name=’demo*’)" />

Configuring pickerCallback function in Item picker


<wctags:itemPicker id="itemPicker"
pickerCallback="myPickerCallback" />
myPickerCallback function can be like:
function myPickerCallback(objects, pickerID)

{
var updateHiddenField = document.getElementById(pickerID);
var updateDisplayField = document.getElementById(pickerID +
"$label$");
var myJSONObjects = objects.pickedObject;
for(var i=0; i< myJSONObjects.length;i++) {
var oid = myJSONObjects[i].oid;
// Here “name” is the displayAttribute requested
var displayAttr = eval("myJSONObjects[i].name");
updateHiddenField.value=oid;
updateDisplayField.value=displayAttr;
}
}

Incorporating Pickers in JSP Clients 1033


Configuring an Organization Picker
Objective
Problem: You want to add an organization picker to a custom UI and need to
configure the picker to:
• Search only for objects of certain type(s)
• Search only for objects in certain container(s)
• Display certain search criteria input fields
• Display certain attributes of the objects in the search results table

Background
The organization picker is used when you have a requirement to select specific
organization(s) depending upon certain criteria and use them in your application.
Typical use case could be that you may want to find parts that are available in
particular organization. In this case, you can have a organization picker and then
through this you can select the organization and pass it on to the search criteria to
perform search for parts.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are putting tag
includes “/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/
beginPopuf.jspf” file and “/netmarkets/jsp/end.jspf” files.

Intended Outcome
You should see a text box and a Find button along with the specified label after
using the tags for organization picker. After clicking the Find… button, the
organization picker will be launched.

1034 Customization Guide


On clicking Find… button you should see an organization picker.

Solution
Use the Organization Picker Common Component in your JSP file to include
Organization Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving JSP, JavaScript, Custom taglibs
• The management of resource bundle file customizations
• Windchill xconfmanager concepts

Incorporating Pickers in JSP Clients 1035


Solution Elements
Element Type Description
PickerAttributes.xml XML pickerAttributes.xml
XML file You should use
this file to customize the
search criteria attributes
for an object type for your
picker.
Runtime location:
<Windchill>\codebase\
pickerAttributes.xml
searchClientResource. Resource bundle file You should use this file to
java localize the contents of
the pickers.
organizationPicker.tag Custom JSP tag file This file is contains the
information about the
supported parameters for
this tag.
Runtime location:
<Windchill>\codebase\
WEB-INF\tags\
ContextPicker.tag
SearchableTypes.proper xconf Properties file You should specify
ties.Xconf component Id and
corresponding object
types in this file and then
run xconfmanager.
Runtime location:
<Windchill>\codebase\
com\ptc\windchill\
enterprise\search\
server\Searchable
Types.properties.xconf
custom.js JavaScript file You should specify
custom pickerCallback
function for picker in this
file.
Runtime location:
<Windchill>\codebase\
netmarkets\jsp\search\
custom.js

1036 Customization Guide


Note
You want to disable the type picker in the Context Picker.

Procedure – Including an Organization Picker in a jsp page


The organization picker can be launched from your JSP by calling the
organizationPicker tag:
<tr>
<wctags:organizationPicker id="organizationPickerId" />
</tr>

Customization Points
Parameter Default Possible Req? Description
Value Values
Id Anything that False An ID is associated
is unique in a with every picker in
page the calling
application. This ID
has to be unique for
all pickers, whether
of different types or
same type, in one
page. The id should
not contain "." (dot)
in the name.
componen pickerSearch Any valid No componentId
tId component id determines the
specified in attributes that
pickerAttri- should appear in
butes.xml search criteria panel
of the given picker.
pickerCallback Generated at Name of the No Name of the
the runtime if callback customized callback
user has not function function that a user
specified this would have to
parameter implement. It’s
recommended that
you should specify
pickerCallback

Incorporating Pickers in JSP Clients 1037


Parameter Default Possible Req? Description
Value Values
function in custom.
js file
defaultVal “” (blank) Any values No Default value for
ue textbox rendered by
the picker.
defaultHid “” (blank) Any values No Default value of the
denValue hidden textbox
associated with the
picker.
Label Context Picker Any value No Label of the picker.
displayAt Name Any attribute No Name of the
tribute attribute that should
be displayed in the
picker textbox after
selecting result from
the organization
picker
container “” (blank) Any container No Value of the
Ref containerRef in
which a user wants
to restrict the search.
baseWhere “” (blank) Any valid I*E No Additional where
Clause where clause clause if you want to
query filter search results
on some specific
criteria regardless of
user input. This
where clause will
just get “ANDed”
with the internal
where clause.
pickerTi Contexts Any value No The title of the
tle picker.
pickedData <WebApp>/ URL location No URL of the data
Fetcher netmar of the fetcher fetcher file that will
kets/jsp/ file be used by the
search/ AJAX call to
pickedDa process the selected
ta.jsp results.

1038 Customization Guide


Parameter Default Possible Req? Description
Value Values
Editable True true/false No This attribute
defines whether you
want to have Find
icon along with the
textbox or not.
readOnly False true/false No This attribute
PickerText defines whether the
Box picker text box
should be editable or
not.
Inline False true/false No You should specify
this parameter with
value as true when
you want to launch
picker from a table
level action or
inline.
pickedAt Name Any comma No This parameter
tributes separated list contains a comma
of valid separated list of the
attributes attributes that a user
wants a picker to
fetch. This is
applicable only if
inline is “true”.
pickerType search search/picker No This parameter
defines the picker
type i.e. “search”
picker or “picker”
picker. In search
picker, you will see
search criteria in the
picker and then you
have to hit the
search button to see
the results however
in case of “picker”
picker you will
directly see the
results table without

Incorporating Pickers in JSP Clients 1039


Parameter Default Possible Req? Description
Value Values
any search criteria.
pickerText 25 Any numeric No This parameter
BoxLength value defines the length of
the picker text box.
searchRe “”(blank) Any valid No This parameter
sultsVie view id allows user to define
wId custom view id for
the picker search
results table.
extraSug emaild Any field user False This parameter is
gestAttri wants to used to specify the
butes search on extra attributes that
are to be used for
auto-suggest
showSugges- false True/false False If this property is
tion made true multi
select recently used
context picker will
be shown. In this
case you need to
modify your
callback function
and onchange
function. Default
value is false.
Implemented for
search page only.
This property is
used to enable auto-
suggest to the
picker.

1040 Customization Guide


Parameter Default Possible Req? Description
Value Values
suggesMin 1 Integer values False This parameter is
Chars used to specify the
min. character on
which auto-suggest
initiates if enabled
suggestSer Picker specific userPicker, False Key for selecting
viceKey partPicker etc. suggestable class (e.
g.
ContextServi
cePickerSugge
stable) which in
turn call query
service.Key needs to
be present in
search-
service.pro
perties.xconf
file.

Configuring Organization Picker with multi select option in


results table
<wctags:organizationPicker id="orgPickerId" multiSelect="true" />

Configuring baseWhereClause in Organization picker


<wctags:organizationPicker id="orgPickerId"
baseWhereClause="(name=’myOrg*’)" />

Configuring pickerCallback function in Organization picker


<wctags:organizationPicker id="orgPickerId"
pickerCallback="myPickerCallback" />
myPickerCallback function can be like:
function myPickerCallback(objects, pickerID)
{
var updateHiddenField = document.getElementById(pickerID);
var updateDisplayField = document.getElementById(pickerID +
"$label$");
var myJSONObjects = objects.pickedObject;
for(var i=0; i< myJSONObjects.length;i++) {
var oid = myJSONObjects[i].oid;
// Here “name” is the displayAttribute requested
var displayAttr = eval("myJSONObjects[i].name");
updateHiddenField.value=oid;

Incorporating Pickers in JSP Clients 1041


updateDisplayField.value=displayAttr;
}
}

1042 Customization Guide


Configuring a Type Picker
You want to create a Type Picker either for the display or for the assignment of
type-able items.

Background
Type Picker Common Component is to be used either for display or for
assignment of type-able items. For example in a search application to select the
type of objects that you are interested to do a search on or in a create application
to create an item of a specific type. It can be used to display the type in case of
edit or view applications. The component can be used in the context/mode of
CREATE, EDIT, SEARCH or VIEW.

Scope/Applicability/Assumptions
• If the Type Picker behavior is to be driven by site/organization preferences viz.
display (list or tree), default type, filter criteria etc, its assumed that you will
extract the relevant information and pass them to the component.
• The component will apply access control policies except for SEARCH mode.
• It is assumed that your <MyPage>.jsp file in which you are implementing
this common component includes “/netmarkets/jsp/begin.jspf” or
“/netmarkets/jsp/beginPopuf.jspf” file and “/netmarkets/
jsp/end.jspf” files.

Intended Outcome
Depending upon the format, you will get either a dropdown or table or a tree:
• Type Picker in DropDown Format

• Type Picker in Table Format

Incorporating Pickers in JSP Clients 1043


• Type Picker in Tree Format

1044 Customization Guide


Solution
Use Type Picker Common Component to display or for the assignment of type
-able items.

Prerequisite knowledge
To understand this documentation, you need to have an understanding of the
following:
• Basic development involving JSP, JavaScript and Custom taglibs
• The management of resource bundle files customizations
• Windchill xconfmanager concepts
• Windchill Type Identifiers

Incorporating Pickers in JSP Clients 1045


Solution Elements
Element Type Description
picker.tld tld Tag Library Descriptor (TLD) file,
which contains Type Picker Tag
definition
Run time Location:
<Windchill>\codebase\
WEB-INF\tlds\
typePickerResource.java Java You should use this file to localize
the contents of the Type Picker pop
up.
<your_page>.jsp jsp Your TypePicker Common
Component implementation
containing jsp file.
wt.properties properties You can define
‘wt.typepickerexclude’
property here
Run time Location:
<Windchill>\codebase\
wt.properties

The solution is also addressed to these variations:


1. You want to specify that a container will display a particular subset of all types
in a Type hierarchy.
2. You want to specify filtering criteria on the types shown, including criteria on
custom subclasses.
3. You want to specify the root/base types (OOTB or custom) to be used.
4. You want to include a type picker that will be launched as a dropdown or
table/tree popup menu.
5. You want to specify whether or not non-instantiable types are to be presented
for picking

Procedure – Configuring Type Picker Common Component


1. Include necessary artifacts.
You should include the necessary artifacts in your configuring jsp file e.g.
“/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/
beginPopuf.jspf” file and “/netmarkets/jsp/end.jspf” file.

1046 Customization Guide


You also need to declare picker taglib directive. (uri=”http://
www.ptc.com/windchill/taglib/picker”)
2. Configure Type Picker.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%>
<%@ include file="/netmarkets/jsp/util/begin.jspf"%>
----
----
<!-- TYPE PICKER CONFIGURE START -->
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="seedType" value="wt.epm.EPMDocument" />
<p:pickerParam name="type" value="BOTH" />
<pr:pickerParam name="displayHierarchy" value="false" />
<p:pickerParam name="showRoot" value="true" />
</p:typePicker>
<!-- TYPE PICKER CONFIGURE END -->
----
----
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Customization Points
typePicker tag attributes
Parameter Default Possible Req? Description
Value values
id - Any value Yes Used to distinguish
between the multiple
Type-Picker usages in a
page. The id value
should not contain "."
(dot).
label - Any value No Used as the Picker label
mode SEARCH - No Defines in which mode
the Type Picker is going
to be used and it should
be one of the value
defined in
com.ptc.cor
e.ui.resources.
ComponentMode
field - - No Target Element is the
one in which the
selected elements
attributes will be

Incorporating Pickers in JSP Clients 1047


Parameter Default Possible Req? Description
Value values
populated. It should be a
subclass of
com.ptc.core.com
ponents.renderin
g.AbstractGuiCom
ponent Currently
support TextBox and
ComboBox
renderContext - - No Object should be an
instance of
com.ptc.core.com
ponents.render
ing.RenderingCon
text. If not supplied
the component will
create one for the user.
objectType typepicker - No This is the object type in
which the picker action
is specified in
*actions.xml .
<Windchill>\
codebase\config\
actions\
EnterpriseUI-
actions.xml
actionName typePicker - No This is the action name
that is specified in
*actions.xml for
the picker action

1048 Customization Guide


pickerParam tag attributes
Parameter Default Possible Req? Description
Value values
adminDomain - No String representation of
Ref the administrative
domain reference (wt.
admin.Admin
DomainRef). Used to
check access control
rights.
containerRef - No String representation of
the container reference
(wt.inf.contai
ner.WTContainer
Ref) and is used to
populate types specified
for this container.
If adminDomainRef
is provided,
containerRef is
calculated from that
even if user has supplied
it.
If adminDomainRef
is NOT provided,
component uses the
default AdminDomain
for the supplied
containerRef or if
containerRef is not
provided, component
uses default
WTContainer
(Exchange container).
lifeCycleState - No String representation of
State (wt.lifecycle.State)
and is used while
checking access control
rights.
seedType - - No Accepts valid logical or
external representation
of Windchill Type

Incorporating Pickers in JSP Clients 1049


Parameter Default Possible Req? Description
Value values
Identifiers. Multiple
values supported and it’s
required for mode =
CREATE/EDIT/VIEW
filterType - - No Accepts valid logical or
external representation
of Windchill Type
Identifiers. Multiple
values supported.
The type and its
descendants are filtered
out from the picker
element
defaultType - - No Accepts valid logical or
external representation
of Windchill Type
Identifiers. For single
select, it should be only
one value. Multiple
values are supported and
it’s required for mode =
EDIT/VIEW. It can
support blank, "Select a
Type" etc values also.
appOption - - No Localized Display name
and value separated by a
"$" delimiter and
multiple values are
supported.
format dropdown - No It should be one of the
enum constant value
defined in
com.ptc.windchil
l.enterprise.
picker.type.ser
ver.TypePicker
Format. The possible
values are dropdown,
table, tree
select single - No Possible values are

1050 Customization Guide


Parameter Default Possible Req? Description
Value values
single and multi.
type BOTH - No It should be one of the
enum constant value
defined in
com.ptc.windchil
l.enterprise.
picker.type.ser
ver.TypePicker
Types. Possible values
are ROOT_TYPES
(only seedTypes will be
displayed), SOFT_
TYPES (only SOFT
Types will be
displayed), BOTH
(MODELED & SOFT
Types will be
displayed)
display false false/true No Accepts String
Hierarchy representation of
Boolean value. This is
valid only for dropdown
format for which it
presents picker elements
in hierarchy.
showInstan false false/true No Accepts String
tiable representation of
Boolean value. If true -
only instantiables will
be displayed and for
false both instantiables
and non-instantiables
will be displayed
showRoot true false/true No Accepts String
representation of
Boolean value. If true
shows the seedTypes as
I level elements.
componentId Foundation. - No componentId is defined
allSearch

Incorporating Pickers in JSP Clients 1051


Parameter Default Possible Req? Description
Value values
as 'APP_
ID+.+COMPONENT_
NAME'.
Valid APP_IDs are
ProjectLink,
Foundation, or
PDMLink. This is used
for mode = "SEARCH"
to find the I level types
from <Windchill>\
codebase\com\
ptc\windchill\
enterprise\
search\server\
SearchableType
s.properties.
Passing null will default
to the Default
pickerCall- typePicker - No A javaScript function
Back Populate that will be invoked to
Target populate the selected
Element element attributes in the
target element. This is
not applicable for
dropdown.
pickedData netmarkets/ - No A jsp file which is
Fetcher jsp/ invoked in the AJAX
typepicker/ call to fetch attributes of
type the picked elements.
Picker_data The file should be
Fetcher.jsp located in the
<Windchill>/
codebase and relative
path is the value to be
provided. It’s not
applicable for
dropdown.
filterByInter- - Valid No String representation of
face Windchill valid windchill
Interface Interface. Its Single
valued parameter. For

1052 Customization Guide


Parameter Default Possible Req? Description
Value values
example,
filterByInterface = “wt.
index.Indexable”
If filterByInterface
param configured then
only subtypes of
seedType that
implement the interface
should be displayed in
the type hierarchy. Here,
Type picker will
show only subtypes of
seedType which
implements Indexable
interface.
Seed type is always
selectable even if non-
instantiable when this
parameter is configured.
When fliterByInterface
configured along with
ShowInstantiable=true
then only instantiable
type which implements
interface will be
available in type picker.

Incorporating Pickers in JSP Clients 1053


Parameter Default Possible Req? Description
Value values
additional- - Valid No String representation of
Types Windchill valid Windchill Abstract
Abstract class Classes. Its Multi valued
parameter. For example,
additionalTypes= “wt.
meeting.Meeting, wt.
org.WTPrincipal”
All abstract classes
specified by this
parameter will be
present in type picker as
long as they are
subclasses of the
seedType and
implement the interface
specified by the
filterByInterface
parameter.
This parameter is
dependent on
filterByParameter. Type
picker framework
respects this parameter
only when
filterByInterface is
configured.
showInternal- false false/true No Accepts String
NameAsTool- representation of
tip Boolean value.
If true then shows
tooltip as internal name
of type, otherwise shows
display name of type

Configuring Type Picker that will be launched as a dropdown or table/


tree popup menu
• Type Picker in “Drop Down” forma
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="format" value="dropdown" />

1054 Customization Guide


</p:typePicker>
• Type Picker in “table” format
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="format" value="table" />
</pr:typePicker>
• Type Picker in “tree” format
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="format" value="tree" />
</p:typePicker>

Configuring Type Picker with your filter criteria


• Filtering via “filterType” parameter
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="seedType" value="wt.doc.WTDocument" />
<p:pickerParam name="filterType" value="com.ptc.ReferenceDocument" />
</p:typePicker>
• Filtering via properties defined in wt.properties.
The properties are to be defined in <Windchill>/codebase/
wt.properties.xconf and propagated to wt.properties file via
xconfmanager.

Incorporating Pickers in JSP Clients 1055


Property Description Example
wt.typepicker wt.typepicker wt.typepickerex
excludede excludedelimiter cludedelimiter=;
limiter =<delimiter
string>
This defines the
delimiter to be used for
‘wt.typepickerex
clude’ property and
the default value is ‘,’
wt.typepicker wt.typepicker wt.typepickerex
exclude/<mode>/ exclude/<mode>/ clude/CREATE/
<root type> <root type>= wt.doc.WTDocu
<delimited list ment=
of external WCTYPE|wt.doc.WT
string Document|org.r_
representation of and_d.Agenda
type identifier> wt.typepickerex
• ‘mode’ should be clude/
one of the value wt.doc.WTDocu
defined in ment=
com.ptc.cor WCTYPE|wt.doc.WT
e.ui.resour Document|org.r_
ces.Component and_d. Meeting
Mode
○ If no ‘mode’
identifier is
specified, then it’s
assumed that the
property is
applicable to all
mode.
○ Multiple values are
to be separated by
wt.typepicker
excludede
limiter property
○ Excludes the listed
types and all their
modeled and soft
subtypes from the

1056 Customization Guide


Property Description Example
Type Picker if the
root type matches
the provided
seedType.
wt.typepicker wt.typepickerex wt.typepickerex
exclude/<mode>/ clude/<mode>/ clude/CREATE/
<container type> <container type>= wt.pdmlink.PDM
<delimited list LinkProduct
of external =WCTYPE|wt.
string doc.WTDocumen
representation of t|org.r_and_
type identifier> d.Agenda
• ‘mode’ should be wt.typepickerex
one of the value clude/
defined in wt.pdmlink.PDM
com.ptc.cor LinkProduct
e.ui.resour =WCTYPE|wt.
ces.Component doc.WTDocumen
Mode t|org.r_and_
d.General
○ If no ‘mode’
identifier is
specified, then it’s
assumed that the
property is
applicable to all
mode.
○ Multiple values are
to be separated by
wt.typepicker
excludedelimit
er property
○ Excludes the listed
types and all their
modeled and soft
subtypes from the
Type Picker if the
container type
matches the
provided
containerRef.

Incorporating Pickers in JSP Clients 1057


The exclusion types extracted from the properties would be aggregated. The
result of above illustrated examples would mean that ‘Agenda’, ‘Plan’ and
‘General’ and their sub types would be filtered out when the rootType is
WTDocument and container being PDMLinkProduct and the operation is
CREATE. For all other operations, only ‘Meeting’ and ‘General’ and their sub
types would be filtered out.

Configuring Type Picker with your root/base types


< p:typePicker id="typePickerTest" label="Type : " mode="CREATE" >
<p:pickerParam name="seedType" value="wt.part.WTPart" />
</picker:typePicker>

Configuring Type Picker with or without non-instantiable


< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="seedType" value="wt.part.WTPart" />
<p:pickerParam name="showInstantiable" value="true" />
</p:typePicker>

Configuring Type Picker with your picker call back function


< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" >
<p:pickerParam name="seedType" value="wt.part.WTPart" />
<p:pickerParam name="pickerCallBack" value="myCallBack" />
</p:typePicker>
Points to be taken care while authoring your pickerCallBack
• This javaScript function will be invoked to populate the selected element
attributes in the target element.
• User supplied function should be available in the page where Type Picker is
inserted.
• pickerCallBack function signature is "call_back_function(JSON_Object,
Picker_Id, Field_Id)"
e.g
function mycallBack(JSONObjects, pickerId, targetId) {
var elements = JSONObjects.pickedObjects;
var targetElement = document.getElementById(targetId);

//update Target Element


if ((targetElement.type == "text") || (targetElement.type ==
"hidden")) {
--------
}else {
--------
}
//update hidden field
var valueElement = document.getElementById(pickerId);
-----

1058 Customization Guide


return true;
}

Configuring Type Picker with your picker data fetcher


< picker:typePicker id="typePickerTest" label="Type : "
mode="SEARCH" >
<picker:pickerParam name="seedType"
value="wt.part.WTPart" />
<picker:pickerParam name="pickedDataFetcher"

value="myfolder/myDataFetcher.jsp" />
</picker:typePicker>
Points to be taken care while authoring your pickedDataFetcher
• The response of the pickedDataFetcher should contain <DIV> tag with id
same as the Type-Picker id. The content inside the <DIV> tag is extracted and
evaluated to create JSON objects. An example of a typical response will be
<DIV id=”Type_Picker_Id” >
{"pickedObjects":
[
{"type" : "Part" , "theType" : "wt.part.WTPart "},
{"type" : "Document" , "theType" : "wt.doc.WTDocument”}
]
}
</DIV>

Accessing the Selected/Populated Information from Type Picker


• If you supply GUIComponent (via field) and RenderingContext (via
renderContext) for Target Element and
○ If GUIComponent Id is not set; Type Picker CC will set it to Type Picker
Id
○ If RenderingContext’s ContextString not set, Type Picker won’t set it.
• You supply GUIComponent and NO RenderingContext for Target Element
○ Type-Picker uses a default RenderingContext, who’s ContextString won’t
be set.
• You supply NO GUIComponent and NO RenderingContext for Target
Element
○ Type-Picker creates appropriate GUIComponent and will set Type Picker’s
Id to it.
DropDown format

Incorporating Pickers in JSP Clients 1059


• If you want to access the selected value in the page (after submitting the page),
the
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString
()+"___"
+ GUIComponent.getId() + GuiComponentUtil.COMBO_BOX;

• If you want to access the selected value in the Command, you can get a hold
of it through the NmCommandBean
HashMap comboBox_hmap = commandBean.getChangedComboBox();
Object comboBox = comboBox_hmap.get(GUIComponent_Id);

Table/Tree Popup Format


• If you want to access the target element (TextBox or ComboBox) in the page,
the
○ TEXTBOX
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString
()+"___"
+ GUIComponent.getId() + GuiComponentUtil.TEXT_BOX;
○ COMBOBOX
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString
()+"___"
+ GUIComponent.getId() + GuiComponentUtil.COMBO_BOX;
• The selected values are stored in an “input” hidden element in the page, with
the selections separated by a delimiter (“,”)
• If you want to access the selected value in the Command, you can get a hold
of it through the NmCommandBean.
String selected_value = cb.getTextParameter(Type_Picker_Id);

1060 Customization Guide


Configuring a User Picker
Objective
You want to add a user picker to a custom UI and need to configure the picker to:
• • search only for objects of certain type(s)
• • search only for objects in certain container(s)
• • display certain search critieria input fields
• • display certain attributes of the objects in the search results table

Background
The user picker is used when you have a requirement to select specific user(s)
depending upon certain criteria and use them in your application. Typical use case
could be that you may want to find parts which are created by certain user. In this
case you can have a user picker and then through this you can select the user and
pass it on to the search criteria to perform search for parts.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are putting tag
includes “/netmarkets/jsp/begin.jspf” or “/netmarkets/jsp/
beginPopuf.jspf” file and “/netmarkets/jsp/end.jspf” files.

Intended Outcome
You should see a text box and Find icon along with the specified label after using
the tag for user picker. After clicking the Find icon, a user picker will be launched.

Incorporating Pickers in JSP Clients 1061


On clicking the Find… button you should see a user picker.

Solution
Use the User Picker Common Component in your JSP file to include User Picker
in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Basic development involving JSP, JavaScript, Custom taglibs
• The management of resource file customizations.
• Windchill xconfmanager concepts

1062 Customization Guide


Solution Elements
Element Type Description
PickerAttributes.xml XML pickerAttributes.xml XML file You
should use this file to customize the
search criteria attributes for an object
type for your picker.
Runtime location:
<Windchill>\codebase\
pickerAttributes.xml
searchClientResource Resource bundle You should use this file to localize the
.java file contents of the pickers.
userPicker.tag Custom JSP tag This file is contains the information
about the supported parameters for
this tag.
Runtime location:
<Windchill>\codebase\
WEBINF\tags\
userPicker.tag
SearchableTypes xconf properties You should specify component Id and
.properties.Xconf file corresponding object types in this file
and then run xconfmanager.
Runtime location:
<Windchill>\codebase\
com\ptc\windchill\
enterprise\search\
server\Searchable
Types.properties.xconf
custom.js JavaScript file You should specify custom
pickerCallback function for picker in
this file.
Runtime location:
<Windchill>\codebase\
netmarkets\jsp\search
\custom.js

Procedure – Including a User Picker in a jsp page


Configure basic user picker:
<tr>
<wctags:userPicker id="userPickerId" />
</tr>

Incorporating Pickers in JSP Clients 1063


Customization Points
Customization Points are listed in following tables:
Parameter Default Possible Req? Description
Value values

Id Anything that No An ID is associated with


is unique in a every picker in the calling
page application. This ID has to
be unique for all pickers,
whether of different types
or same type, in one page.
The id should not contain
"." (dot) in the name.
componentId picker Any valid No componentId determines the
Search component id attributes that should appear
specified in in search criteria panel of
picker the given picker.
Attributes.xml
pickerCall Generated Name of the No Name of the customized
back at runtime callback callback function that a user
if user has function would have to implement.
not It’s recommended that you
specified specify pickerCallback
this function in custom.js file
parameter
defaultValue (blank) Any values No Default value for textbox
rendered by the picker.
defaultHidd (blank) Any values No Default value of the hidden
enValue textbox associated with the
picker.
Editable True true/false No This attribute defines
whether you want to have
Find icon along with the
textbox or not.
readOnly False true/false No This attribute defines
PickerText whether the picker text box
Box should be editable or not.
Inline False true/false No You should specify this
parameter with value as true
when you want to launch
picker from a table level

1064 Customization Guide


Parameter Default Possible Req? Description
Value values

action or inline.
picked Name Any comma No This parameter contains a
Attributes separated list comma separated list of the
of valid attributes that a user wants a
attributes picker to fetch. This is
applicable only if inline is
“true”.
Label Context Any value No Label of the picker.
Picker
display Name Any attribute No Name of the attribute that
Attribute should be the displayed in
the picker textbox after
selecting result from the
user picker
containerRef “” (blank) Any container No Value of the containerRef in
which a user wants to
restrict the search.
baseWhere “” (blank) Any valid I*E No Additional where clause if
Clause where clause you want to filter search
query results on some specific
criteria regardless of user
input. This where clause
will just get “ANDed” with
the internal where clause.
pickerTitle Contexts Any value No Title of the window in
which the picker is
launched.
pickedData <We- URL location No URL of the data fetcher file
Fetcher bApp>/ of the fetcher that will be used by the
netmarkets/ file AJAX call to process the
jsp/search/ selected results.
pickedData
.jsp
pickerType search search/picker No This parameter defines the
picker type i.e. “search”
picker or “picker” picker. In
search picker, you will see
search criteria in the picker
and then you have to hit the

Incorporating Pickers in JSP Clients 1065


Parameter Default Possible Req? Description
Value values

search button to see the


results however in case of
“picker” picker you will
directly see the results table
without any searchcriteria.
pickerText 25 Any numeric No This parameter defines the
BoxLength value length of the picker text
box.
searchRe- “”(blank) Any valid No This parameter allows user
sults view id to define custom view id for
ViewId the picker search results
table.
showUser ActiveOnly ActiveOnly No This parameter is used to
Type DeletedOnly restrict the user search to
active/deleted/active and
ActiveAndDel deleted users only.
Etc
showRoles False true/false No This parameter is used to
enable role drop down in
user picker. If you want to
use this parameter then you
should specify the
containerRef parameter
from where the roles have
to be fetched.
extraSuggest emaild Any field user No This parameter is used to
Attributes wants to specify the extra attributes
search on that are to be used for auto-
suggest.
showS False True/false No This parameter is used to
uggestion enable auto suggest for the
picker.

1066 Customization Guide


Parameter Default Possible Req? Description
Value values

suggestMin 1 Integer values No This parameter is used to


Chars specify the min. character
on which auto-suggest
initiates if enabled
suggest Picker userPicker, No Key for selecting
ServiceKey specific partPicker etc. suggestable class (e.g.
ContextService
PickerSuggestable) which
in turn call query service.
Key needs to be present in
search-service.properties
.xconf file.

Configuring User Picker with multi select option in results


table
<wctags:userPicker id="userPickerId" multiSelect="true" />

Configuring baseWhereClause in User picker


<wctags:userPicker id="userPickerId"
baseWhereClause="(name=’demo*’)" />

Configuring pickerCallback function in User picker


<wctags:userPicker id="userPickerId"
pickerCallback="myPickerCallback" />
An exsmple of the myPickerCallback function:
function myPickerCallback(objects, pickerID)
{
var updateHiddenField = document.getElementById(pickerID);
var updateDisplayField = document.getElementById(pickerID + "$label$");
var myJSONObjects = objects.pickedObject;
for(var i=0; i< myJSONObjects.length;i++) {
var oid = myJSONObjects[i].oid;
// Here “fullName” is the displayAttribute requested
var displayAttr = eval("myJSONObjects[i].fullName");
updateHiddenField.value=oid;
updateDisplayField.value=displayAttr;
}
}

Incorporating Pickers in JSP Clients 1067


Configuring a Participant Picker in JCA
Objective
Participant Picker gives you the ability to search for participants using a variety of
search criteria and gives the ability to pick selective participants.

Background
The current way of picking of participants is limited to Users, Groups, and is not
consistent across Windchill. The new Participant Picker Common Component
gives consistent behavior across Windchill. Participant Picker gives you the ability
to search Participants of type User, Group, and Organization. It provides a wide
variety of search scope criteria using which you can narrow down the search.

Note
This topic describes how to customize a JCA-based participant picker for use
in JCA tables. In Windchill 11.0, a new participant picker based on AngularJS
has been introduced and PTC recommends using it for standalone, single-page
applications based on AngularJS, HTML, or Javascript. For more information,
see Configuring a Participant Picker in AngularJS on page 1083.

Scope/Applicability/Assumptions
• Using in Windchill Client Architecture table: You should define a Windchill
Client Architecture action, and point the action to a JSP page that has
participant picker tag. Provide the required attributes “action Class” and
“action Method “to the participant picker tag. Add the Windchill Client
Architecture action you created to the desired Windchill Client Architecture
table. When you click the action, it will launch the Participant Picker Wizard.
Select desired participant and click OK. The Picker will invoke the action
Method of the action Class that you have provided. In that method, you will
consume or process the selected participant in a desired way.
• Using Participant Picker in combination with Property Picker: The assumption
is that you know how to use the Property Picker. The action attribute of your
Property Picker should point to the JSP page that has participant picker tag.
The required attribute “action Class” should “”(empty) and “action Method “
should be “JavaScript:${pickerCallback}()”. ${pickerCallback} is the
pickerCallback JavaScript function that you supplied to Property Picker. After
you select the desired participants and click OK in the wizard, your

1068 Customization Guide


pickerCallback JavaScript function will be invoked with JSON object
containing the picked participants.

Intended Outcome
The selected participants are either populated in Windchill Client Architecture
table, or a populated in text box of Property Picker.

Incorporating Pickers in JSP Clients 1069


Solution
Use the Participant Picker to search for participants, and add the selected
participants to a Windchill Client Architecture table or text box in a Property
Picker.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• How to add Windchill Client Architecture actions to a Windchill Client
Architecture table, how to dynamically update the table with selected
participants.
• How to configure a Property Picker, how to author JavaScript picker Callback
functions.

Solution Elements
Element Type Description
actionClass Tag Attribute Name of the action class that
needs to be invoked for processing
the selected Participants.
actionMethod Tag Attribute Name of the action method that
needs to be invoked for processing
the selected Participants.
select Tag Attribute This will determine whether the
picker allows multiple selections
("multi"), or just a single select
("single").
participantType Tag Attribute Use this to set the default to any
Participant type. The class com.
ptc.core.components.beans.
PrincipalBean has four string
constants defined, which one can
be pass to this attribute. The
constants are ALL_
PARTICIPANT, USER, GROUP
and ORG.
singleParticipantType Tag Attribute Use this to set the default
Participant type specified in the
tag attribute participantType as the
only supported type. This takes
value true/false. When set to true,
it will restrict to single type

1070 Customization Guide


Element Type Description
specified as in the attribute
participantType. When set to false
or left unspecified, the picker
supports participant types ALL_
PARTICIPANT, USER, GROUP,
ORG.
associationMap Tag Attribute This map contains key, value pairs
of association to be displayed in
association drop down list. Keys
are Java String literals that are
returned to the user upon selection
of any association. Value is a
localized string that is displayed in
association drop down list.
defaultAssociation Tag Attribute The association you desire to be
pre selected in the dropdown
should be passed in this attribute.
associationLabel Tag Attribute The localized string for Display
Label of the association.
emailAllowed Tag Attribute Set this to "true" to get email
Textbox rendered. You can type
any comma or space separated
emails that you desire to invite.
contextMap Tag Attribute The List of Context in which you
wants to perform Search In. This
map contains key, value pairs of
contexts to be displayed in Search
In drop down list. Keys are Java
String literals that represent oid of
the Windchill object. Value is a
localized string that is displayed in
Search In drop down list.
filterEmail Tag Attribute If this attribute is set to “true”
when searching for users, only
users with email addresses are
returned. Default is “false”.
recentAllowed Tag Attribute Set this to “false” to prevent the
recent participants TextBox from
being rendered. Default is “true”.
applicationContext Tag Attribute If this attribute is set to “true”

Incorporating Pickers in JSP Clients 1071


Element Type Description
Search when searching for users, only
users within a specified
application context will be
returned. Default is “false”.
defaultContext Tag Attribute The context you desire to be pre
selected in the dropdown should
be passed in this attribute.
serviceMap Tag Attribute LDAP server's list is passed, to
perform search. Default this
attribute is not supplied. This map
contains key, value pairs of
contexts to be displayed in Service
drop down list. Keys are Java
String literals that represent the
LDAP Server. Value is a localized
string that is displayed in Service
drop down list.
includeInternal Tag Attribute Set this to “true” to search for
internal groups. Default is “false”.
disableRestricted Tag Attribute Set this to “true” to bypass the
SearchScope restricted search scope set on the
organization. Default is “false”.
enforceRestricted Tag Attribute Set this to “true” to force the
SearchScope restricted search scope, despite
how it is set on the organization.
Default is “false”.
showRoles Tag Attribute Set this to “true” to add a filter on
search to restrict search scope to
the selected role. This option will
only display when the type option
is User.
When true, this will provide a
dropdown list of available roles in
the search criteria. The roles will
come from the passed in context.
Default is “false”.
resourcePool Tag Attribute This will provide the pool of
principals to search.

1072 Customization Guide


Element Type Description

All access control rules will still


apply.
searchProfileGroups Tag Attribute Set this to “true” to search only
profile groups in the system.
Default is “false”.
searchDisconnected Tag Attribute Set this to “PrincipalBean.LDAP”
Principals to search only disconnected
principals in LDAP.
Set this to “PrincipalBean.DB” to
search only disconnected
principals in the DB.
Default is “false”.
title Tag Attribute This will provide the title for the
participant picker window.
Default is “Find Participant”.
showSearchIn Tag Attribute This will determine whether or not
the "Search In:" field shows up in
the participant picker. Default is
"true" to preserve existing
functionality.
helpSelectorKey Tag Attribute This will set the help link for the
picker, if nothing is provided it
will default to the service.
properties value for
ParticipantPickerHelp
enforceModify Tag Attribute This will filter the search results to
Permission only return objects that the current
user has MODIFY permission on.

Incorporating Pickers in JSP Clients 1073


Procedure – Making Association available in Participant
Picker
You want to include association in the Participant Picker. You will need to supply
the tag attributes associationMap, defaultAssociation and associationLabel to the
Participant Picker tag.
The second example in Sample Code on page 1075 below describes code sample
of how association can be added to the Participant Picker.

Procedure – Participant Picker with Search in Context


You want to narrow down the search to different contexts. You will need to supply
the tag attributes contextMap and defaultContext to the Participant Picker tag. The
contexts can be Organization, Site, Product, Project, and Library.

Procedure – Search for Participants in different LDAP


You want to search for Participants in a different LDAP. You will need to supply
the tag attribute serviceMap.
Configure your Windchill to support multiple LDAP servers. Each LDAP server
will be identified by a name. The name of LDAP server has to be supplied as key,
and a localized display label as value. When you supply the serviceMap, you will
see a dropdown in the Participant Picker with label “Service”. The selected key is
sent as service parameter to the Info*Engine tasks by the Participant Picker.

Procedure – Making Email invitation available in Participant


Picker
You want to add email invitation text box to the Participant Picker. You will need
to set the tag attribute emailAllowed="true".
The third example in the Sample Code on page 1075 section below describes code
sample of how get email invitation textbox in the Participant Picker.

Procedure – Single select Participant Picker


You want to select only participant at a time. You will need to set the tag attribute
select=”single”. This will render the Participant selection list as text box that can
hold one value at a time.

Procedure – Restrict to single Participant type search


You want to restrict the type of Participants to be searched to one. You will need
to set the tag attribute singleParticipantType="true".

1074 Customization Guide


Sample Code

Sample JSP that contains a Participant Picker tag


After making entry for action to launch the Participant Picker, write a JSP with the
same name as in action tag (e.g. participantPickerSample.jsp).
<%@ page import="com.ptc.windchill.enterprise.picker.principal.PrincipalBean"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

<jca:participantPicker
actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands"
actionMethod="addPrincipal"
participantType="<%= PrincipalBean.GROUP %>">
>
</jca:participantPicker>
-

This will render a basic participant picker as show below.

Incorporating Pickers in JSP Clients 1075


You perform a search based on search criteria. Move desired participants to
Participant List and click OK. The component invokes actionClass and
actionMethod provided as attributes to the participant picker tag. You need to
write actionMethod in the actionClass. Example code is given below.
public class CustomPrincipalCommands {
public static FormResult addPrincipal(NmCommandBean cb) throws WTException {
FormResult result = new FormResult(FormProcessingStatus.SUCCESS);
result.setNextAction(FormResultAction.REFRESH_OPENER);
String principals = cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS);

if (principals == null) {
result.setStatus(FormProcessingStatus.FAILURE);
return result;
}

ArrayList<String> selectedPrincipals = new ArrayList<String>();


int start = 0;
int pos = principals.indexOf("#", start);
while (pos != -1) {
String principal = principals.substring(start, pos);
selectedPrincipals.add(principal);
start = pos + 1;
pos = principals.indexOf("#", start);
}
// Now process selectedPrincipals

return result;
}
}

You should write a static method as actionMethod. It will take only one argument
i.e., NmCommandBean. The selected participants are sent to this method as text
parameters. With in the component these values are stored in hidden variable. The
name of the hidden variable is defined as a static String in “com.ptc.windchill.
enterprise.picker.principal.PrincipalBean”. To extract selected participants use
PrincipalBean.PARAM_SELECTED_PRINCIPALS. This will return “#”
separated DN (Distinguished Name).

1076 Customization Guide


Adding Association
To add association in the Participant picker, you need to provide three attributes as
highlighted in the following sample. The attribute associationMap takes
LinkedHashMap. You supply the key, value pairs to this map. Key’s are the java
String literals. When user selects an association, this key String literal is passed
back to the actionMethod as text Parameter. Values are localized string displayed
in the dropdown list. Component uses LinkedHashMap to retain the order in
which the key value pairs are added while displaying in the dropdown list.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ page import="java.util.LinkedHashMap"%>
<%@ page import = "com.ptc.windchill.enterprise.picker.principal.
PrincipalBean" %>
<%
LinkedHashMap associationMap = new LinkedHashMap();
associationMap.put("GUEST", "Guest");
associationMap.put("MEMBERS", "Members");
associationMap.put("PROJECT MANAGER", "Project Manager");
%>

<c:set var="associationMap" value="<%= associationMap %>"/>


<c:set var="participantType" value="<%= PrincipalBean.USER %>"/>
<jca:participantPicker
actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands"
actionMethod="addPrincipal"
participantType="${participantType}"
emailAllowed="true"
defaultAssociation="GUEST"
associationMap="${associationMap}"
associationLabel="Add to Role"
>
</jca:participantPicker>

The above code will render association dropdown as shown in the following
figure.

Incorporating Pickers in JSP Clients 1077


In the above example, you are trying to add a role to the participant. You move the
desired participants to Participants List, select a role from the association list and
click OK. The actionMethod code will now look like this.
public class CustomPrincipalCommands {
public static FormResult addPrincipal(NmCommandBean cb) throws
WTException {
FormResult result = new FormResult(FormProcessingStatus.SUCCESS);
result.setNextAction(FormResultAction.REFRESH_OPENER);
String principals = cb.getTextParameter(PrincipalBean.PARAM_SELECTED
_PRINCIPALS);
if (principals == null) {
result.setStatus(FormProcessingStatus.FAILURE);
return result;
}
ArrayList<String> selectedPrincipals = new ArrayList<String>();
int start = 0;
int pos = principals.indexOf("#", start);
while (pos != -1) {
String principal = principals.substring(start, pos);
selectedPrincipals.add(principal);
start = pos + 1;
pos = principals.indexOf("#", start);
}

String role = cb.getTextParameter(PrincipalBean.PARAM_ASSOCIATION);


ArrayList result = NmRoleHelper.service.addUsersToRole(cb, role,
selectedPrincipals);
return result;
}
}

1078 Customization Guide


You can extract the selected association from text parameter as highlighted in the
above code.

Incorporating Pickers in JSP Clients 1079


Adding Email subscription
The tag to get email subscription the code will look like this.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components"
prefix="jca"%>
<%@ page import="java.util.LinkedHashMap"%>
<%@ page import = "com.ptc.windchill.enterprise.picker.principal.
PrincipalBean" %>
<%
LinkedHashMap associationMap = new LinkedHashMap();
associationMap.put("GUEST", "Guest");
associationMap.put("MEMBERS", "Members");
associationMap.put("PROJECT MANAGER", "Project Manager");
%>

<c:set var="associationMap" value="<%= associationMap %>"/>


<c:set var="participantType" value="<%= PrincipalBean.USER %>"/>
<jca:participantPicker
actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands"
actionMethod="addPrincipal"
participantType="${participantType}"
emailAllowed="true"
defaultAssociation="GUEST"
associationMap="${associationMap}"
associationLabel="Add to Role"
>
</jca:participantPicker>

The above code will render the email subscription field as shown in the following
figure.

1080 Customization Guide


Sample JSP to launch the Picker and send back the picker
values to a Textbox.
You can use Property Picker tag to render a Textbox and Find button to launch
Participant Picker. The Find button has to declared in actions.xml as described in
the above sections. The Property Picker by default provides a JavaScript call back
function that will be invoked by the picker to send back the picked values from
any picker. Property Picker also has an ability to define custom JavaScript
function that can be invoked by pickers. For example:
<p:propertyPicker label="${label}" field="${textbox}"
action="participantPickerSample2" type="participantpicker">
<p:populate from="${displayAttribute}" to="${displayFieldId}"/>
<p:populate from="oid" to="${id}" />
<p:pickerParam name="pickerId" value="${id}" />
<p:pickerParam name="objectType" value="wt.org.WTGroup"/>
<p:pickerParam name="componentId" value="${componentId}"/>
<p:pickerParam name="pickedDataFetcher" value="${pickedDataFetcher}" />
<p:pickerParam name="pickerCallback" value="${pickerCallBack}" />
<p:pickerParam name="containerRef" value="${containerRef}"/>
<p:pickerParam name="baseWhereClause" value="${baseWhereClause}" />
<p:pickerParam name="pickerTitle" value="${pickerTitle}"/>
<p:pickerParam name="multiSelect" value="${multiSelect}"/>
</p:propertyPicker>

Coming back to the Participant Picker, one can get the callback JavaScript
function name as request parameter, when Participant Picker is launched from
Property Picker.
<c:set var="pickerCallback" value="<%=request.getParameter("pickerCallback")%>"/>
<jca:participantPicker
actionClass=""
actionMethod="JavaScript:${pickerCallback}()"
participantType="<%= PrincipalBean.GROUP %>"
<jca:participantPicker>

We pass a blank string to the actionClass attribute of Participant Picker. The


JavaScript call back function name that we got from the request parameter is
appended to the string “JavaScript:” and passed as value to actionMethod. This
string “JavaScript:” is used internally in the picker to identify, as PickerCallBack
mechanism is needed. When user selects the desired participants and clicks OK,
the values are sent back to the JavaScript function as JSON object (as defined in
Property Picker).

Examples of Usage in Windchill Code


All locations are within \Windchill\codebase\netmarkets\jsp:

Incorporating Pickers in JSP Clients 1081


• \roleAccess\profile_addMembers.jsp
• \subscription\subscrPrincipalPicker.jsp
• \team\addUsersToRole.jsp
• \object\findParticipant.jsp
• \work\addUsersToRole.jsp (resourcePool)
• \principal\find_disconnected.jsp
(searchDisconnectedPrincipals)
• \group\addProfileToList.jsp (enforceModifyPermission &
searchProfileGroups)
• \user\addToAdmin.jsp (enforceRestrictedSearchScope)
• \agreements\findParticipant.jsp (disableRestrictedSearchScope)

1082 Customization Guide


Configuring a Participant Picker in
AngularJS
Objective
Participant Picker gives you the ability to search for participants using various
search criteria and to pick selected participants. This customization is intended to
add the AngularJS participant picker to an AngularJS page.

Background
This AngularJS–based participant picker common component provides the ability
to select from an expanded list of participants, including users, groups,
organizations, roles, and actors. It provides a wide variety of search scope criteria
with which you can narrow down the search, including the ability to configure
LDAP as a selectable option.

Note
This topic describes how to customize an AngularJS-based participant picker
for use in a standalone, single-page application based on AngularJS, HTML,
or Javascript. The AngularJS-based participant picker was introduced in
Windchill 11.0. PTC recommends using it for standalone, single-page
applications. To customize a participant picker to use in a JCA page, refer to
the JCA-based participant picker topic Configuring a Participant Picker in
JCA on page 1068.

Scope/Applicability/Assumptions
To use an AngularJS participant picker app in a Windchill Client Architecture
table, you should define a Windchill Client Architecture action, and point the
action to a JSP page that has a participant picker tag. Add the Windchill Client
Architecture action you created to the desired Windchill Client Architecture table.
When you click the action, it launches the Participant Picker Wizard. Select
desired participant and click OK. The picker delivers the selected participant to
the application it is supporting.

Intended Outcome
The selected participants are populated in an element such as a table, text field, or
list.

Incorporating Pickers in JSP Clients 1083


Solution
Use the Participant Picker to search for participants and populate the results into a
table, text field, or list or other element that you choose.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• How to add Windchill Client Architecture actions.
• How to author JavaScript picker Callback functions.
• How to configure a standalone application page in AngularJS 1.2. Refer to the
AngularJS Developer Guide for additional information.

Solution Elements
Element Type Description
auto-suggest Boolean Set this to “true” to have the
picker work as an auto-suggest
search.
auto-suggest- Integer The limit of results to return to
display-limit auto-suggest. This value will
override the typical value returned
from the server but only if it is
less than the max count set on the
property
com.ptc.netmarkets.user
Search.maxCount.
auto-suggest- String The text to display in the auto-
placeholder suggest input field. By default the
value is Enter participant
name.
auto-suggest- String Specifies which attribute to search
user-search- on for user type in auto-suggest. It
field only works when user is the only
defined participant type available
in the picker. The options are
name or userName. The default
is name.
default- Object Specifies which columns should
columns-display be used in the results table and if
they are hidden by default. When
a column is hidden, it is still
available to display through the

1084 Customization Guide


Element Type Description
column toggle support of the
results table. The configuration is
assigned to a specific participant
type.
default- String The directory service from the list
directory- of services that should be the
service default selection. If not provided,
the default will be the value
specified by the property
wt.federation.org.de
faultAdapter. If no value is
specified in the property or it does
not match a directory-service in
the directory-services list, All is
the default selection when there
are multiple directory services.
default- String Specify which of the participant-
participant- types should be the default type
type selected. The default value, if
there are multiple types, is All,
signifying that all the types
provided by participant-types will
be used in the search.
display- Boolean Determines if the directory service
directory- selections should be displayed.
service The default value is “false”.
display-field String Specifies which attribute of the
selected participant type should
display after selection in auto-
suggest. The default attribute is
name.
directory- Array The directory services to be used
services by the search. If none are
specified, the system defaults will
be used.
embedded Boolean Set this to “true” to embed the
picker in the web page instead of
it appearing as a popup window.
help-link String The value for the help topic to use
for this use of the picker. If not

Incorporating Pickers in JSP Clients 1085


Element Type Description
provided, the default will be
LclSrchParticipantPick.
internal-group- Boolean Set to true to include internal
search groups in the search results.
Default is “false”.
ldap-attributes Object A way to specify LDAP attributes
for display in the results table and
if they are hidden by default. The
configuration is assigned to a
specific participant type.
multi-select- Boolean Determines if the participant
mode picker is multi-select or single-
select. Default is “true”.
participant- Directive Directive needed to launch the
picker participant picker. Can be used as
an element or attribute.
participant- Array The types of participants to be
types supported by this launch of the
picker. Available values are:
User, Group, Organization,
Role. Default value is [User,
Group, Organization]
window-title String The value of the title to use for the
Participant Picker pop-up. If none
is provided, Find
Participants is the default
value.

Procedure – Participant Picker with Search in Context


You want to narrow down the search to different contexts. You need to supply the
tag elements contextMap and defaultContext to the Participant Picker
tag. The contexts can be Organization, Site, Product, Project, and Library.

Procedure – Search for Participants in different LDAP


You want to search for Participants in a different LDAP. You need to supply the
tag element directory-services.
Configure your Windchill to support multiple LDAP servers. Each LDAP server
is identified by a name. The name of LDAP server has to be supplied as key, and a
localized display label as value. When you supply the directory-services

1086 Customization Guide


tag element and you also set display-directory-services to true, you
see a drop-down in the Participant Picker with the label “Service”. The selected
key is sent as service parameter to the Info*Engine tasks by the Participant Picker.

Procedure – Single Select Participant Picker


You want to select only one participant at a time. You need to supply this tag
element as shown: multi-select-mode="false". This provides a single-
select radio button list in the results table.

Procedure – Restrict to Single Participant Type Search


You want to restrict the type of Participants to be searched to one. You need to
supply this tag element as shown: singleParticipantType="true".

Procedure – Add a Custom LDAP Attribute


You want to display a custom LDAP attribute in the Search results table. The
following is sample code to add this function.
<form id="participantPickerForm">
<input id="participantPickerFindButton" type="submit" value="Find"
participant-picker window-title="'MySimpleTitle'" help-link="'app'"
picker-data="data1" ldap-attributes="{'users':[
{'name':'Phone Number', 'field':'telephoneNumber', 'hidden':false},
{'name':'Address', 'field':'postalAddress', 'hidden':false},
{'name':'Custom CN', 'field':'cn', 'hidden':true},

]}"

default-columns-display="{'users':[
{'name':'Organization', 'hidden': true},
{'name':'status', 'hidden': false}
]}"/>
</form>

Procedure – Embed an Auto Suggest Field in an AngularJS


Window
You want to embed the participant picker as an auto complete field in an
AngularJS window, instead of launching the Participant Picker app. You need to
supply this tag element as shown: participant-picker auto-suggest=
"true".

Incorporating Pickers in JSP Clients 1087


Sample Code

Sample JSP that contains a Participant Picker tag


After making entry for action to launch the Participant Picker, write a JSP with the
same name as in action tag (for example,
participantPickerSample.jsp).
<base href="<%=pageContext.getServletContext().getContextPath()%>/">
<jca:enableCorePlatform theme="Windchill" version="2.0" applications="participantPicker"
fullPage="true" />
<link rel="stylesheet"
href="/Windchill/apps/participantPicker/resources/css/participantPicker.css">
<form id="participantPickerForm"> <input id="participantPickerInputField"
disabled="true" type="text" /> <input id="participantPickerFindButton"
type="submit" value="Find" participant-picker
participant-picker-callback="pickerCallback" multi-select-mode="false" /> </form>

This renders a basic participant picker as shown here.

Examples of Usage in Windchill Code


• Calendar application: Windchill\codebase\src_web\apps\
calendar\index.jsp
• Sample configurations of this picker are included in the Customization ▶
Component Catalog

1088 Customization Guide


20
Configurable Links
Configurable Link Tables........................................................................................ 1090
Configurable Revision Links ................................................................................... 1100

This section contains information on customizing configurable links.


• Configurable Link Tables on page 1090
• Configurable Revision Links on page 1100

1089
Configurable Link Tables
Special link types, known as configurable links, are provided which can be used to
configure and display additional relationship tables on document and part
information pages. JSP files have been provided to allow sites to implement and
display these configurable link tables. The tables then display in the navigation
link menus on the information page.
For more information, see the “Type and Attribute Management” chapter of the
Windchill Business Administrator's Guide.

Configurable Links Example


An example has been provided out-of-the-box for each of the configurable link
types, including tables for both the parent type and child type information pages.
The following files are delivered for the example:
• <Windchill>/loadfiles/configurableLinks/
ConfigurableLinkExamples.xml

Note
The load file loads both the link types and the association constraints.

• <Windchill>/codebase/config/actions/
ConfigurableLinkExamples-actionmodels.xml
• <Windchill>/codebase/config/actions/
ConfigurableLinkExamples-actions.xml
• <Windchill>/codebase/com/ptc/windchill/enterprise/
object/configurableLinkExamplesResource.class
The file ties the registry of the Customize menu on information pages to the link
type that is implemented for the table, the table header, and the action title.
• <Windchill>/codebase/com/ptc/windchill/enterprise/
ConfigurableLinkExamples.xconf
• <Windchill>/codebase/com/ptc/windchill/enterprise/
ConfigurableLinkExamples-wt.properties.xconf
• <Windchill>/codebase/com/ptc/windchill/enterprise/
ConfigurableLinkExamples-service.properties.xconf

1090 Customization Guide


Caution
It is recommended that you install this example on a test machine.
Uninstalling the example requires manually deleting entries from some files.
See Uninstalling the Configurable Links Example on page 1091 for more
information.

Installing the Configurable Links Example


Use the following procedure to install the configurable links example.
1. Open a windchill shell.
2. Enter the following command:
xconfmanager -i
<Windchill>/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExamples.xconf -p
3. Restart your method server.
4. Load the loadfile:
windchill wt.load.LoadFromFile -d
<Windchill>/loadfiles/configurableLinks/ConfigurableLinkExamples.xml

Note
The actionmodels.xml file overrides the Customize menu on information
pages with the Configurable Link Examples menu on the end. If you have
customized your third-level navigation menus, then these lists must match or
your customizations will be overridden. As an alternative, you could add the
Configurable Link third-level navigation to the actions entry for your info
pages.

Uninstalling the Configurable Links Example


Use the following procedure to uninstall the configurable links example. This
procedure involves manually editing the files that were loaded when the example
was installed.
1. Open the <Windchill>/declarations.xconf file.
2. Remove the entry containing the string:
"ConfigurableLinkExamples.xconf"
3. Save and close the <Windchill>/declarations.xconf file.

Configurable Links 1091


4. Open the <Windchill>/codebase/wt.properties file.
5. Remove the following entries from the file:
• config/actions/ConfigurableLinkExamples-
actions.xml
• config/actions/ConfigurableLinkExamples-
actionmodels.xml
6. Save and close the <Windchill>/codebase/wt.properties file.
7. Restart the method server.
The example has been uninstalled and the third-level navigation Configurable
Link Examples will no longer display.

1092 Customization Guide


Customizing Configurable Link Tables
This section describes each of the components that went in to creating a
Configurable Link Table and displaying it in the OOTB example. Customizing the
configurable link tables are also covered here. Customization is described using
the OOTB example as a reference. An important point to note is that the file
extensions (Ex: .xml, .xconf) and the format within the files must be maintained.
1. Define Configurable Link types and valid relationships.
The first step to customizing configurable link tables is to define the
configurable link subtypes and the relationship constraints for each link type.
This is done in the ConfigurableLinkExamples.xml file. This file
contains two sections:
• Configurable Link Subtypes: The first part defines the Configurable Link
Subtypes. The name and description for each link type must be defined
here. The name field defined on BeginTypeDefView is the Configurable
Link Type and is what will be used to tie-in the registration of the display
location of the table, the table header and the action title associated with
the link type (see Creating labels for the table header and action title on
page 18–71).
The BeginTypeDefView name, the PropertyValue description and
a displayName must be defined with meaningful customized names to
define a new Configurable Link Type.
• Configurable Link Valid Relationships: The second part of this file
contains the relationship constraints for the configurable link subtypes that
have been defined - these are the valid relationships for each defined link
type. Each constraint specifies the Role A and Role B objects to be
associated with a specific link type. "Role A" is the object that constitutes
the left-hand-side of the link, and "Role B" is the object that constitutes the
right-hand-side. The linkType is the BeginTypeDefView that is defined in
the Configurable Link Subtype definition. The roleAType and roleBType
are the objects that take on the respective roles for the specific linkType.
2. Define Action Names for the Relationship Tables.
The next step is to set up a mechanism to display the relationship table
corresponding to a configurable link. This is done by defining actions for each
configurable link table. The file ConfigurableLinkExamples-
actions.xml does this in the example provided.
This file contains the action definitions for all configurable links in the OOTB
example. In the UI, the table names (i.e., actions) are displayed in a sub-menu
in the Customize menu on information pages. Clicking on an action will

Configurable Links 1093


display a table that shows the relationship contained by that configurable link.
The table can display the relationship either from the Role A side or from the
Role B side, depending on how the action is set up.
• To display the relationship from the Role A side, the URL associated with
the action must point to: /netmarkets/jsp/object/
configurableLinkRoleATable.jsp
• To display the relationship from the Role B side, the URL associated with
the action must point to: /netmarkets/jsp/object/
configurableLinkRoleBTable.jsp
To define a new action, follow the syntax within the <action … /action>
fragment. The name field for the action can be set to any meaningful name.
The value used for this field will be used as the key to provide the display
name for this action in the rbinfo file. After setting the name of this action,
follow the rules above to define if this specific action will display the
relationship table from the Role A or the Role B side.
3. Determining the location to display the actions.
The actions created in step 2 above need to be defined in the appropriate area
in order to display them. An action-model is used to provide this definition. In
the OOTB example, the file ConfigurableLinkExamples-
actionmodels.xml handles this aspect.
The relationship tables for configurable links should be defined in the in the
Customize menu on information pages. steps 3a and 3b describe how to create
a model, and then display it. The end result is that the Customize menu on
information pages will have a new menu option. The menu option will be the
actions that display the relationship tables for configurable links.
a. Defining a model
i. First, define the action model by giving it a name - "configLinks"
in the OOTB example. The resourceBundle definition after the name is
the location of the java file using annotations that contains the display
names.
ii. Now that the name has been defined, a brief description can be
provided.
iii. Next, define all the actions (i.e., relationship tables) that are intedned
to be displayed under this action model. In the example, all actions
defined in step 2 are under this model.
iv. Finally, the model as a whole needs to be placed in the in the
Customize menu on information pages of objects that intend to display
it. In this example, it is intended to be displayed from the part and

1094 Customization Guide


document info pages. That is done by overriding the pre-existing
definition for the Customize menu on information pages for these 2
objects, and this is described below.
b. Displaying the model
The model "third_level_nav_part" contains the list of Customize menu on
information pages that is available for parts. OOTB, this model is defined
in PartClient-actionmodels.xml, and the menu options are
"general", "relatedItems", "changes", "history", and "collaboration". In
order to add the newly created configLinks model to the info page of a
part, the "third_level_nav_part" definition has been overridden to include
this new model as well. An important point to keep in mind is that
performing this step will override any previous customizations to "third_
level_nav_part". In order to retain any previous customizations, copy the
definition of the model being overridden ("third_level_nav_part" in this
case) as it exists on the system into the newly created actionmodels file
("ConfigurableLinkExamples-actionmodels.xml" in this
case). Then add the newly defined model ("configLinks" in this case)
to the overridden model ("third_level_nav_part") using the "submodel"
tag.
The same steps in step 3b would have to be followed to display the new
menu option for configurable link tables in the in the Customize menu on
information pages of any other object (Document is also provided in the
OOTB example).
4. Creating labels for the table header and action title
Labels are created using annotations in a java file. In the OOTB example, this
is done in the configurableLinkExamplesResource.java file.
This file ties the registration of the in the Customize menu on information
pages to the link type that is implemented for the table, the table header and
the action title. The tie-up for the link type is done in the moreurlinfo field.
The value for this field has the configurableLinkType set to the value of the
BeginTypeDefView name defined in Step 1. The display text for the action
title is set by defining the respective values for the action names created in
step 2.
This file must be compiled, and the compiled (.class) version of this file must
be placed in <Windchill>/codebase/com/ptc/windchill/
enterprise/object

Configurable Links 1095


Note
For steps 5 through 8, the OOTB example code is located in files with the
prefix “ConfigurableLinkExamples”, however you should make
any customization changes by creating files with the
“ConfigurableLinkCustomizations” file prefix.
• ConfigurableLinkCustomizations.xconf
• ConfigurableLinkCustomizations-wt.properties.xconf
• ConfigurableLinkCustomizations-service.properties.xconf

5. Registering the Relationship Tables with a Validator


Once the actions have been defined, it is necessary to register each newly
created action with the common validator in order to ensure that the logic
behind the hide/display rules for the action title and relationship table work
correctly. In the OOTB example, this is done in the
ConfigurableLinkExamples-service.properties.xconf file.
The source and target locations for this file are:
• Source: com/ptc/windchill/enterprise
• Target: <Windchill>/codebase/com/ptc/windchill/
enterprise
Depending on the table being registered - Role A (parent) or Role B (child) (i.
e., depending on the selector), the corresponding validator -
ConfigurableLinkParentTableActionValidator or
ConfigurableLinkChildTableActionValidator should be used
respectively as the serviceClass.
6. Registering the Relationship Tables with Table Titles
In order to see Table Titles on your custom configurable link tables, you need
to register each table with ConfigurableLinkDynamicUrlDelegate
in ConfigurableLinkCustomizations-
service.properties.xconf.
In the OOTB example, this is done in the
ConfigurableLinkExamples-service.properties.xconf file.
7. Registering the Relationship Tables with Table Views
In order to use custom Table Views with your custom configurable link tables,
you need to register each table with the appropriate table views class in
ConfigurableLinkCustomizations-
service.properties.xconf. If the base type of the configurable link

1096 Customization Guide


is ConfigurableReferenceLink, then you would register your
configurable link with ConfigurableReferenceLinkTableViews. Likewise links
of base type ConfigurableDescribeLink should be registered to
ConfigurableDescribeLinkTableViews and those with base types of
ConfigurableMasterLink should be registered to
ConfigurableMastersLinkTableViews. The selectors that are used
should be the internal name defined for the configurable links, followed by
either _childTable or _parentTable depending on if it is a Role A or
Role B table.
For example, CustomReferenceLink's selectors would be
com.ptc.CustomReferenceLink_childTable and
com.ptc.CustomReferenceLink_parentTable.
In the OOTB example, this is done in the
ConfigurableLinkExamples-service.properties.xconf file.
8. Registering the Relationship Tables with the Action Command Delegate
This is a required step for all configurable link tables that have toolbar
actions. In order to make the configurable link toolbar actions work properly,
register every configurable link table with
ConfigurableLinkTableToolbarActionCommandDelegate. Use
the same selector from Step 7 (ex. com.ptc.CustomReferenceLink_
childTable). These entries should be made in
ConfigurableLinkCustomizations-
service.properties.conf.
In the OOTB example, this is done in the
ConfigurableLinkExamples-service.properties.xconf file.
9. Registering the actions and actionmodels files
The next step is to add the newly created actions and actionmodels files (from
steps 2 and 3 respectively) to the application wide list of actions/actionmodels
files that are picked up by the actions service. This is done in the OOTB
example by the ConfigurableLinkExamples-
wt.properties.xconf file.
An important point to keep in mind is that the newly created actions and
actionmodels files (as part of the customization) now contain overrides to
models that were originally defined OOTB. If this step of adding these new
files is not performed, then the original definition of these models will be used
by the application.
In the OOTB example as described above, the "third_level_nav_part" model
has been overridden to include the "configLinks" submodel. It is
important to perform Step 9 in such a way that these new files are added to the

Configurable Links 1097


global definition after the OOTB definition. In this example,
ConfigurableLinksExample-actionmodels.xml must be added
after PartClient-actionmodels.xml and
DocumentManagement-actionmodels.xml. This is because the
OOTB example overrides the definition of the "third_level_nav_part"
and "third_level_nav_doc" models. All the actions and actionmodels
files are placed in wt.properties (step 10) and the last definition of a
specific model is what will take effect.
If the newly created actions and actionmodels files are removed from
wt.properties, or are not registered as required here in Step 8, or placed
before the OOTB model definitions, then the OOTB behavior will be observed
for the specific Customize menu options on information pages.
10. Collecting the registration in Steps 5 through 9 together.
For convenience in the installation process, the xconf settings (containing
registrations such as those in steps 5 and 6) specific to a module are placed
together in one file. In the OOTB example, this file is
ConfigurableLinkExamples.xconf.
This file references the files created in steps 5 through 9 above and puts them
together in one location for the xconfmanager to pick up and propagate the
changes. The xconfmanager places all actions and actionmodels files in wt.
properties, and this is used eventually by the action service.
The above steps create a customized Configurable Link Table. In order to
install this, follow the instructions under the Installing the Configurable Links
Example on page 1091.

1098 Customization Guide


Defining Access Control Policy Rules for
Configurable Links
After defining a Configurable Link Subtype based on ConfigurableMastersLink,
the access control policy rules for the configurable link subtype must be defined
or loaded so that the to grant the product or library or project team members the
appropriate access rights. There are no OOTB access rules for
ConfigurableMastersLink object or any of its subtypes. Therefore, OOTB only the
administrative users have the right to create these links.
The access control policy rules for the ConfigurableMastersLink can be defined in
one of the following three ways:
1. Use Policy Administration to add access policies for the
ConfigurableMastersLink subtypes.
2. Load the access control policy rules using the csvAccessRule tag in an XML
load file.
Following is an example of an access control policy rule that can be loaded via
an XML file that will grant everyone permissions read, modify, create and
delete ConfigurableMastersLink objects. More specific access control policy
rules can be defined for subtypes of ConfigurableMastersLink.
<csvAccessRule handler="wt.load.LoadUser.createAccessRule">
<csvuser/>
<csvdomain>/System</csvdomain>

<csvtypeId>wt.configurablelink.ConfigurableMastersLink</csvtype
Id>
<csvpermission>+</csvpermission>
<csvprincipal>ALL</csvprincipal>
<csvpermissionList>0/1/2/5</csvpermissionList>
<csvstate/>
</csvAccessRule>
3. Update the product and/or library container templates to include the access
control policy rules for the ConfigurableMastersLink and/or its subtypes. Any
new products or libraries created with the updated templates will automatically
load the access control policy rules. Following is an example of an access
control policy rule that can be added to a product or library templates that will
grant the teamMembers permissions read, modify, create and delete
ConfigurableMastersLink objects. More specific rules can be defined for
subtypes of ConfigurableMastersLink.
<AccessControlRule>
<domainName>/Default</domainName>

<externalTypeId>wt.configurablelink.ConfigurableMastersLink</ex

Configurable Links 1099


ternalTypeId>
<lifecycleState>ALL</lifecycleState>
<WTPrincipalReference isInternal="true">
<groupName>teamMembers</groupName>
<groupType>teamMembers</groupType>
</WTPrincipalReference>
<grantPermissionSet>
<AccessPermissionSet>
<permissionField name="READ"/>
<permissionField name="MODIFY"/>
<permissionField name="CREATE"/>
<permissionField name="DELETE"/>
</AccessPermissionSet>
</grantPermissionSet>
</AccessControlRule>

Configurable Revision Links


A Configurable Revision Link is a revision to revision relationship. When a
configurable revision link is created, you can initialize a soft attribute defined on
the link.
You can configure the default values that can be set for each attribute via an XML
configuration file. The IBA framework APIs are used to load the IBA attributes,
so the name must be the attribute name of the IBA attribute.
The value1 is a required attribute which specifies the value for the attribute. The
value2 attribute is optional and is required to pass in additional value (for
example precision in float). If the XML file is not configured, no operations are
performed.
The supported type for which IBA attributes can be set is
ConfigurableRevisionLink.

1100 Customization Guide


Events
Events that are configured to set\reset the values of IBA attributes and the
respective tags that hold values are:
Event Tag
Creation of Configurable Revision onCreation
Link. The value is only set if value is
not already set.
Copy forwarded Configurable Revision onReviseOfRoleA
Links on the revise of Role A.
Copy forwarded Configurable Revision onReviseOfRoleB
Links on the revise of Role B. This
option is only available if the
preference is set to True.

Supported IBA Attribute Types


Supported IBA attributes types for both standard and global IBAs and the format
for the value:
Type Context Sample Value
String Standard and Global value= "StringValue"
IBAs
Integer Standard and Global value= "IntegerValue"
IBAs
Real Number Standard and Global value= "RealValue|
IBAs Precision"
Real Number with Units Standard and Global value="RealValue|
IBAs Precision|Units"
Boolean Standard and Global value= "BooleanValue"
IBAs
Date & Time Standard and Global value= "YYYY-MM-DD
IBAs HH:MM:SS.S" (the time
is GMT)
URL Global IBAs value= "hyperlink|label"

Configurable Links 1101


Note
• If there are multiple parts to an attribute (for example Real Number with
precision), the parts must be delimited by '|'.
• The delegate only supports setting the attribute if the attribute has a single
value. In the case of a multi-valued attribute that has more than one value,
the delegate will not set any value for the attribute.
• Attributes values can be defined for the Parent type and are applied to soft
types by inheritance.

Defining and Loading Default Values


1. The property that contains the definitions for the default values:
wt.configurablelink.DefaultValues=
$(wt.home)$(dir.sep)codebase$(dir.sep)wt$(dir.sep)
configurablelink$(dir.sep)DefaultValuesForConfi
gLink.xml
2. If changes are made to the DefaultValuesForConfigLink.xml file
you must either:
a. Restart the Method Server
b. Run the wt.configurablelink.ConfigurableLinkUtils
utility to load the default values for attributes.

Sample Configuration File


This is a sample xml file for specifying the default values for IBA attributes to be
set on creation.
Location: <Windchill>\codebase\wt\configurablelink\
DefaultValuesForConfigLink.xml
<type name="WCTYPE|wt.configurablelink.ConfigurableRevisionLink">
<attribute name="std_real_1">
<onCreation value="20|2" />
<onReviseOfRoleA value="20|2" />
<onReviseOfRoleB value="50|2" />
</attribute>
<attribute name="std_real_u1">
<onCreation value="20|1|kg/s**3" />
<onReviseOfRoleA value="40|2|kg/s**3" />
<onReviseOfRoleB value="50|2|kg/s**3" />
</attribute>
<attribute name="std_bool_1">
<onCreation value="true" />

1102 Customization Guide


<onReviseOfRoleA value="false" />
<onReviseOfRoleB value="false" />
</attribute>
<attribute name="std_str_1">
<onCreation value="StringND"/>
<onReviseOfRoleA value="StringRoleA"/>
<onReviseOfRoleB value="StringRoleB"/>
</attribute>
<attribute name="std_url_1">
<onCreation value="http://www.ptc.com|PTC"/>
<onReviseOfRoleA value="http://www.ptc.com|PTC"/>
<onReviseOfRoleB value="http://www.ptc.com|PTC"/>
</attribute>
<attribute name="std_ts_1">
<onCreation value="2001-01-30 12:12:12.128"/>
<onReviseOfRoleA value="2001-01-30 12:12:12.128"/>
<onReviseOfRoleB value="2001-01-30 12:12:12.128"/>
</attribute>
<attribute name="std_int_1">
<onCreation value="2"/>
<onReviseOfRoleA value="2"/>
<onReviseOfRoleB value="2"/>
</attribute>
</type>
</defaultValuesForattributes>

Configurable Links 1103


21
Customizing Online Help
Customizing Windchill Help Center Content............................................................. 1107
Adding Topics to the Help Center TOC .................................................................... 1108
Linking to Help Topics .............................................................................................1114
Windchill Help Center Logging.................................................................................1115

This section explains how to customize Windchill online help. Customizers of


online help should have advanced knowledge of HTML and JavaScript, and some
familiarity with XML.
Windchill solutions deliver online help in the Windchill Help Center. The
Windchill Help Center is a cross-browser, DITA-based format that provides a
three-pane window. The top pane contains buttons to select navigation features.
The left pane is a tabbed view that contains the table of contents, the index, and a
search form for navigating and searching the help system. Online help content
appears in the right pane.
The Windchill Help Center refers to a collection of topic files and their
corresponding tables of contents and full-text search files. In the Windchill Help
Center , the term topic refers to a single HTML file that is displayed in the right
pane of the Windchill Help Center window. For more information about the
Windchill Help Center features, see the home page of the Windchill Help Center.
The default location of your Windchill Help Center is the <Windchill>/WHC/
directory, where <Windchill> is the Windchill installation directory.

1105
Caution
When you customize online help, always work with a copy of the online help
files. After you have ensured that your customizations work properly, you can
copy your changes to the appropriate directory.

1106 Customization Guide


Customizing Windchill Help Center
Content
This section describes how to edit online help topic content. To update topics in
the Windchill Help Center, you must have the appropriate permissions to replace
files on your server.

Modifying an Existing Topic

Caution
Before modifying any existing content backup your Windchill Help Center
directory.

To modify the text of an existing topic, use a standard HTML editor or text editor.
Modification of HTML content other than text is not recommended. Use the
following steps to access, modify, and replace help topics.
1. Right click the topic you want to change in the table of contents of the
Windchill Help Center.
2. Select Copy Link Location from the menu.
3. The portion of the Address (URL) after http://<server location>/
Windchill-WHC/ contains the file name of the topic you want to edit. For
example, for
http://user.ptc.com/Windchill-WHC/
UserSetupPreferences.html#styler-id1.1.1.4.4.4.4.1
you would edit
UserSetupPreferences.html (you can ignore the #styler-
id1.1.1.4.4.4.4.1 part of the URL).
4. Navigate to the installed location of your Windchill Help Center and locate the
zip file that contains the HTML help topics. By default, the installed location
is <Windchill>/WHC/WEB-INF/volume, where <Windchill> is the
Windchill installation directory.
5. Open the appropriate ZIP file for your locale. For example, English content in
contained in wc_en.zip.
6. With an archive utility that allows you to extract a individual files from a ZIP
file, extract the file(s) you want to modify to a temporary directory.

Customizing Online Help 1107


Note
Unarchiving and rearchiving the ZIP file containing the HTML topics is
not recommended. Use a utility that allows you to update files directly
inside the ZIP file.

7. In your temporary directory, open the help topic in a standard HTML editor to
modify the content. Modification of colors, headers, or other styles is not
recommended. Be sure to maintain the same file name.
8. Stop the Windchill web server. This is required before you can update any
contents in the Windchill Help Center directory.
9. Using your chosen archive utility, overwrite the existing HTML file (s) in the
ZIP file with your modified HTML files.
10. Restart the Windchill web server in order to verify your changes to the
Windchill Help Center content.

Adding Topics to the Help Center TOC


You can add additional content to the table of contents (TOC) of the Windchill
Help Center. There are two methods for adding content:
• Adding Content using Arbortext on page 1108
• Adding Content using the Add Topics Utility on page 1111

Note
Any custom content that you add is not stored in the same location as the the
OOTB Windchill Help Center content. Because of this you cannot add links to
this content from a Windchill UI using the process specified in Linking to
Help Topics on page 1114.

Adding Content using Arbortext


You can add content published from Servigistics Arbortext Editor as a DMP
Image Input to an existing Windchill Help Center. You can publish multiple
documents as a DMP Image Input and add multiple directories to the Windchill
Help Center. Additional contents will be appended to the image’s table of contents
in alphabetical order based on the names of the directories that contain your added

1108 Customization Guide


content. The image’s index terms and profile settings will also be updated based
on the additional content. However, the additional content will not be searchable
with the Windchill Help Center search feature. See the “Adding Content to
Existing Images” topic in theServigistics Arbortext Help Center for more
information.

Generating Content in Arbortext


1. Publish your content using the steps in the “Composing a Document as DMP
Image Input” topic in the Servigistics Arbortext Help Center.

Note
For more information and instructions on this process see Arbortext Digital
Media Publisher ▶ Developer’s Guide in the Servigistics Arbortext Editor
Help Center.

2. Copy your generated content into a folder. This folder is referred to as


the<new_content> directory in the following instructions.

Placing the New Content in Windchill


1. If the <Windchill>\WHC\WEB-INF\additionalcontents\
directory does not exist, you must manually create it.
2. Copy your <new_content> directory to the <Windchill>\WHC\WEB-
INF\additionalcontents\ directory on your Windchill server.
3. Restart your webserver.
4. Once the webserver has been restarted, the <new_content> directory is
processed. A folder named .compiled is created within the <new_
content> directory.
5. Your new content will be displayed as the last item in the TOC of the
Windchill Help Center.

Note
The new content is not searchable through the Search function within the
Windchill Help Center.

Troubleshooting
If the new content does not appear in the TOC of your Windchill Help Center:
1. Verify that the following files exist:

Customizing Online Help 1109


• <new_content>\.compiled\config\indexterm_en.xml
• <new_content>\.compiled\config\profiles.xml
• <new_content>\.compiled\dmp_fragment.config
2. If those files do not exist:
a. Copy the indexterm_en.xml and profiles.xml files from the
.compiled directory into the in the .compiled\config\ directory.
Do not move or modify the original files in the .compiled directory.
b. In the .compiled directory create a dmp_fragment.config file as
follows:
<?xml version="1.0" encoding="UTF-8"?>
<DMPConfigFragment>
<TocInfo profileHref="config/profiles.xml">
<TocHref locale="en" href="toc/en.xml"/>
</TocInfo>
<VolumeInfo>
<Volume id="<ZIP File ID>" href="volume/<ZIP File ID>.zip"/>
</VolumeInfo>
</DMPConfigFragment>

Replace <ZIP File ID> with the name of the .zip file located in the
<Windchill>\WHC\WEB-INF\additionalcontent\<new_
content>\volume directory.

Note
The sample above is for the English locale. When adding content for other
languages you must specify the appropriate locale versions of the files (such as
indexterm_<LOCALE>.xml or <TocHref locale="<LOCALE>"
href="toc/<LOCALE>.xml"/>).

1110 Customization Guide


Adding Content using the Add Topics Utility
If you do not have Arbortext, you can add topics to the Windchill Help Center
using a stand alone utility. The Add Topics utility is a simple utility that can add
content to the Windchill Help Center table of contents. Your additional content is
added to the bottom of the Windchill Help Center TOC. The content that you add
will not be searchable.

Downloading the Utility


Download the utility from the following location : http://www.ptc.com/view?im_
dbkey=141479
The download includes the Add Topics utility and a copy of these instructions. The
download file may contain an updated version of the instructions.
Extract the contents of the <FILENAME>.zip file to the following location on
your Windchill server: <Windchill>\Windchill\WHC\

Generating your Content


Generate an HTML topic collection from the HTML editor of your choice. The
files that you add will contain whatever styles you use when you generate them.
Additional content does not use the existing Windchill Help Center stylesheet.
Once you have generated the files, place all the files that you want to add to the
TOC into a single folder. This folder is referred to as the <new_content>
directory in the following instructions.

Note
You can also include PDF files in your custom content.

Customizing Online Help 1111


Running the Add Topics Utility

1. Make sure that the Windchill Help Center is not running. This may require
you to stop your webserver or Windchill server.
2. Launch the Add Topic utility (AddTopics31.exe).
3. Select the table of contents XML file that you want to add content to. There is
an XML TOC file for each installed language. For example <Windchill>\
Windchill\WHC\WEB-INF\toc\en.xml is the TOC file for English.
4. Select the directory with the files you want to include in the table of contents.
Your folder must reside on the same level as the WEB-INF folder of your
Windchill Help Center installation directory (<Windchill>\Windchill\
WHC). The list of files is loaded under the HTML and PDF files list.
5. Specify a name for the new table of contents book.
6. The files that you add are imported in alphanumeric order by default. Use the
Move Up and Move Down buttons to modify the order of the files. You can also
reorder files by dragging and dropping the files directly within the list.

1112 Customization Guide


7. Click Add Topics to add the files.
8. After the utility completes updating the table of contents update, click OK.
9. Restart your webserver or Windchill Server.
10. Once the Windchill Help Center is running, verify that the TOC changes are
what you wanted. If not, you must revert back to the original TOC and rerun
the Add Topics utility.

Note
• Do not move or delete the referenced files after updating the table of
contents. This will cause broken links and the files you added will not be
displayed in the Windchill Help Center.
• A backup file is created with the following naming convention: <YOUR_
TOC><TIMESTAMP>BACKUP.xml. For example: en07022012_
133940BACKUP.xml. You will need this file if you ever want to revert
back to your original TOC.
• The Add Topics utility can be rerun multiple times to add additional
content. Sections are added to the bottom of the TOC in the order in which
they are processed. Each time you run the utility a new book is created for
the TOC. You cannot add content to existing TOC books.

Reverting to the Original TOC


To revert to the original table of contents follow these steps:
1. Stop your webserver or Windchill Server.
2. Verify that the appropriate backup file exists in the <Windchill>\
Windchill\WHC\WEB-INF\toc\ directory. The file name will be in the
format: <YOUR_TOC><TIMESTAMP>BACKUP.xml. For example:
en07022012_133940BACKUP.xml.
3. Delete the TOC XML file that was created when you ran the Add Topics
utility. This file is located in the <Windchill>\Windchill\WHC\WEB-
INF\toc\ directory. The file name will be based on an installed language.
For example <Windchill>\Windchill\WHC\WEB-INF\toc\
en.xml is the TOC file for English.
4. Rename the <YOUR_TOC><TIMESTAMP>BACKUP.xml file to <YOUR_
TOC>.xml
5. Restart your webserver or Windchill Server.

Customizing Online Help 1113


Linking to Help Topics
This section explains how to link to topics in the Windchill Help Center (WHC)
from common component user interfaces. The WHC is the repository for all help
topics.
The web app for the WHC is different than the web app for Windchill.

URL Details
• The wt.whc.url property in the wt.properties file defines the URL to
the WHC.
• The wt.help.HelpLinkHelper.createHelpHREF(String) API
returns the correct fully qualified WHC URL.

How to Link to Help Topics


This section explains how to link to help topics in the WHC from the Windchill
UI.

Information Pages
The help button ( ) will appear in the upper right corner of the information page
if you set a help context in your info builder:
// sets the help topic to use from the Windchill Help Center
infoConfig.setHelpContext("HelpTopicName");

Table/Tree
The help button ( ) will appear in the upper right corner of the table/tree if you
set a help context in your builder:
// sets the help topic to use from the Windchill Help Center
tableConfig.setHelpContext("HelpTopicName");

If your table/tree is still defined in a jsp instead of with a builder, adding the help
topic would be as follows:
<renderTable model="${tableModel}" helpContext=" HelpTopicName"/>

Wizards
The help button ( ) will appear in the upper right corner of the wizard if you
specify a help selector key in the wizard tag:
<jca:wizard helpSelectorKey="HelpTopicName" …>

1114 Customization Guide


Other Pages
If you are not using a common component but would like to produce a link to the
WHC in your UI, you can use the helpButton tag in a jsp to output a button on
the page:
<%@taglib uri="http://www.ptc.com/windchill/taglib/wrappers" prefix="w" %>
<w:helpButton helpSelectorKey="HelpTopicName"/>

This results in a help button ( ) in the UI.


If for some reason the helpButton tag cannot be used for a particular UI, you
can get a URL to a help topic with the
HelpLinkHelper.createHREF(String) API.
For example,
wt.help.HelpLinkHelper.createHelpHREF("HelpTopicName")
will return a URL to the given help topic in the WHC in the following form:
<value from wt.whc.url property in wt.properties>/
HelpTopicName.html.
For example: http://<localhost>/Windchill-WHC/
HelpTopicName.html
For launching that URL you could use the javascript API:
PTC.help.openHelpWindow(helpUrl);
This would launch the help topic in a popup window, and on subsequent clicks of
the help link would refocus that same help window instead of launching a new
one.

Windchill Help Center Logging


Configuring Windchill Help Center Logging
To capture operational information about the Windchill Help Center, enable Help
Center Logging using the following steps.

1. Display the logging configuration page by browsing to view_config_


logging.jspx. This file is in the root directory of the Windchill Help
Center application. For example, browse to: http://<hostname>/
Windchill-WHC/view_config_logging.jspx
The logging configuration page appears as follows:

Customizing Online Help 1115


2. Select Enable to enable logging.
3. Select a logging level.
• Debug — Reports all Windchill Help Center operational states in addition
to the information and errors reported by the Error and Info logging levels.

Caution
Use the Debug log level setting with care. Setting a logging level of
Debug causes a very significant amount of information to be recorded
in the Windchill Help Center log file.

• Info — Reports informational messages about Windchill Help Center


operation in addition to the errors reported by the Error logging level.
• Error — Only reports errors the Windchill Help Center encounters while
running.
4. Enter a path to store log files in Log File with Path. Logging comments are
recorded in a file named temp.log in this directory. When the log file
reaches a maximum size of approximately 10 mb, a new log file is started, and
the previous log file is saved with a numeric extension. Older log files are not
automatically deleted.
5. Click Submit to start capturing enhanced logging comments. Use an ASCII
editor to view the contents of the log files.

1116 Customization Guide


Note
Log files can fill with information rapidly. PTC recommends you enable
logging only while diagnosing specific issues with your Windchill Help
Center deployment, and not in an ongoing manner for any logging level other
than Error.

Customizing Online Help 1117


22
Windchill Search Customization
Customizing Indexing Behavior .............................................................................. 1120
Customizing Solr ................................................................................................... 1122
Customizing Faceted Search ................................................................................. 1128

This section contains information on customizing search functionality.

1119
Customizing Indexing Behavior
You can modify search engine index information that is associated with a
Windchill business object.

Configure DefaultIndexObjectBuilder
Provide the implementation for the following method with a signature:
protected void setAdditionalAttributes(EPMDocument
indexable, TypeInstance ti, WCIndexingObject
indexingObject, WTCollection sharedMapCollection) throws
WTException
To use a customized DefaultIndexObjectBuilder class, you must update
the service.properties file to reflect this change.
The following is the default entry:
# #####################################################
# The wt.index.builder.IndexObjectBuilder service.
# ###########################################################
wt.services/svc/default/wt.index.builder.IndexObjectBuilder/
null/wt.index.Indexable/0=wt.index.builder.DefaultIndexObjectBuilder
/duplicate
For this example, assume that you have a custom
DefaultIndexObjectBuilder named DemoIndexObjectBuilder that
you want to use to index. If you want to override the default
DefaultIndexObjectBuilder, you must add the following line to
service.properties : wt.services/svc/default/
wt.index.builder.IndexObjectBuilder/null/
wt.epm.EPMDocument/0=
wt.index.builder.DemoIndexObjectBuilder/duplicate

Note
This value should be entered on one line.

setAdditionalAttributes
You can override the custom_
setAdditionalAttributes(EPMDocument indexable,
TypeInstance ti, WCIndexingObject indexingObject,
WTCollection sharedMapCollection) method and add your specific
code into this method.

1120 Customization Guide


Example
import wt.epm.EPMDocument;
import wt.fc.collections.WTCollection;
import wt.index.IndexAttributeInfo;
import wt.index.WCIndexingObject;
import wt.util.WTException;
import com.ptc.core.meta.type.common.TypeInstance;

/**
* Demo IndexObjectBuilder implementation for EPMDocument object type.
*/

public class DemoIndexObjectBuilder extends


DefaultIndexObjectBuilder<EPMDocument> {

/* Override setAdditionalAttributes method to set additional attributes in


* IndexingObject so that it gets indexed to SOLR and is searchable
* The super class already has some implementation, so have to call
* super.setAdditionalAttributes method explicitly Instead we can have a
* custom method that can be overridden and keep it's implementation
* empty in DefaultIndexObjectBuilder
* (non-Javadoc)
* @see wt.index.builder.DefaultIndexObjectBuilder#setAdditionalAttributes
* (wt.index.Indexable, com.ptc.core.meta.type.common.TypeInstance,
* wt.index.WCIndexingObject, wt.fc.collections.WTCollection)
*/

@Override
protected void setAdditionalAttributes(EPMDocument indexable, TypeInstance ti,
WCIndexingObject indexingObject, WTCollection sharedMapCollection)
throws WTException {
//call the setAdditionalAttributes method of super class to keep the
//existing implementation intact

super.setAdditionalAttributes(indexable, ti, indexingObject,


sharedMapCollection);

//Get the additional values to be indexed from TypeInstance or any


//other custom implementation

String demoVal = "SOME_VALUE";

//Get the custom for which user wants solr field. Like SOME_ATTRIBUTE
IndexAttributeInfo attributeInfo = getAttributeInfo
("SOME_ATTRIBUTE", demoVal, false);

//If the attribute value needs to be indexed as a separate field in SOLR,


//then add it to unmappedAttInfo list in IndexingObject

indexingObject.addToUnmappedAttInfo(attributeInfo);

Windchill Search Customization 1121


//If the attribute value needs to be searchable via keyword, then append the
//value to the metadata field whose content is searchable through keyword
indexingObject.appendMetadataField(demoVal);
}
}

Customizing Solr
Solr has the following configuration files:
• <$solr-home>\wblib\conf\schema.xml
• <$solr-home>\wblib\conf\solrconfig.xml
The value for <$solr-home> is the Solr home directory you specified when
installing Solr with Windchill.

Note
The default core is wblib. If you plan to use multicore, then this folder would
be replaced by the core names.

Custom Solr Help Link


When you set the Search Mode preference to Advanced, a clickable link named
Examples for Query Mode Syntax appears on the Advanced Search page.
Clicking this link opens a blank JSP page that can be customized according to
your requirements. The customizable JSP file is named
examplesForQueryModeSyntaxLink.jsp and is located under
Windchill/codebase/netmarkets/jsp/search.
For keyword search examples, see “Using Advanced Search Mode” in the
Windchill Help Center.

Language Customization
To support any new language, customize indexing, or customize searching
behavior for specific fields, then you must modify schema.xml.
The fields for all the languages supported in Windchill are configured out-of-the-
box.
Index search queries are targeted against the Keyword field, which has the type
text_rlp. For every language, Windchill defines different fields (text_ja for
Japanese, text_kor for Korean, and so on).

1122 Customization Guide


When adding a new language, you must introduce a new field with a name of your
choice. For example, the following is the entry for text_rlp:
<fieldtype name="text_rlp" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="com.ptc.search.solr.tokenization.PTCTokenizerFactory"
defaultLanguage="jpn" defaultFieldType="text"

fieldTypesPerLangauge="jpn-text_ja,eng-text,deu-text_deu,
kor-text_kor,fra-text_fr,ita-text_ita,zhs-text_zhs,ell-text_ell,ru-text_rus" />
</analyzer>

<analyzer type="query">
<tokenizer class="com.ptc.search.solr.tokenization.PTCQueryTokenizerFactory"
defaultFieldType="text"
fieldTypesPerLangauge="jpn-text_ja,eng-text,deu-text_deu,
kor-text_kor,fra-text_fr,ita-text_ita,zhs-text_zhs,ell-text_ell,ru-text_rus" />
</analyzer>
</fieldtype>

• Each language-dependent field should be mentioned in the comma-separated


value given for the fieldTypesPerLangauge attributes.
• Your language-dependent value would be the ISO 639 code for the language
and the field name. Use the following format:
<ISO 639 code>-<fieldName>

For example, for Japanese, ISO 639 code is jpn and the field name is text_
ja. Therefore the value is jpn-text_ja.
For a list of language codes, use the following link:
http://www.loc.gov/standards/iso639-2/php/code_list.php
• The defaultLanguage parameter sets the default language tokenizer in
case the actual language of the token is not detected properly,

Filtering Text Field Searches

Note
For more detailed information about analyzers, filters and tokenizers, see the
following link:
http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters

Windchill Search Customization 1123


Every text field uses the
com.ptc.solr.analysis.PTCWordDelimiterFilterFactory filter.
This filter splits words into subwords and performs optional transformations on
subword groups. Words are split into subwords using the following rules:
Rule Example
Split on intra-word delimiters (by "Wi-Fi" splits into "Wi" and "Fi"
default, all non alpha-numeric
characters)
Split on case transitions. "TransAM" splits into "Trans" and
"AM"
Leading and trailing intra-word "__hello—there, 'dude'" splits into
delimiters on each subword are ignored. "hello", "there", and "dude"
Trailing "'s" characters are removed for "O'Neil's" splits into "O" and "Neil".
each subword.

Note
This step is not performed in a
separate filter because of possible
subword combinations.
This filter is a replica of solr.WordDelimiterFilter, which is shipped
with Solr. It has been customized to protect the following characters: ".", "-" and
"_"
Splitting is affected by the following parameters:
• generateWordParts=1
Parts of words are generated: "whistle-blower" = "whistle" "blower"
• generateNumberParts=1
Number subwords are generated: "500-42" = "500" "42"
• catenateWords=1
Maximum runs of word parts are catenated: "re-confirm" = "reconfirm"
• catenateNumbers=1
Maximum runs of number parts are catenated: "500-42" = "50042"
• catenateAll=1
All subword parts are catenated: "wi-fi-4000" = "wifi4000"
• splitOnCaseChange=1
Split on case transitions: “PowerShot” = "Power" "Shot"
• preserveOriginal=1

1124 Customization Guide


Includes original words in subwords: "500-42" = "500" "42" "500-42"
The
com.ptc.solr.analysis.PTCSpecialCharacterFilterFactory
filter is also used. This filter creates sub-tokens for tokens that end with PTC
protected special characters. Currently there are only three protected special
characters:
• dot or period (.)
• dash (-)
• underscore (_)
Sub-tokens are created with the following rules:
Rule Example
Tokens ending with a period(.) "dot." = "dot.", "dot"
Tokens ending with a dash (-) "dash-" = "dash-", "dash"
Tokens ending with an underscore (_) "under_" = "under_", "under"

Note
Ensure that the same order of tokenizers is maintained at indexing and query
time. Tokens generated at query time should be the same as when indexing for
a given word.

Stop Words
The words mentioned in $solr-home\wblib\conf\stopwords.txt are
not indexed. These words should be words that a user would not enter in a
meaningful search. For example, “if” or “not”. To include these words in searches,
remove them from stopwords.txt.
For English, the text field is used and is configured using the
StopFilterFactory filter.

Synonyms
The synonym entries in $solr-home\wblib\conf\synonyms.txt ensure
that searching on one word can find records with synonymous words. You can edit
this file to enter or remove synonyms.
The SynonymFilterFactory filter is configured for English text fields.

Windchill Search Customization 1125


autoCommit
Windchill uses the Solr auto commit feature to commit the index information
automatically after certain criteria is met.
You can configure autoCommit in solrconfig.xml.
This criteria is specified under the following element:
<updateHandler class="solr.DirectUpdateHandler2">
<autoCommit>
<maxDocs>1000</maxDocs>
<maxTime>60000</maxTime>
</autoCommit>

maxDocs
maxDocs is the maximum uncommited Windchill business object documents
before autocommit triggered
maxTime
maxTime is the maximum time (in milliseconds) after adding a Windchill
business object document before an autocommit event is triggered
Indexed searches perform better when the maxTime and maxDocs values are
higher.
However, an object does not appear in search results unless the index information
is committed.

Note
Use higher values when you run bulk indexing.

Enabling Alphanumeric Splits


By default, Windchill search does not tokenize alphanumeric transitions. For
example, the string “ABC123” is indexed as “ABC123.”
You can customize Solr to enable alphanumeric splits. When enabled, the string
“ABC123” is indexed as the following:
ABC123
ABC
123
To enable alphanumeric splitting, perform the following actions:
1. Stop Windchill.
2. Navigate to the following file:

1126 Customization Guide


/solr-home/wblib/conf/conf_generic_field_types.xml
3. Locate all instances of the following: splitOnNumerics="0"
And replace with the following: splitOnNumerics="1"
4. Restart Windchill.
5. Once Windchill is restarted, re-index data using the Bulk Index Tool.

Windchill Search Customization 1127


Customizing Faceted Search
Modeled Attribute Visibility in Facets
By default all attributes that are searchable are considered for facets. List of
searchable attributes is configured per type in
searchableAttributesByType.properties file. If any attributes need
to be hidden in facet then add a new entry in this file against 'facetSearch'
key and remove the required attribute.
For instance, following is the entry for attributes of WTPart:
advancedSearch.wt.part.WTPart=
thePersistInfo.createStamp,iterationInfo.creator,defaul
tUnit,lock.locker,search_name,search_
number,ownership.owner,source,state.state,partType,the
PersistInfo.modifyStamp,iterationInfo.modifier,view.i
d,organization.id,oemPreference,endItem,versionInfo.i
dentifier.versionId,iterationInfo.identifier.iteratio
nId,collapsible,interopInfo.iopState,defaultTraceCode,
genericType
If you want to hide defaultUnit in facets then add a new entry as below
excluding the defaultUnit attribute ID:
facetSearch.wt.part.WTPart=
thePersistInfo.createStamp,iterationInfo.creator,lock.
locker,search_name,search_
number,ownership.owner,source,state.state,partType,the
PersistInfo.modifyStamp,iterationInfo.modifier,view.i
d,organization.id,oemPreference,endItem,versionInfo.i
dentifier.versionId,iterationInfo.identifier.iteratio
nId,collapsible,interopInfo.iopState,defaultTraceCode,
genericType
The entry is type specific. If any particular attribute is to be hidden for multiple
types then multiple entries need to be added for applicable types.

Customization for hiding IBAs from Facet


You can customize the visibility of IBAs appearing on the facet.
Implement the FacetService interface. Update the service entry with custom
class in service.properties.

1128 Customization Guide


Element Package Type Description
FacetService Com.ptc.wind Interface The interface
chill.enter controls the
prise.search. visibility of IBAs
facet on the facet.

Customization Points
Update the service entry with Custom class in "service.properties" as
shown in the sample code. In the example, facetCustomClass is the name of
custom class.
wt.services/svc/default/
com.ptc.windchill.enterprise.search.facet.FacetService/
null/null/0=
com.ptc.windchill.enterprise.search.facet.FacetCustom
Class/duplicate
Implement the inherited
method FacetService.isAttributeVisible(AttributeTypeIden
tifier). The isAttributeVisible API returns boolean value which is set
to true by default. You can customize theisAttributeVisible API to
return false in case the customer wants to hide any IBAs from facet.
Example:
public booleanisAttributeVisible(AttributeTypeIdentifier ibaAttribute){
if(ibaAttribute.getAttributeName().equals("name of attribute")){
return false;
}
return true;
}

Windchill Search Customization 1129


23
Business Logic Customization
Encrypted Passwords ............................................................................................ 1136
Login Page Customization ..................................................................................... 1156
Customizing a Bill of Materials................................................................................ 1158
Customizing Logic for Structure Compare ............................................................... 1160
Context Builder Customization Example.................................................................. 1163
Association Constraints ......................................................................................... 1170
Customizing Multiple Inventory Dispositions ............................................................ 1174
Mass Change Operations ...................................................................................... 1185
Mass Change Supported Types.............................................................................. 1193
Sponsored Problem Reports and Variances ............................................................ 1197
Change Management Cardinality............................................................................ 1200
Change Management Delegate .............................................................................. 1204
Change Management Transitions ........................................................................... 1206
Change Template Initialization Rules ...................................................................... 1210
Replicated Objects as Change Task Resulting Objects............................................. 1213
Evaluating Business Rules On Demand .................................................................. 1219
Editing Attributes on the Links of Change Relationship Tables................................... 1228
Change Workflow Closure...................................................................................... 1243
Flexible Change Links for Query Builder.................................................................. 1253
Customizing Business Rules .................................................................................. 1264
Bypassing Business Rules ..................................................................................... 1284
Loading Business Rule Objects .............................................................................. 1291
Customizing Change Management Workflow Process Templates.............................. 1312
Customizing Promotion Request Workflow Processes.............................................. 1318
Enhanced Promotion Process ................................................................................ 1322
Customizing Workflow Events on an Object............................................................. 1333
Customizing Workflow Task Pages ......................................................................... 1335
Refine and Review Workflow Transitions................................................................. 1359
Adding Custom Workflow Attribute to Workflow Processes ....................................... 1366
Workflow Email Notifications .................................................................................. 1369
Multiple Participant Selection Wizard Customization ................................................ 1374

1131
Customizing Change Activity Workflow Assignments ............................................... 1382
Customizing Change Tables Designed for Workflow................................................. 1392
Locking Annotations In Change Workflows ............................................................. 1398
Customizing the Display of Life Cycle Information .................................................... 1402
Defining Custom Life Cycle Transitions ................................................................... 1404
Setting Up a Customized State-Based Versioning Scheme....................................... 1407
Using a BusinessAlgorithm in a Calculated Attribute ................................................ 1416
Customizing Options and Variants .......................................................................... 1426
Customizing Security Labels .................................................................................. 1432
Custom Publishing ................................................................................................ 1454
Customizing Publishing Queues ............................................................................. 1473
Interference Detection ........................................................................................... 1479
Modifying the Default Behavior of Dynamic Part Generation ..................................... 1487
Report Generation Overview .................................................................................. 1493
Basic Report Example ........................................................................................... 1493
Import and Export of Report Templates ................................................................... 1494
Java Methods ....................................................................................................... 1497
Customization Details ............................................................................................ 1498
Cognos Presentation Customization ....................................................................... 1518
Reporting Info*Engine Task Data Source Customization........................................... 1524
Report Loading ..................................................................................................... 1530
ReportTemplate Data Source Customization ........................................................... 1539
Reporting Input Page Customization....................................................................... 1543
Report Localization Customization.......................................................................... 1548
Report Selection List Customization........................................................................ 1554
Package Type-Based Properties ............................................................................ 1566
Identifying Users in Context Replication and Activating Replicated Users .................. 1580
Select Files – Copy Forward Exclusion Decisions .................................................... 1594
Windchill Replication Package Command Line Sample Scripts ................................. 1597
Add Custom Attributes to Microsoft Office ............................................................... 1600
Customize the Windchill tab in Microsoft Office ........................................................ 1602
Customize Windchill Actions in Windows Explorer ................................................... 1617
Customize the DTI Document Search Window......................................................... 1620
Using DTI with Form-Based Authentication ............................................................. 1621
Customizable Action Item Attributes........................................................................ 1624
Customizing the HTML Client Object Selection Page ............................................... 1630
Customizing Auto Associate................................................................................... 1638
Enabling Support for Custom Parts ......................................................................... 1646
Customizing the Parameters in the Download Service.............................................. 1648
Reservation Service APIs ...................................................................................... 1655
Using the Reservation Service................................................................................ 1655
Using the Reservation Client Tools ......................................................................... 1657
Using the Update Count Client Tools....................................................................... 1658
Adding the Undo Reservation Action to a Menu ....................................................... 1659
Sample Code: Reservation Service ........................................................................ 1660
Product Lifecycle Management Services, Version 2.0............................................... 1662
STEP Data Exchange using EXPRESS .................................................................. 1699

1132 Customization Guide


Custom Windchill Workgroup Manager Requests .................................................... 1884
Creating the Windchill Server-side Customization .................................................... 1890
Pre Operation Customization Hooks for PDM Actions .............................................. 1895
Registering a Custom Event Listener ...................................................................... 1896
CAD Document Structure Publishing to Other Systems ............................................ 1898
Adding a ThingWorx Mashup to Windchill................................................................ 1906
Annonymous Arbortext Access............................................................................... 1922
Customizing Logic to Determine the Default Configuration Specifications .................. 1932

This section contains information on customizing business processes and


functionality in your Windchill system.

Business Logic Customization 1133


24
Encrypted Passwords
Encrypted Passwords ............................................................................................ 1136

This chapter explains how to encrypt passwords currently stored as plain text in a
file.

1135
Encrypted Passwords
Background
Historically, Windchill has stored password values in plain-text in files on a file
system and relied on appropriate access permissions to restrict access to those
files. As of Windchill release 9.1 M050 these passwords can be optionally
encrypted such that the plain-text value is no longer displayed when the file is
viewed.
Windchill provides out of the box property values that can be encrypted. However,
you can encrypt additional values for Windchill .xconf file managed properties, as
well as, values that are not managed by .xconf files.
Once a value is encrypted, code must exist to properly decrypt this value prior to
use or failures likely will result when the encrypted value is used by the system.
If you have created an .xconf property value that is a password or is otherwise
sensitive information, consider encrypting the value. If you have customized code
that extends base Windchill classes or reads Windchill .properties files directly, it
may require updating to ensure proper handling of encrypted values.
For complete details regarding encryption, including the encryption mechanism,
accompanying files, SOX compliance, and more, see the online help topic
“System Password Encryption Options.”

Scope/Applicability/Assumptions
• Assume you have code that adds a new .xconf property for Windchill use
whose value contains sensitive information.
• Assume you have code that adds a property which isn’t managed by the
Windchill xconf framework whose value contains sensitive information.
• Assume you have code that reads Windchill .properties files directly to access
property values.

Intended Outcome
Once a property is encrypted the corresponding value for that property will no
longer appear in plain text and instead, appear in an encrypted form.
For example, one of the out of the box property values that Windchill can
optionally encrypt is the wt.pom.dbPassword .xconf property.
Prior to encryption, in <Windchill>/site.xconf this value appears as:
<Property name="wt.pom.dbPassword" overridable="true" targetFile="db/
db.properties"
value="my_password"/>

1136 Customization Guide


In the underlying <Windchill>/db/db.properties file, this value
appears as:wt.pom.dbPassword=my_password
After encrypting the wt.pom.dbPassword property, each value appear as:
<Property name="wt.pom.dbPassword" overridable="true" targetFile="db/
db.properties"
value="encrypted.wt.pom.dbPassword"/>
wt.pom.dbPassword=encrypted.wt.pom.dbPassword
The encrypted values appear in the form of: “encrypted.<property_name>”.

Solution
Use Windchill’s encryption mechanism to provide a secure means to store
sensitive property value information.
To ensure a standard practice, properties which require encryption should ideally
be xconf managed, using xconfmanager set commands, if able. This ensures an
easier process to encrypt the property. However, there may be design
considerations or architecture issues which prevent the property from being xconf
managed, such as the file not strictly containing key/value pairs or the xconf
framework not being present in the classpath that can influence whether that is
feasible.

Prerequisite knowledge
To apply this best practice, you need to have an understanding of the following:
• Basic development using Java
• Optionally Windchill xconf framework

Solution
To ensure a standard practice, properties which require encryption should ideally
be xconf managed, using xconfmanager set commands, if able. This ensures an
easier process to encrypt the property. However, there may be design
considerations or architecture issues which prevent the property from being xconf
managed, such as the file not strictly containing key/value pairs or the xconf
framework not being present in the classpath that can influence whether that is
feasible.
Use Windchill’s encryption mechanism to provide a secure means to store
sensitive property value information.

Prerequisite Knowledge
To apply this documentation, you need to have an understanding of the following:
• Basic development using Java
• Optionally Windchill xconf framework

Encrypted Passwords 1137


Solution Elements
Element Type Description
WTKeyStore Java Class An interface and API to
the secure location for
encrypted values. This
class can be used to
encrypt and decrypt the
values. See the Javadoc
for the API’s.
This class contains the
primary API to encrypt a
property value and a
secondary means to
decrypt a value.
WTKeyStoreUtil Java Class An interface and API that
provides helper methods
to obtain the
validProperties.list
properties and decrypted
values. See the Javadoc
for the API’s.
This class contains the
primary API used to
determine if a property
value is encrypted and
decrypt it accordingly.
validProperties.list List File The <Windchill>/bin/
adminTools/sip/
validProperties.list file is
a list of Windchill xconf
managed properties
which can be encrypted.
Each property is
contained on a separate
line as is the fully name
of the .xconf managed
property.
This file is how
Windchill’s xconf
framework determines
what properties should be
encrypted. New .xconf

1138 Customization Guide


Element Type Description
managed properties can
be added on a new line in
the file by specifying the
new property name.

Encrypted Passwords 1139


Element Type Description
validIEProperties.list List File The <Windchill>/bin/
adminTools/sip/
validIEProperties.list file
is a list of Windchill
xconf managed properties
which can be encrypted
specific to the use of out-
of-process InfoEngine
adapters installed on a
host separate from
Windchill.
This file should only
contain properties
necessary for out-of-
process IE adapters on a
separate host.
EncryptPasswords.xml XML File The <Windchill>/bin/
adminTools/sip/
EncryptPasswords.xml is
an xml file containing
ANT tasks that provide
administrative utilities for
managing encrypted
passwords and the
securing mechanism.
This file can be used as a
guide to see how to
encrypt non-.xconf
managed properties. You
can examine the
encryptWVSWorker-
Agent and
encryptWVSCADAgent
targets. These targets rely
on WTKeyStoreUtil
methods to encrypt
properties that are not
xconf managed but still
rely on securing the
property values using
Windchills encryption
mechanism.

1140 Customization Guide


Element Type Description
WTKeyStoreUtilWVS Java Class An interface and API that
provides methods to
encrypt WVS CAD and
Worker configuration
passwords.
This class contains code
that can be used as an
example on how to
encrypt non-.xconf
managed properties.

There are two variations of the problem:


1. You want to encrypt and decrypt .xconf managed property values.
2. You want to encrypt and decrypt non-.xconf manager property values.
Each of these uses the encryption and decryption mechanism for various
properties. The difference is that if a property is a single valued managed .xconf
property the xconf framework can be used to set an encrypted value for that
property. If the property is not managed by .xconf files then a secondary means to
encrypt the property needs to be coded.
In both situations, code needs to specifically decrypt the property prior to its use
otherwise the value will likely result in errors and/or failures as the value is
encrypted.

Procedure – Encrypting Static .xconf Managed Single-


Valued Properties
New properties that are xconf managed, have a static property name, that is the
property name never changes, and contain a single value can be encrypted using
the same means that Windchill relies on for the out-of-the-box encryption of these
properties.

Encrypting a Property Value. (This assumes that you have already


created your new .xconf managed property):
1. Edit <Windchill>/bin/adminTools/sip/validProperties.list file and add the
property name to a new line below the last file entry. This tells the encryption
mechanism that this property should be encrypted.
2. From a Windchill shell run xconfmanager to set a value for this property. For
example, <Windchill>/bin/xconfmanager -s <name>=<value>
- p. This will encrypt the “properyValue”. In your site.xconf and
companion .properties file where the value lives you’ll see the encrypted value

Encrypted Passwords 1141


and not the value entered on the command line. The actual value is stored by
Windchill’s encryption mechanism.
You can also encrypt additional .xconf properties that Windchill provides out-of-
the-box if your value for that property is sensitive information. To do so, follow
the above procedure, the only difference is that the property is provided by
Windchill and not created as part of a customization.
Additionally, there is a secondary means to encrypt a password using the
EncryptPasswords.xml file.
1. Edit <Windchill>/bin/adminTools/sip/
validProperties.list file and add the property name to a new line
below the last file entry. This tells the encryption mechanism that this property
should be encrypted.
2. From a Windchill shell, run <Windchill>/bin/adminTools/sip/
EncryptPasswords.xml encryptPw -DpropertyName=
<property> -Dpassword=<password_value>.
3. For additional details see the online topic “System Password Encryption
Options.”
This encrypts the property value. However, for the value to be used properly by
code that relies on the value, the code must be updated to decrypt the value prior
to use. For out-of-the-box properties, Windchill decrypts properties at the
appropriate interface locations.
Any code that relies on this value must be updated to properly decrypt it.

Procedure — Decrypting a Property Value


1. All code that extends Windchill base classes which retrieve property values
must be updated if they overwrite methods that return property values. For
custom code that obtain and use property values you can decrypt an encrypted
value by using the following:
a. com.ptc.windchill.keystore.WTKeyStoreUtil provides an
API to obtain the decrypted value of a property value if it is encrypted (see
the Javadoc for complete details). The API is:
public static String decryptProperty(String property_name,
String property_value,
String product_root)

Where property_name is the property name for which you want to decrypt a
value for, property_value is the value that may currently be encrypted
and product_root is the fully qualified path to <Windchill> (or
<adapater_home> for adapter installations).

1142 Customization Guide


A code example for the usage of this API is as follows:
final String encrypted_value = “encrypted.wt.pom.dbPassword”;
final String property = “wt.pom.dbPassword”;
final String PATH = “D:\ptc\Windchill\”;
String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil.
decryptProperty(property,encrypted_value, PATH);

The string decrypted now contains the decrypted value and can be used
properly elsewhere in the code where it is relied on.

Procedure – Encrypting Dynamic .xconf Managed Single-


Valued Properties
New properties that are xconf managed, have a dynamic property name, that is the
property name changes, and contain a single value can be encrypted using the
same means that Windchill relies on for the out-of-the-box encryption of these
properties.
A dynamic property name could be one that is built on-the-fly in code and relies
on specified derived information such as a hostname for example.
Care must be taken when encrypting a dynamic property. Dynamic property
encryption is based on the use of regular expressions due to the properties
dynamic nature. As a result, the regular expression used to encrypt a property
must ensure that it is restrictive enough to only encrypt those properties which are
intended for encryption. If a too broad regular expression is used an unwanted
consequence is that additional properties could be encrypted with the necessary
decryption code not yet existing.

Encryptring a Property Value


This assumes that you have already created your new .xconf managed property:
1. Edit <Windchill>/bin/adminTools/sip/
validProperties.list file and add the property name token to a new
line below the last file entry. This tells the encryption mechanism that this
property token will be used to encrypt properties matching regular
expressions. For consistency, the property name token should resemble the
regular expression used for matching properties.
2. It is then necessary to add to WTKeyStore.java’s implementation by extending
private Static List<String>
getEncryptionPropertiesRegExList(final String
productRoot) method. This methods implementation generates a
Collection of regular expression used to match property names. If a property
name matches a regular expression the property value is encrypted
accordingly.

Encrypted Passwords 1143


This methods implementation should be overridden through a custom
implementation.
3. There is additional work needed to change the <Windchill>/bin/
adminTools/sip/EncryptPasswords.xml file. Certain Ant targets
within this file validate property name inputs. The -validInput private
target would require updating to also validate the regular expression added in
step 2. The files current implementation can be examined for guidance on how
to accomplish this.

Note
Any code that relies on this value must be updated to properly decrypt it.

Decrypting a Property Value:


1. All code that extends Windchill base classes which retrieve property values
must be updated if they overwrite methods that return property values. For
custom code that obtain and use property values you can decrypt an encrypted
value by using the following:
com.ptc.windchill.keystore.WTKeyStoreUtil provides an API
to obtain the decrypted value of a property value if it is encrypted (see the
Javadoc for complete details). The API is public static String
decryptProperty(String property_name, String property_
value, String product_root).
A code example for the usage of this API is as follows:
final String encrypted_value = “encrypted.wt.federation.
defaultAuthorization.machine123.subnet.net”;

inal String property = “wt.federation.defaultAuthorization.


machine123.subnet.net”;

inal String PATH = “D:\ptc\Windchill\”;

String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil.


decryptProperty(property,encrypted_value, PATH);

1144 Customization Guide


The string decrypted now contains the decrypted value and can be used
properly elsewhere in the code where it is relied on.
Where property_name is the property name for which you want to decrypt a value
for, property_value is the value that may currently be encrypted and product_root
is the fully qualified path to <Windchill> (or <adapater_home> for adapter
installations).

Procedure – Encrypting Non-.xconf Managed Properties


New properties that are non-.xconf managed and contain can be encrypted using
Windchill’s encryption mechanism. However, you must create a means to encrypt
the password as well as decrypt it.

Encrypting a Property Value


1. You must create a means to encrypt your property value. This can be done
through a Java class that can be invoked through a main() method and through
modifying <Windchill>/bin/adminTools/sip/
EncryptPasswords.xml.
a. <Windchill>/bin/adminTools/sip/
EncryptPasswords.xml contains ANT targets,
encryptWVSWorkerAgent and encryptWVSCADAgent, that encrypt
property values that are not xconf managed. These targets can be examined
for an example on how to do this. You must create a new target that
accepts parameters that invokes a Java class to do the encryption.
b. The Java class that is invoked uses the parameters, a property and value,
and encrypts them using the Windchill encryption mechanism. This Java
class must also contain logic to property encrypt the file where this
property is stored as well as placing the correct value in the Java keystore.
The WTKeyStoreUtilWVS.java class contains code that is invoked
by the encryptWCSWorkerAgent and encryptWCSCADAgent
targets which can be examined for an example on the logic used to encrypt
a file where the property value is stored.
This encrypts the property value. However, for the value to be used properly by
code that relies on the value, the code must be updated to decrypt the value prior
to use. For out-of-the-box properties, Windchill decrypts properties at the
appropriate interface locations.

Note
Any code that relies on this value must be updated to properly decrypt it.

Encrypted Passwords 1145


Decrypting a Property Value
All code that extends Windchill base classes which retrieve property values must
be updated if they overwrite methods that return property values. For custom code
that obtain and use property values you can decrypt an encrypted value by using
the following:
com.ptc.windchill.keystore.WTKeyStoreUtil provides an API to
obtain the decrypted value of a property value if it is encrypted (see the Javadoc
for complete details). The API is public static String
decryptProperty(String property_name, String property_
value, String product_root)
Where property_name is the property name for which you want to decrypt a
value for, property_value is the value that may currently be encrypted and
product_root is the fully qualified path to <Windchill> (or <adapater_
home> for adapter installations).
A code example for the usage of this API is as follows:
final String encrypted_value = “encrypted.wt.pom.dbPassword”;

final String property = “wt.pom.dbPassword”;

final String PATH = “D:\ptc\Windchill\”;

String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil.


decryptProperty(property,encrypted_value, PATH);

The string decrypted now contains the decrypted value and can be used properly
elsewhere in the code where it is relied on.

Customization Points
For each solution element whose usage involves the use of parameters, provide a
2nd-level section with a table that describes all of the available parameters. This
can be used for API methods, XML elements, JSP tags, etc. Use the following
template for the table(s):

1146 Customization Guide


WTKeyStore.java API: public WTKeyStore (final String product_root)
Parameter Default Possible Req? Description
Value Values
product_root None String Yes A String that is
the fully
qualified path
to the home
location, either
<Windchill>
or <adapater_
home>

WTKeyStore.java API: public String get(final String key)


Parameter Default Possible Req? Description
Value Values
key None String Yes A String that is
the key used to
retrieve a
value from the
Java keystore

WTKeyStore.java API: public put(final String key, final String value)


Parameter Default Possible Req? Description
Value Values
key None String Yes A String that is
the key used to
retrieve a
value from the
Java keystore
value None String Yes A String that is
the value to
place in the
Java keystore

Encrypted Passwords 1147


WTKeyStore.java API: public String remove(final String key)
Parameter Default Possible Req? Description
Value Values
key None String Yes A String that is
the key for a
value to
remove from
the Java
keystore

WTKeyStoreUtil.java API: public static String decryptProperty(final


String property_value, final String product_root)
Parameter Default Possible Req? Description
Value Values
property_value None String Yes A String that is
a value which
may need
decryption
product_root None String Yes A String that is
the fully
qualified path
to the home
location, either
<Windchill>
or <adapater_
home>

1148 Customization Guide


WTKeyStoreUtil.java API: public static String decryptProperty(final
String property_name, final String property_value, final String
product_root) )
Parameter Default Possible Req? Description
Value Values
property_name None String Yes A String that is
a property
name
property_value None String Yes A String that is
a value which
may need
decryption
product_root None String Yes A String that is
the fully
qualified path
to the home
location, either
<Windchill>
or <adapater_
home>

WTKeyStoreUtil.java API: private static String


getEncryptionPropertiesRegExList(final String product_root)
Parameter Default Possible Req? Description
Value Values
product_root None String Yes A String that is
the fully
qualified path
to the home
location, either
<Windchill>
or <adapater_
home>

Encrypted Passwords 1149


EncryptPasswords.xml API: run Ant -f EncryptPasswords.xml
-projecthelp to see the full list of available commands and usage.
Parameter Default Possible Req? Description
Value Values
wt.home env.WT_ String No A String that is
HOME the fully
env.wt_home qualified path
to the home
../../../. location, either
The value <wt_home>
defaults to or <adapater_
environment home>.
variable WT_
HOME, then
wt_home, and
finally the
canonical path
../../../.

Limitations
The properties that are encrypted need to be accessible from the server side as the
encryption mechanism relies on a location that is not web accessible from a client
for security purposes. There is minimal performance overhead for encrypting and
decrypting a property. However, it should be noted that the underlying
implementation of the Java keystore relies on a singleton pattern and access to the
keystore is synchronized.

Sample Code
Creating a Java keystore for Windchill to encrypt values:
try
{
WTKeyStore keyStore = new
WTKeyStore(WTProperties.getLocalProperties().
getProperty("wt.home"));

}catch(IOException e){
logger.error("Could not load keystore", e);
}

Encrypting a value in the keystore:


String value = “encrypted.wt.pom.dbPassword”;
String property = “wt.pom.dbPassword”;

1150 Customization Guide


try
{
WTKeyStore keyStore = new
WTKeyStore(WTProperties.getLocalProperties().
getProperty("wt.home"));

// encrypt property value


keyStore.put(property, value);

} catch (IOException ioe) {


logger.error("Error creating keystore: ", ioe);
} catch (NullPointerException npe) {
logger.error("Could not add the encrypted value to the
keystore: ", npe);
}

Decrypting a property:
String product_root = WTProperties.getLocalProperties().
getProperty(“wt.home”);
String value = “encrypted.wt.pom.dbPassword”;
String property = “wt.pom.dbPassword”;
// decrypt encrypted values
value = WTKeyStoreUtil.decryptProperty(property, value, product_root);

/* value can now be used as normal as it will contain the decrypted value */

Additionally, a secondary means can be used to decrypt a value:


String value = “encrypted.wt.pom.dbPassword”;
try
{
WTKeyStore keyStore = new
WTKeyStore(WTProperties.getLocalProperties().
getProperty("wt.home"));

// decrypt encrypted values


String ks_value = keyStore.get(value);
if(ks_value != null)
{
value = ks_value;
}
}catch(IOException e){
logger.error("Could not load keystore", e);
}

Adding a new regular expression for encrypting dynamic properties:


/* This code currently exists in WTKeystoreUtil.java. except where
* where denoted “NEW”

Encrypted Passwords 1151


*/
private static final String NEW_REGULAR_EXPRESSION = “<your regular
expression goes here>”; // NEW

private static List<String> getEncryptionPropertiesRegExList(final


String product_root) {
List<String> propertiesList = new ArrayList<String>();

if(isCompletePropertiesListFile(product_root)) {
/*
* add a hardcoded list of dynamic properties that will
* utilize regular expressions to determine what to encrypt
* for dynamic property names.
*/
propertiesList.add(WT_FEDERATION_DEFAULTAUTHORIZATION);
propertiesList.add(NEW_REGULAR_EXPRESSION); // NEW

logger.debug("Full property list found, returning regex


list of size=" + propertiesList.size());
} else {
logger.debug("Full property list not found, return empty
regex list");
}
return propertiesList;
}

This will add a new regular expression for matching property name patterns.
Again, care must be taken when creating a regular expression. See Procedure –
Encrypting Dynamic .xconf Managed Single-Valued Properties on page 1143.

Examples of Usage in Windchill Code


• wt.dataservice.DSPropertiesServer.java
This Java class works with DSProperties.java to decrypt property values that
appear encrypted. This class uses reflection to ensure that the
DSPropertiesServer exists on the server and not the client side.
• com.ptc.wvs.server.cadagent.Inifile.java
This Java class implements a means to decrypt properties that are not .xconf
file managed properties.
• com.ptc.windchill.keystore.WTKeyStoreUtilWVS.java
This Java class implements a means to encrypt properties that are not .xconf
file managed properties.
• com.ptc.windchill.keystore.WTKeyStoreUtil.java

1152 Customization Guide


This Java class implements a means to encrypt dynamic properties that are.
xconf file managed properties.

Encrypted Passwords 1153


25
Customizing the Login Page
Login Page Customization ..................................................................................... 1156

This chapter contains information on customizing the login page.

1155
Login Page Customization
You can customize the login page following the existing instructions. See
Configuring an Alternative Authentication in Windchill for more information. The
logout page is controlled by the wt.property wt.logout.url.
Specify the wt.property, wt.auth.form.loginMarker to include a
unique string that is contained in the login page. This will allow background Ajax
data requests to automatically show the login window when the session has timed
out.
For example:
wt.auth.form.loginMarker=<form method="POST" action="j_security_check" id="login">

For better URL handling, it is recommended that you include the following code
to the login page so that newer browsers will not drop the hash token that specifies
the state of the application.
<script type="text/javascript">
if (window.location.hash) { //Handle logging in to a bookmark
document.forms[0].action += window.location.hash;
}
</script>
To customize the appearance and behavior of the login window, the window
object can be pre-populated during page load with a custom SmartClient window
instance. You can use the example from the SmartClient documentation or modify
the one provided by PTC out-of-the-box:
isc.RPCManager.loginWindow = isc.Dialog.create({
src: 'app/login/loginSuccess.jsp?ptscsc=true',
showModalMask: true,
isModal: true,
title: "",
autoCenter: true,
showCloseButton: false,
showMinimizeButton: false,
width: 400,
height: 350
});

1156 Customization Guide


26
Customizing Business Logic
Customizing a Bill of Materials................................................................................ 1158
Customizing Logic for Structure Compare ............................................................... 1160
Context Builder Customization Example.................................................................. 1163

This chapter describes how to customize business logic.

1157
Customizing a Bill of Materials
A Bill of Materials (BOM) is a product structure report that identifies the items
required to assemble a product. Currently, the BOM report includes only items
from a part structure. Two types of BOMs are supported.
• A BOM Hierarchy report shows the quantity and unit attributes of the "usage"
associations and visually indicates the hierarchical levels.
• A Parts List report is a list of all of the components (that is, parts that do not
use other parts) in the part structure hierarchy. It uses information in the
"usage" associations to determine the quantity of each component. Basically, it
answers the question "When a part assembly is completely disassembled, what
parts and how many of each do I have?".
Both of these reports are defined to be generated as an HTML page optimized for
printing from a Web browser.

Customizing Existing Reports


Global attributes on parts are displayed in the BOM reports automatically using
the table view, but global attributes on part usage links cannot be displayed
automatically. The global attributes on the part usage link are shown in the list of
available columns, but to get the actual value to display, the corresponding report
configuration class needs to be extended to indicate the specific global attributes
from the part usage link to display.
As an example, if a global attribute "LinkName" was added to part usage link,
the values of that attribute can be displayed in the Multi-level BOM Report by
1. Creating an extension of the MultiLevelBOMReportTreeBuilder
class similar to the following
@ComponentBuilder("part.report.multiLevelBOM")
public class MultiLevelBOMReportTreeBuilderCustomAtts extends
MultiLevelBOMReportTreeBuilder {

@Override
public ComponentConfig buildComponentConfig(ComponentParams params)
throws WTException {
ComponentConfig tableConfig = super.buildComponentConfig(params);
ComponentConfigFactory factory = getComponentConfigFactory();

String columnLabel = "Custom column name";


ColumnConfig col = factory.newColumnConfig("IBA|LinkName", columnLabel, true);
col.setDataUtilityId("part.report.numberText");
col.setTargetObject("link");

1158 Customization Guide


tableConfig.addComponent(col);

return tableConfig;
}

}
2. Register the custom ComponentBuilder in the <Windchill>/
codebase/config/mvc/PartReport-configs.xml file
• Add the line
<bean class="custom.MultiLevelBOMReportTreeBuilderCustomAtts"/>
• And remove the line
<bean class="com.ptc.windchill.enterprise.part.reports.mvc.builders.
MultiLevelBOMReportTreeBuilder"/>
3. Set up a custom table view with that column as one of the selected columns.

Customizing Business Logic 1159


Customizing Logic for Structure Compare

Note
For a general overview of comparing structures, see the “Comparing
Structures” online help topic in the Windchill Help Center.

This information applies to the following applications:


• Compare to Part Structure
• Compare to Part Configuration Structure
• Compare to Part Instance Structure
In these applications, a matching process is used to determine whether two objects
will line up on the same row. This matching is often done based on properties of
link objects between parent and child. Utilizing properties on the parent or child
are also possible.
For two parents that are matching, one on the left and one on the right, each link
under the left parent is matched against each link under the right parent to find a
comparison precedence. A lower precedence means a stronger match. A
precedence of “0” means the links match completely, and a negative precedence
means the links do not match.
A matcher is configured to match on one link object type. Therefore, it is possible
to customize matching logic for different link object types.
It is important to note that the matchEdges() method is called many times
during the matching process, so the method must be highly performant, otherwise
serious performance degradations will occur.
Customizing matching logic is a two-step process.
1. Implement a custom matcher. For example:
public class DSBCustomMatcherWTPartUsageLink extends DSBAbstractMatcher {
@Override
public int matchEdges(DSBEdge sourceEdge, DSBEdge targetEdge) {
// Custom matching logic
...
// Example of gathering required attributes
Object sourceFindNumber = sourceEdge.getEdgeInfo()
.getAttribute(PLMEntity.FIND_NUMBER.getAttribute());
Object targetQuantityAmount = targetEdge.getEdgeInfo()
.getAttribute(PLMEntity.QUANTITY_AMOUNT.getAttribute());
Object sourceVersion = sourceEdge.getChild()
.getNodeInfo().getAttribute(PLMEntity.VERSION.getAttribute());
...
}
@Override

1160 Customization Guide


public List<Attribute> initRequiredEdgeAttributes() {
// Edge attributes required for matching
// If no attributes are required for matching, return null
return Arrays.asList(new Attribute[]{
PLMEntity.FIND_NUMBER,
PLMEntity.QUANTITY_AMOUNT
});
}
@Override
public List<Attribute> initRequiredNodeAttributes() {
// Node attributes required for matching
// If no attributes are required for matching, return null
return Arrays.asList(new Attribute[]{
PLMEntity.VERSION
});
}
}
2. Add an entry in the appropriate xconf file linking the custom matcher to a
link type. For example:
<Service context="default" name="com.ptc.windchill.enterprise.dsb.server
.graph.matcher.DSBAbstractMatcher">
<Option cardinality="singleton" selector="wt.part.WTPartUsageLink"
requestor="null" serviceClass="com.ptc.windchill.enterprise.dsb.server
.graph.matcher.DSBCustomMatcherWTPartUsageLink"/>
</Service>

Example
This is an example for how to convert a custom matcher.
public class CustomDSBGraphProcessorDelegate extends DSBAbstractMatcher {
@Override
public int matchEdges(DSBEdge sourceEdge, DSBEdge targetEdge) {
// Custom matching logic
}
@Override
public List<Attribute> initRequiredEdgeAttributes() {
// Edge attributes required for matching
}
@Override
public List<Attribute> initRequiredNodeAttributes() {
// Node attributes required for matching
}
}
To use your own delegate, you can specify the following in
service.properties:
<Service context="default" name="com.ptc.windchill.enterprise.dsb.server
.graph.matcher.DSBAbstractMatcher">
<Option cardinality="singleton" selector="wt.part.WTPartUsageLink"
requestor="null" serviceClass="com.ptc.windchill.enterprise.dsb.server

Customizing Business Logic 1161


.graph.matcher.CustomDSBGraphProcessorDelegate"/>
</Service>

Changes in Logic from Previous Releases


The process for creating custom matching logic for compare applications has
changed in Windchill 10.1 M010.
There are four notable changes:
1. Custom matchers no longer implement DSBGraphProcessorDelegate
and ApplicationContextChild. Custom matchers only need to extend
DSBAbstractMatcher.
2. The method getRootSummaryStatusFlags() has been removed.
3. The methods initRequiredEdgeAttributes() and
initRequiredNodeAttributes() have been added.
4. A matcher is now configured to match on one link object type.

1162 Customization Guide


Context Builder Customization Example
Enabling the example
To enable the Context Builder customization example:
1. Add the following entry to <Windchill>/declarations.xconf :
<ConfigurationRef xlink:href="codebase/com/ptc/
windchill/enterprise/contextbuilder/
ContextBuilderCustom.xconf"/>
2. Save the change.
3. Exectue the following command: xconfmanager -p
4. Restart the MethodServer.
5. Navigate to the Edit Definition tab, there will be two example Context Builder
extension actions.

When the xconfmanager propagates the changes, an actions.xml file will be


added to the list of actions.xml files read by the actions framework. The
wt.properties property
“com.ptc.netmarkets.util.misc.defaultActions” is the property
that the actions framework reads to determine the set of available actions. The
specific actions xml file that defines the custom action that can be exposed in
the CAR Context Builder is <Windchill>/codebase/config/actions/
contextbuildercustom-actions.xml.
There are four example actions in the contextbuildercustom-
actions.xml file that show how multiple actions can be added to the CAR
Context Builder. There are two actions exposed on the Rules tab toolbar and two
actions exposed on the right click menu of the top level node of the tree. All
entries look similar to this example:
<action name="editIncludeExcludeRulesGWT">
<command class=
"com.ptc.windchill.enterprise.object.alternaterep.client.

Customizing Business Logic 1163


action.CustomFilterRuleAction" />
<url=”Windchill/netmarkets/jsp/contexbuildercustom/customFilterRulesPopup.jsp
</action>
The key to hooking into the Context Builder application is to use the
com.ptc.windchill.enterprise.object.alternaterep.clien
t.action.CustomFilterRuleAction as the command class. This takes
care of appending the CB_CCID and CB_SEEDID query string parameters to the
URL used to launch the custom application. It also makes some javascript API’s
available to the custom application to take care of updating the checkboxes in the
tree when the custom application has finished and is ready to create rules. The url
of the action should be set to point to the resource that provides the custom
functionality. In the example provided by PTC it points to a
customFilterRulesPopup.jsp.
When a Context Builder extension action is selected, a window will be launched
and the resource pointed to by the URL will be loaded in it.

1164 Customization Guide


API’s Available for Custom Filter Applications
Server side API available to navigate the Design Context Structure
public interface ContextBuilderInterface {

public Collection<CBStructureNode>
getChildrenFromCache(String collectorCacheID,
Collection<String> seeds, HttpServletRequest request) throws
InvalidCollectorCacheException, InvalidCollectorSeedException,
CollectionException;
}
The inputs to the API are:
• Collector Cache ID (String): This is the parameter passed to the custom filter
application in the URL when the custom filter application is launched (CB_
CCID parameter)
• Seeds/Collection of components to traverse (Collection of Strings) : For the
first call, this should contain the id passed to the custom filter application in
the URL when the custom filter application is launched (CB_SEEDID), for
subsequent calls, the collection should contain the ids of the components
returned from previous call that need to be traversed further to get to the CAD
modules – when all CAD modules are retrieved, then this API should not be
called anymore.
• Request : As the customization may execute within the context of a separate
web app, the HTTP request object needs to be passed in as input to the
Context Builder API such that Windchill picks up the authenticated user, the
user locale, HTTP session specific data, etc to establish the appropriate
context for the execution of this API. If the request object is null, then it is
assumed that no initialization of context is required.
The output of this API is:
• A collection of CBStructureNode : This object would contain a child
component id (string), the child Persistable object, a link id (string), the link
Persistable object (between parent and child), the parent id (string), a string
representing the path of that component in the structure and its inclusion status
For each combination of child component id + path we would have a
CBStructureNode object
Exceptions may be thrown in the following situations:

Customizing Business Logic 1165


• InvalidCollectorCacheException - collector cache id is no longer
valid
• InvalidCollectorSeedException - seed object(s) passed are invalid
(we cannot refresh them)
• CollectionException - collection exception
These exceptions are extensions of WTException; therefore in any error case
mentioned above localized error messages will be returned in them.
The caller of this API should also be prepared to deal with runtime exceptions (db
unavailable, etc).
This API will not return items that are filtered by Expansion Criteria filters (those
items are not displayed in the context builder tree and would not be available to
this API).
This API will return the link and child identifiers and Persistable objects. It is up
to the invoker API to then use other services to acquire additional information
about the object using other APIs (info engine or other Windchill supported APIs)
if not available in the Persistable objects (for example, reusable attributes would
not be available from the Persistable objects). This API will not return any
information about the level of representation selected for each item in the
structure.
The identifier returned in the CBStructureNode object will be of the form:
OR:<object class>:<number>

Server Side API Available to Update the Context Builder Cache


public interface ContextBuilderInterface {

public String addRulesToCache(String collectorCacheID, String seedId,


List<CBPath> nodesToUpdate, HttpServletRequest request) throws WTException;
}
The following are the inputs to this API:
• Collector Cache ID – This is the parameter passed to the custom filter
application in the URL when the custom filter application is launched (CB_
CCID parameter)
• Seed ID – This is the parameter passed to the custom filter application in the
URL when the custom filter application is launched (CB_SEEDID parameter)
• List of CBPath items for which we should add new inclusion/exclusion rules
– this List should include the CBPath items that have been modified by user –
for items not modified, they should not be passed in. The reason why
CBPath’s are passed to this API instead of CBStructrueNodes is because, for
creation of rules, only the information in CBPath’s is required. To create an
instance of a CBPath using the path identifier (that was given to the custom

1166 Customization Guide


filter application in the CBStructureNode objects) and an inclusion value,
please use the CBPathFactory.
Please note that instead of a Collection, a List is passed to this API – if for some
reason, the order of inclusions for paths is important, then it is up to the invoker of
the API to pass the CBPaths in appropriate order for creation – the order in which
rules are created can potentially modify the end result of inclusions in the context.
In addition, it is up to the application to decide how to handle multiple paths to
same component (if all should be set to same inclusion status or not).
• Request – As the customization may execute within the context of a separate
web app, the HTTP request object needs to be passed in as input to the
Context Builder API such that Windchill picks up the authenticated user, the
user locale, HTTP session specific data, etc to establish the appropriate
context for the execution of this API. If the request object is null, then it is
assumed that no initialization of context is required.
As output, this API will:
• On failure, an exception will be returned – the exception will have a localized
message with information about the failure.
• On success, this API will provide as output a string that has a token that is to
be used by client Context Builder to refresh the screen after the custom filter
UI is dismissed (the tree, visualization and rules panel would be updated
accordingly).
This API will add rules for the paths passed in (according to the inclusion state
passed in) at the bottom of the rules list of the associated context. For CAR’s, the
representation will be set based on the preference value in the system.

Client side API to Hand Over Control to Context Builder on Success of


Custom Filtering
On success of the custom filter application, the custom filter application should
hand over control to the context builder and should request it to refresh itself.
When called to refresh, the custom builder will close the custom filter application
and should go to server (by using token passed by API defined in previous
section) to get the data to be refreshed in the Context Builder application.
After refresh is done, the modal mode should be dismissed in the Context Builder
application and should be fully functional again for the user.
The following API is available to the custom filter application to hand over
control to the context builder application (this is a JavaScript API)
opener.CB.refreshContextBuilderForCustomFilter(token);
Where the input to this API is:

Customizing Business Logic 1167


• Token – This is the string returned by the addRulesToCache API defined in
previous section – this is a required input and the API will fail if no token is
passed.
This API does not produce any output (void call).

Client side API to Cancel Custom Filter


When the custom filter window is closed, a JavaScript API should be called on the
opener window (the Context Builder window) to reset the modal mode.
This API should be invoked when a cancel button is pressed on the custom filter
window or when the custom filter window is “unloaded” (closed by pressing the
“X” button on the browser window).
The API should be called in the following way:
opener.CB.closeCustomFilterWindow();

This API does not produce any output (void call).

1168 Customization Guide


27
Customizing Change Management
Association Constraints ......................................................................................... 1170
Customizing Multiple Inventory Dispositions ............................................................ 1174
Mass Change Operations ...................................................................................... 1185
Mass Change Supported Types.............................................................................. 1193
Sponsored Problem Reports and Variances ............................................................ 1197
Change Management Cardinality............................................................................ 1200
Change Management Delegate .............................................................................. 1204
Change Management Transitions ........................................................................... 1206
Change Template Initialization Rules ...................................................................... 1210
Replicated Objects as Change Task Resulting Objects............................................. 1213
Evaluating Business Rules On Demand .................................................................. 1219
Editing Attributes on the Links of Change Relationship Tables................................... 1228
Change Workflow Closure...................................................................................... 1243
Flexible Change Links for Query Builder.................................................................. 1253

This chapter describes how to customize change management.

1169
Association Constraints
This section explains how to create association constraints within change
management.

Background
Association constraints can now be created for restricting the types of affected and
resulting objects that can be associated to a change object. The association links
for the affected and resulting objects are now typed which will allow for creating
multiple subtypes of the links.
This means that a change object type X can be constrained for using a particular
type of affected data, while a different change object type Y can be constrained
using an entirely different soft-type link of affected data. By default, no
constraints are defined against any of the change objects and their affected or
resulting links. When no constraints are defined, all supported changeable objects
can be associated to affected or resulting object tables.
Association constraints might be used if you have multiple types of change objects
for different purposes. For example a Publications Request is used for processing
a change request for documents. In this case an association constraint could be
created for the change request “Publications Request” and documents, that only
allow users the ability to associate documents and no other objects to the affected
objects of Publications Requests. All supported objects types in the affected
objects table for the base type change request would still be allowed.

Scope/Applicability/Assumptions
• Assumes you have used the type manager and created constraints.
• General Knowledge of the change objects and the role they play in the change
process.

Intended Outcome
The expected results of applying this solution will be that affected and resulting
objects can be constrained to particular types for a specified change object type.

1170 Customization Guide


Solution
Use the Type Manager to constrain the types of objects that can be associated in
the affected and resulting objects tables associated to the change object.

Prerequisite Knowledge
To perform this task, you must have an understanding of the following:
• Using the Type Manager and creating association constraints.
• Basic Knowledge of the change objects and the role they play in the change
process.
The section below includes references to many or all of these subjects.

Solution Elements
Element Type Description
wt.change2.ReportedA Link The link class for associating
gainst class affected objects on a Problem
Report or Variance
wt.change2.RelevantRe Link The link class for associating
questData2 class affected objects on a Change
Request

Customizing Change Management 1171


Element Type Description
wt.change2.AffectedAc Link The link class for associating
tivityData class affected objects on a Change Task
wt.change2.ChangeRe Link The link class for associating
cord2 class resulting objects on a Change Task
wt.change2.HangingChan Link The link class for associating
geLink class hanging changes on the resulting
objects of a Change Task
StandardardChangeSer Default The default implementation of the
vice change change service for creating,
service updating, deleting for change
objects and associations.
Package: wt.change2
ChangeMgmtConstrain Helper A helper class for managing
tHelper class constraints within change.
Package: wt.change2.constraints

When defining the association constraint the Change Object type is the driver for
what relationship link is used. The
ChangeService2.storeAssociations will derive the correct link type
given the Change Object and the base link class and update the link to use the
right type for the defined constraint.

Customization Points
The change wizard form delegates and processes will create the links
automatically for the defined constraint link type. Typical use cases to customize
the creation of the links may be due to adding additional attributes on the link or
customized processing of change. When customizing the creation of the affected
or resulting links the following order should be followed:
1. The new link object should be created.
2. Any attributes should be initialized with the default or user entered values
3. The change service store association service should be called.
• For details on the steps for creating new associations see the javadoc for
StandardardChangeService.storeAssociations(ChangeIte
mIfc, WTCollection) and ChangeMgmtConstraintHelper.
• Prior to setting subtype attributes on a subtype link the type definition
reference needs to be set. To set the type definition reference, see the javadoc
for

1172 Customization Guide


ChangeMgmtConstraintHelper.getTypeDefinitionReferen
ce(Class, ChangeItemIfc).

Limitations
Only one constraint can be defined per Change Object and a relationship link. For
example if a constraint is defined for a Problem Report base type and
wt.change2.ReportedAgainst link then another constraint for the
Problem Report base type and a subtype of wt.change2.ReportedAgainst
link cannot be created. However, another constraint can be defined for a Problem
Report subtype and wt.change2.ReportedAgainst or subtype link even
though a constraint has already been defined for the Problem Report base type.
It is very easy to define constraints which may severely limit the ability of users to
be flexible in their associations to changes. Before establishing new constraints on
the links, careful examination of the roles of the users in the change process
should be conducted and the rules should be as “open” as possible (as opposed to
as “constrained” as possible).

Customizing Change Management 1173


Customizing Multiple Inventory
Dispositions
This section contains information on customizing Multiple Inventory Dispositions
on the AffectedActivityData link.

Background
As of the Windchill 10.0 release, Multiple Inventory Dispositions on the
AffectedActivityData Link shall be available OOTB. This document
details steps on how to customize Multiple Inventory dispositions by;
• Adding new inventory disposition types
• Adding new inventory disposition values to be used by inventory disposition
types
• Setting a default disposition value.

Scope/Applicability/Assumptions
The action to set inventory dispositions is exposed on the toolbar or on the actions
menu drop-down of the Affected Objects table in the create/edit Change Task
wizard. It is assumed that you have the ability to navigate to that table.
New inventory disposition values can be added using Enumerated Type
Customization Utility (enumCustomize tool). It is assumed you have the basic
knowledge on how to use the tool, if you are not familiar with the tool see The
Enumerated Type Customization Utility on page 1981 for more information.
• Use the Enumerated Type Customization Utility(enumCustomize tool) to
introduce new inventory disposition values for use in the inventory disposition
types
• Use the Enumerated Type Customization Utility(enumCustomize tool) to
specify a default inventory disposition value
• Use the Type and Attribute Management utility to introduce new types of
inventory dispositions.

Intended Outcome

○ You shall be able to introduce new inventory disposition values
○ You shall be able to specify a default inventory disposition value

1174 Customization Guide


○ You shall be able to introduce new types of inventory disposition types

Solution
Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:
• Basic knowledge of change management process
• The management of RBINFO files customizations
• Basic knowledge on how to use the new Windchill Release 10.0 Type and
Attribute Management utility
• Java Language

Solution Elements
Element Type Description
inventory rbInfo Contains the master list of
DispositionRB inventory disposition
.rbInfo values.
Runtime location:
<Windchill>\src
\wt\change2
change2Client Class Resource bundle for
Resource.java inventory disposition
types
Runtime location:
<Windchill>\
srclib\wnc\Change
Management.jar
AffectedActivity XML Loader for
Data.xml AffectedActivityData
Link. Contains OOTB
dispositions and their
values.
Runtime location:
<Windchill>\
loadFiles\type\
standardX20.dtd DTD DTD for disposition
elements
Runtime location:
<Windchill>\
loadXMLFiles

Customizing Change Management 1175


Element Type Description
Coreobjects.dtd DTD The IXB DTD for
disposition elements
Runtime location:
<Windchill>\
codebase\registry
\ixb\dtds
\standardX20.dtd
AffectedActivity Java class OOTB link class
Data.java Runtime location:
<Windchill>
\srclib\wnc\
Foundation.jar
DefaultDisposit Class Default disposition
ionHandler.java handler. You will need to
extend this handler or
implement
DispositionHandler
Interface.
Runtime location:
<Windchill>
\srclib\wnc
\Change
Management.jar
Disposition Interface If not extending
Handler.java DefaultDispositionHan-
dler, implement this
interface.
Runtime location:
<Windchill>
\srclib\wnc\
Change
Management.jar
ChangeTask Class Contain configurable
AffectedItems views for affected items
TableViews table
.java Runtime location:
<Windchill>
\srclib\wnc\
Change
Management.jar

1176 Customization Guide


Element Type Description
AffectedItems Class Builder for affected items
TableBuilder.java table
Runtime location:
<Windchill>
\srclib\wnc\
Change
Management.jar
ChangeManag XML Defines actions related to
ement-actions.xml inventory dispositions
Runtime location:
<Windchill>
\codebase\config\
actions
Disposition Class Sets the value of an
DataUtility.java inventory disposition type
which is a column in the
affected items table
Runtime location:
<Windchill>
\srclib\wnc\
Change
Management.jar
Change xconf Links the disposition
Management- handler with inventory
service.proper disposition types
ties Runtime location:
.xconf <Windchill>
\codebase\
service.proper
ties

Customizing Change Management 1177


Element Type Description
ChangeManagement- xconf This is where to register
components.data the data utilities
Utilities. Runtime location:
properties <Windchill>
.xconf \codebase\com\
ptc\
core\components\
components.data
Utilities
.properties
ChangeManag XML This where the builder is
ement-configs.xml registered so the MVC
framework can find it.
Runtime location:
<Windchill>
\codebase\config
\mvc

Customization Points
Introducing New Values for Use in the Disposition Types
Out-of-the-box (OOTB) inventory disposition attribute values are fixed lists of
values. If you want to customize an available OOTB disposition type by adding a
new entry you must define an entry in the
InventoryDispositionRB.rbinfo file.
The InventoryDispositionRB.rbinfo file contains a fixed set of master
lists of inventory disposition values. To add an entry in the
InventoryDispositionRB.rbinfo file, use the enumCustomize tool
to edit the file. See The Enumerated Type Customization Utility on page 1981 for
more information.
After you have customized the disposition type, use the Type and Attribute
Management utility. On the affected Activity Data Type, select the disposition
attribute and edit the Enumerated Value List from the Constraints tab

Specifying a Default Value for Disposition


Use enumCustomize tool to select a default disposition value. See The
Enumerated Type Customization Utility on page 1981 for more information.
If the default disposition value is not added to the constraint set of an inventory
disposition type, a blank shall be shown as the preselected value in the inventory
disposition UI drop down

1178 Customization Guide


Adding New Disposition Types
Inventory disposition types are enumerated columns that are added to the
AffectedActivityData Link. There are inventory dispositions types that
are added OOTB; customizers can add more inventory disposition types as global
attributes on the AffectedActivityData Link to meet their business needs
by using the Type Manager. Here are the steps to follow
1. Extend AffectedItemsTableBuilder and Override
getDispositionComponentIds API to account for your new inventory
disposition types. Also, if you decide to extend
ChangeTaskAffectedItemsTableViews as opposed to just changing
it, then you will need to override buildConfigurationTable to return
your new table views.
@ComponentBuilder("changeTask.affectedItemsTable")
public class YourNewTableBuilder extends AffectedItemsTableBuilder {
/**
* Returns the list of supported disposition types.
*/@Override
public List <String> getDispositionComponentIds() {

/**
* Returns the configurable table.
*/@Override
public ConfigurableTable buildConfigurableTable(String id) throws
WTException {
}
}
2. Register your builder.
The builder will be discovered dynamically by the MVC framework. In order
for the framework to find your builder, you will need to register either the base
package location of the builder or the builder class in the xml configuration
file under the mvc package in the src_web variant. Here is an example for
AffectedItemsTableBuilder as registered in
ChangeManagement-configs.xml.
• To register the base builder package. Add this to the xml configuration file:
<mvc:builder-scan base-package="com.ptc.windchill.enterprise.
change2.mvc.builders"/>

• Or register the builder class. Add this to the xml configuration file:
<bean class=" com.ptc.windchill.enterprise.change2.mvc.builders.tables.
AffectedItemsTableBuilder "/>

Customizing Change Management 1179


3. The @ComponentBuilder annotation connects the builder with other
components in the system such as JSP’s. The string you put in the
@ComponentBuilder(“changeTask.affectedItemsTable “)
annotation in the builder must be the same builder ID you include in the JSP.
For example affectedItemsTable.jsp has the following to request the
change task affected item component.
<jsp:include
page="${mvc:getComponentURL('changeTask.affectedItemsTable')}"/>
4. Extend ChangeTaskAffectedItemsTableViews to add your new
inventory disposition types to the link
public class YourTableViews extends ChangeTaskAffectedItemsTableViews
{
/**
* Get the disposition columns
*/
@Override
public List <?> getSpecialTableColumnsAttrDefinition(Locale locale) {
}
}
5. Extend DefaultDispositionHandler to get/set the values of your new
inventory disposition types. At a minimum, you will need to override the
API’s given below:
public class YourNewDispositionHandler extends DefaultDispositionHandler {

/**
* Get disposition value for a given disposition type.
*/
@Override
public InventoryDisposition getDispositionValue(String componentId,
BinaryLink link) {

/**
* Set the disposition value for a given disposition type. */
@Override
public boolean setDispositionValue(String componentId, BinaryLink link,
InventoryDisposition disposition) throws WTException {

/**
* Get the default disposition value for a given disposition type
*/
@Override

1180 Customization Guide


public InventoryDisposition getDefaultInventoryDisposition(
ChangeLinkAttributeBean
linkBean, String component_id) {

/**
* Get the disposition value set of a given disposition type
*/
@Override
public ArrayList <InventoryDisposition> getInventoryDispositionSet
(ChangeLinkAttributeBean
linkBean, String component_id) {

}
}
6. Register your new disposition handler in the service properties file
(ChangeManagement-service.properties.xconf). The selector
attribute is your new inventory disposition type and the serviceClass is
your new disposition handler.
<! -- Handler for processing the disposition types -->
<Service context="default" name="com.ptc.windchill.enterprise.change2.
handler.DispositionHandler"><Option serviceClass="com.ptc.
windchill.enterprise.
change2.handler.YourNewDispositionHandler"
selector="YourNewDispositionType"
requestor="null"
cardinality="duplicate"/>
</Service>
7. Register your disposition types against DispositionDataUtility. You
may also choose to extend DispositionDataUtility to meet your
business need. The service property file to register the dispositions is
ChangeManagement-
components.dataUtilities.properties.xconf.
For example:
<Option serviceClass="com.ptc.windchill.enterprise.change2.
dataUtilities.DispositionDataUtility"
requestor="java.lang.Object"
selector="YourNewDisposition"
cardinality="duplicate"/>

Customizing Change Management 1181


Customizing through the UI
1. As the site administrator, go to Type Manager and create a new global attribute
for AffectedActivityData Link, this is the inventory disposition type

2. Constrain the attribute to the new disposition values you created in


Introducing New Values for Use in the Disposition Types on page 1178.

1182 Customization Guide


3. Now that we have configured multiple disposition types and values, it is time
to create an instance of multiple dispositions on the
AffectedActivityData link.
• Create a change notice and update the default change task by going to
“Select Affected/Resulting Objects” step
• Your new disposition type(s) should show as column(s) on the affected
objects table
• The drop-down under your new disposition type (column) should show
your new disposition values constrained to that type
• To change the disposition values for a disposition type, click Actions drop-
down and select “Set Dispositions”

Customizing Change Management 1183


1184 Customization Guide
Mass Change Operations
You want to understand how to add or modify mass change operations. The
expectation is that you are able to add new Mass Change operations and extend
processing of existing Mass Change operations.

Background
As a customizer you may want to add additional operations for use in the mass
change wizard. For example, to create a new operation for a custom association
and/or object type. You also may want to extend existing mass change operations
to insert additional processing validation. For example, to validate that the
revisions are all at a RELEASED state prior to performing the Insert Existing Part
operation.

Scope/Applicability/Assumptions
Performing this task assumes pre-existing knowledge of:
• Java
• Creating JSPs
• actions.xml
• Updating properties

Solution
Register filter delegates for processing new or existing operations. Create new
actions, properties, and JSP for new operations.

Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:
• Basic development involving Java HTML forms, JSP, and XML.
• The actions framework in the Windchill client architecture
• The management of RBINFO file
• Xconfmanager, wt.poperties and service.properties.

Customizing Change Management 1185


Solution Elements
Element Type Description
com.ptc.windchill Class A filter delegate is used
.enterprise.mass for the mass change client
Change.filters. to filter out objects
MassChangeFilter selected by the user that
Delegate are ineligible for a
specific mass change
operation. Using the
filtered list of eligible
objects the filter delegate
then creates, modifies, or
deletes associations for
the selected mass change
operation. If an object is
ineligible for the selected
mass change operation,
the ineligible object will
not be processed
config/actions/ XML Location for registering
MassChange- operations and associated
actions.xml filter delegates.
service. properties Location for registering
properties the associating delegates
for processing mass
change document
relationships.
com.ptc.wind Class This class is responsible
chill. for implementing
enterprise.mass functionality common for
Change processing the selected
.filters.Abstract mass change operations.
DefaultFilter Handles the command
Delegate bean and server excluded
items.
com.ptc.windchill Class This class is responsible
.enterprise.mass for processing the
Change.filters. selected mass change
AbstractWorkable operation. Also contains
FilterDelegate common filter logic for
excluding logic for

1186 Customization Guide


Element Type Description
objects that are not
eligible for the mass
change operation.
Performs operations that
are specific to Workable
including handling
checkout operations.
com.ptc.windchill Class This delegate contains
.enterprise.mass filter logic to exclude row
Change.filters. objects from a mass
AbstractPart change operation based
UsageFilter on logic that is specific to
Delegate WTPartUsageLink
operations.
com.ptc.windchill Class This filter delegate
.enterprise. determines whether the
massChange. selected objects are
filters.Abstract eligible for the mass
DocumentLink change operation on the
FilterDelegate selected document. The
supported document types
are wt.doc.WTDocument
and wt.epm.
EPMDocument.
com.ptc.windchill Class This filter delegate
.enterprise.mass determines whether the
Change.filters. selected objects are
AddDocument eligible for the mass
LinkFilter change operation for the
Delegate selected document. The
AssociationDelegate
registered for the selected
association type
("Referenced By",
"Described By", or
"Passive") which is used
to filter or create the
appropriate association
links for the selected
objects and the selected
document. The supported

Customizing Change Management 1187


Element Type Description
document types are wt.
doc.WTDocument and
wt.epm.EPMDocument.
com.ptc.wind Class This filter delegate
chill. determines whether the
enterprise.mass selected objects are
Change.filters. eligible for the mass
AddPart change operation for the
UsageFilter selected parts. The
Delegate delegate filters invalid
selected objects and
creates new part usage
links for any valid objects
selected given the user
specified part.
com.ptc.windchill Class This filter delegate
.enterprise.mass determines whether the
Change.filters. selected objects are
ChangePartUsage eligible for the mass
FilterDelegate change operation for the
selected parts. The
delegate filters out invalid
objects selected prior to
performing the operation.
Valid objects associated
to the user specified part
will have their attributes
updated.
com.ptc.wind Class This filter delegate
chill. determines whether the
enterprise.mass selected objects are
Change.filters. eligible for the mass
RemoveDocument change operation for the
LinkFilter selected document. The
Delegate AssociationDelegate
registered for the selected
association type
("Referenced By",
"Described By", or
"Passive") which is used
to filter or remove the

1188 Customization Guide


Element Type Description
appropriate association
links for the selected
objects and the selected
document. The supported
document types are wt.
doc.WTDocument and
wt.epm.EPMDocument.
com.ptc.windchill Class This filter delegate
.enterprise.mass determines whether the
Change.filters selected objects are
.RemovePart eligible for the mass
UsageFilter change operation for the
Delegate selected parts. The
delegate filters invalid
selected objects and
removes the part usage
links for the valid
selected objects based on
the user specified part.
com.ptc.windchill Class This filter delegate
.enterprise determines whether the
.massChange selected objects are
.filters. eligible for the mass
ReplacePart change operation for the
Usage selected parts. The
FilterDelegate delegate filters invalid
selected objects or
replaces the part usage
links for the valid objects
selected with the user
specified replacement
part.
com.ptc.windchill Interface This delegate is used to
.enterprise determine the appropriate
.associations association link to create
.Association or to retrieve the
Delegate appropriated associated
objects. A specific
delegate is selected based
on the registered selector

Customizing Change Management 1189


Element Type Description
type registered in service.
properties.
com.ptc.windchill Class Helper methods for
.enterprise. association delegates.
associations.
Association
DelegateHelper
com.ptc.windchill Class This delegate is used for
.enterprise.mass managing
Change. WTPartDescribeLink
associations. associations.
DescribedByLink
Assocation
Delegate
com.ptc.windchill Class This delegate is used for
.enterprise.mass managing
Change. WTPartReferenceLink
associations. associations.
ReferencedBy
LinkAssociation
Delegate
com.ptc.windchill Class This delegate is used for
.enterprise.mass managing
Change. EPMDescribeLink
associations associations.
.PassiveLink
Association
Delegate

Customization Points
Adding and Extending Operations
The mass change client supports the ability to add new or extend existing
operations to the client. The javadoc in the class MassChangeFilterDelegate has
detailed instructions on how to do this.
While the filter delegate handles the processing of the mass change operation, not
all operations are applicable for the selected object types. (For example a
WTDocument is not valid for mass change operations handling part usage links.)

1190 Customization Guide


In order to indicate which operations are supported for the selected objects
validation is required. See the Mass Change – Supported Types best practice for
details.

Extending Document Specific Operations


When processing the document operations Insert existing document or Remove
related document there is a delegate that is used based on the relationship selected
and the selected objects for the mass change. New delegates can be implemented
to process relationships and/or selected objects. Currently the document
relationships supported are Described By and Referenced By for Documents and
Passive for CAD Documents. See javadoc in the AssociationDelegate and
implementing classes for more details on the implementation and configuration.

Support Parts Built from CAD


Starting in the Windchill 10.2 M030 release, the mass change operation will
support changes to parts built from CAD documents (i.e., parts with an active
“owner” relationships to CAD documents). When Parts Built from CAD support
is enabled the mass change behavior will be as follows:
• The mass change operation will expose a publish action to apply the part
changes to the backing CAD object.
• The preview table will show a different set of actions (e.g., Include, Exclude,
and Export to file).
• The preview table will show all selected target objects, including ineligible
ones.
• A new "Exclusion Reason" column is displayed to explain why an object was
ineligible, as well as a strikethrough on the ineligible object.
• The mass change action is removed from the change task wizard, but it
remains on the resulting objects table of the change task information page.
For compatibility with prior Windchill releases CAD support will not be enabled
by default. To enable Parts Built from CAD support the following property should
be set in the site.xconf file : massChange.enableCADSupport=
true

Note
A future Windchill release will make support of Parts Built from CAD
mandatory, and the above property will be removed.

Customizing Change Management 1191


Customization Updates
Installations with customized mass change code will need to update that code to
be compatible with changes described in the “Support Parts Built fro,m CAD”
section.. The following methods and in package
com.ptc.windchill.enterprise.massChange.filters have been
deprecated and will be removed in a future Windchill release:
• MassChangeFilterDelegate.evaluate(Map<Changeable2,
String> result, String action, List<Changeable2>
selectedItems)
• MassChangeFilterDelegate.processOperation(List<
Changeable2> nonExcludedItems)
• AbstractDefaultFilterDelegate,massChangeOperation()
• AbstractWorkableFilterDelegate.doOperation(Changea
ble2 source_changeable, WTCollection target_
changeables)
• AbstractWorkableFilterDelegate.processExclusionCri
teria(WTCollection targets, Changeable2 sourcePart)
• AbstractPartUsageFilterDelegate.validateForQuantityU
nit()
All extended classes with methods that override those listed above are also
deprecated. See the JavaDoc of the deprecated methods for information on
replacements.

Related Documentation
See Mass Change Supported Types on page 1193 for information on modifying
the supported object types for a mass change operation.

1192 Customization Guide


Mass Change Supported Types
This section explains how to modify the supported object types for a mass change
operation. The supported types for a mass change operation may need to be
modified to include or exclude certain types of objects. For example the default
supported type for the Insert Existing Part operation is to support all part object
types.

Scope/Applicability/Assumptions
This documentation assumes that you are familiar with updating property files.
During this process you ill update the mass change operation properties in
wt.properties with the supported or excluded object types.

Prerequisite Knowledge
To perform this operation, you must have an understanding of the following:
• xconfmanager
• wt.properties
• service.properties

Solution
Solution Elements
Element Type Description
wt.properties properties Location for registering
the supported and
excluded types
service.proper properties Location for registering
ties the validation supported
types for operations.
com.ptc.windchill class Validates that the
.enterprise. operation has valid types
massChange. of objects
validators.
MassChange
Operation
Validator

Customizing Change Management 1193


Including and Excluding Types
The mass change operations are controlled by properties for supported and
excluded types for a specific operation. The supported and excluded types for
selected target objects for the mass change operation can be registered against the
mass change operation in wt.properties.
To specify the supported types for a particular mass change operation the
following name convention should be followed:
• Supported types: massChange.operationName.supportedTypes
• Excluded types: massChange.operationName.excludedTypes
To include or exclude an object type the external form of the type is used. For
example, to include the root type Part in the string use
WCTYPE|wt.part.WTPart. If no supported types are specified for a mass
change operation then all selected objects are supported for the operation. It is
recommended to specify at least one supported type due to multiple launch
locations of the mass change wizard.
Out-of-the-box, the validator MassChangeOperationValidator, is
provided that can be used to leverage the supportedTypes and
excludedTypes. This validator should be able to handle most cases in the
field. The validator is used to present the user with the list of operations which are
applicable based on the selected objects. Validating the items applicability beyond
its type (for example not allowing mass change on checked-out items) should be
handled within the Filter delegates (overriding theevaluate() or
getServerExcludedItems() methods) see the Mass Change Operations on
page 1185.

Restricting the mass change operation to only certain types:

Note
The following example uses the out of the box supported types for the Insert
Existing Part operation (addPartUsage).

1. Using xconfmanager, add a property to wt.properties that specifies the


supportedTypes. The output should look similar to the Insert Part Usage
operation property.
massChange.addPartUsage.supportedTypes=WCTYPE|wt.part.WTPart
2. Register a validator using xconfmanager for the operation key in
service.properties. Note that the selector is the operation with
_filter appended to the end. As stated above, the
MassChangeOperationValidator is designed to use the
supportedTypes and excludedTypes property entries automatically.

1194 Customization Guide


wt.services/svc/default/com.ptc.core.ui.validation.UIComponentValidator
/addPartUsage_filter/null/0=com.ptc.windchill.enterprise.massChange.
validators.MassChangeOperationValidator/duplicate

Identifying the Property to Update


Use the following table identify the property that you must update for a specific
operation.
Property Name Description
massChange. The supported types for the Replace
replacePart Existing Part operation.
Usage.
supportedTypes
massChange. Used to exclude types for the Replace
replacePart Existing Part operation.
Usage.excluded
Types
massChange. The supported types for the Insert
addPartUsage Existing Partoperation.
.supportedTypes
massChange. Used to exclude types for the Insert
addPartUsage. Existing Partoperation.
excludedTypes
massChange. The supported types for the Remove
removePartUsage Part Usage operation.
.supportedTypes
massChange. Used to exclude types for the Remove
removePartUsage Part Usage operation.
.excludedTypes
massChange. The supported types for the Edit Part
changePartUsage Usage operation.
.supportedTypes
massChange. Used to exclude types for the Edit Part
changePartUsage. Usage operation.
excludedTypes
massChange. The supported types for the Insert
addDocument Existing Document operation.
Usage.supported
Types
massChange. Used to exclude types for the Insert
addDocument Existing Document operation.
Usage.excluded

Customizing Change Management 1195


Property Name Description
Types
massChange. The supported types for the Remove
removeDocument Related Document operation.
Usage.supported
Types
massChange. Used to exclude types for the Remove
removeDocument Related Document operation.
Usage.excluded
Types

Related Documentation
• Mass Change Operations on page 1185

1196 Customization Guide


Sponsored Problem Reports and
Variances
An organization can extend change management process for Problem Reports and
Variances to members of an external organization. To distinguish problem reports
and variances that are exposed outside the host organization from their regular
counterparts that are not exposed, they are designated “Sponsored”.
The host organization creates a project in ProjectLink to be used as a repository
for these sponsored objects.

Preferences
There are two preferences that need to be enabled for Sponsored Problem Reports
and Variances functionality:
• Problem Reports in Projects
• Variances in Projects
The preferences can be enabled at the site, organization, and/or container level (on
the project). Both preferences are under the "Change Management" category.
As a project creator or site administrator, use the preference manager to enable the
preferences.

Object Initialization Rule (OIR)


The OIR defines rules by the objects type at the site, organization, and/or
container levels. Such rules stipulate whether the server assigns an attribute’s
value or it is entered by the user. For the Sponsored change objects, the attributes
of interest include:
• Number
• Folder location
• Life cycle
• Team template
The OIR can be used to manage these attributes and when the rules are defined,
careful consideration is needed so that rules defined for projects do not interfere
with rules defined for products and libraries.

Project Team Roles


The Project manager should add Team Roles to the project team based on the roles
needed by the Lifecycle and the Workflow Process Templates to be assigned to the
sponsored changes. “Change Administrator I” role is needed for sponsored
problem reports, “Variance Approvers” role is required if you intend to use
sponsored variances.
See the Windchill Business Administrator's Guide on how to add roles to the team.

Customizing Change Management 1197


Custom numbering schemes
By default the number attribute is auto generated for change objects. This can be
changed using object initialization rules for the Problem Report or Variance to
allow the number to be manually entered or other configurations as supported by
Windchill. See the Number Schemes Administrator for further details.

Basic Access Policies for the Project


These are the minimal policies OOTB that are required to successfully create, edit
and view sponsored objects.
Context Object State Partici- Permis-
Type pant sions
Project WTChan- All Project + Full Control
geIssue Creator (All)
Project WTChan- All Team + Read,
geIssue members Download
Project WTChan- Open Team + Create,
geIssue members Modify,
Modify
Content
Project WTChan- All CHANGE + Full Control
geIssue ADMINIS- (All)
TRATOR I
Project WTVar- All Project + Full Control
iance Creator (All)
Project WTVar- All Team + Read,
iance Members Download
Project WTVar- Open Team + Create,
iance Members Modify,
Modify
Content
Project WTVar- Under Variance + Read,
iance Review Approvers Download
Project WTVar- All CHANGE + Full Control
iance ADMINIS- (All)
TRATOR I
Optional policies recommended for sponsored changes in projects:

1198 Customization Guide


Context Object- State Partici- Permis-
Type pant sions
Project WTChan- All Organiza- + Full Control
geIssue and tion (All)
WTVar- Administra-
iance tor
Project WTChan- All Guest + Read
geIssue and
WTVar-
iance
Project WTChan- All Site + Full Control
geIssue and Administra- (All)
WTVar- tor
iance

Project Folders
By default the folder location is auto generated for change objects; when a new
sponsored object is created, it should be saved in the root folder of the project.
This default behavior can be changed. Use Object Initialization Rules
Administration to change the default.

Project Template
An organization can choose to configure suitable rules and policies that meet their
business needs using a project template. See the Windchill Business
Administrator's Guide for further details.

Customizing Change Management 1199


Change Management Cardinality
You can modify the cardinality or workflow closure rules for change requests
from change orders or change issues from change requests.

Background
The cardinality of the AddressedBy link and the FormalizedBy link is driven by a
delegate infrastructure. The default implementation for out-of-the-box change
object types provided in Windchill 10.0 M20 or later is a delegate supporting 1-N,
N-1, or N-M cardinality. The later is only applicable if the change object
cardinality preferences are enabled. A new delegate is also available to support 1-
1 cardinality.

Scope/Applicability/Assumptions
• Assumes you have general knowledge about Java classes and concepts such as
class extension
• Assumes you have general knowledge about the xconf mechanism to create
properties.

Intended Outcome
After reading this, you should know how to create custom cardinality rules for
change requests and change orders, or change requests and change issues.

Solution
Solution: Create a custom class that extends a default delegate, and create an
xconf entry to register your custom delegate.

Prerequisite knowledge
To apply this best practice, you need to have an understanding of the following:
• Java class extension
• Xconfmanager

Solution Elements
Element Type Description
wt.change2. Interface Generalizable Interface
ChangeCardinalityDele- for cardinality rules
gate
wt.change2. Link class Supports 1-1
DefaultAddressedByDe- ChangeRequest2 to
legate ChangeOrder2 cardinality
wt.change2. Link class Supports 1-1

1200 Customization Guide


Element Type Description
DefaultFormalizedByDe- ChangeRequest2 to
legate ChangeIssue2 cardinality
wt.change2. Link class Supports 1-N, N-1 or N-
AddressedByDelegate M (preference driven)
WTChangeRequest2 to
ChangeOrder2 cardinality
wt.change2. Link class Supports 1-N, N-1 or N-
FormalizedByDelegate M (preference driven)
WTChangeRequest2 to
ChangeIssue2 cardinality
ChangeMgmt-service. Default change service Property file which
properties.xconf properties registers the above
cardinality rules out-of-
the-box.

Customization Points
1. If you want to customize the cardinality for the AddressedBy2 link, then
you should create a new java class (your delegate) which extends the
DefaultAddressedByDelegate or the AddressedByDelegate
(depending on which existing functionality closest matches the behavior
desired)
public class YourCustomAddresssedByDelegate
extends DefaultAddressedByDelegate
{
/**
* Determines if the change request is 'properly addressed'.
Default implementation of
* addressed by means that one change request can be addressed
* by only one change notice and vice-versa.
* @param ChangeIssue
* @param ChangeRequest2
* @return void
* @throws WTException - If the cardinality is
* invalid, a ChangeException2
* should be thrown along with the reason why the
* cardinality is not valid.
*/
@Override
public void validateCardinalityConstraints(ChangeRequest2 cr,
ChangeOrder2 co) {
//YOUR RULES IMPLEMENTED HERE
}
/**

Customizing Change Management 1201


* Overriding this method will handle the closure of the
ChangeRequest2
* object based on a delegate implementation.
* Ultimately, the closure of the ChangeRequest2 will require
the closure of all
* associated ChangeOrder2 objects
* which are registered against the same delegate.
*
* @param changeObjects
* @param changeObjects
* @return
*/
@Override
public boolean isReadyForResolution(ChangeRequest2 cr,
Set<ChangeOrder2> objs) {
//YOUR RULES IMPLEMENTED HERE
return true; // if the change request is ready
}
}
2. If you want to customize the cardinality for the FormalizedBy link, then
you should create a new java class (your delegate) which extends the
DefaultFormalizedByDelegate or the FormalizedByDelegate
(depending on which existing functionality closest matches the behavior
desired)
public class YourCustomFormalizedByDelegate extends
DefaultFormalizedByDelegate
{
/**
* Determines if the change request is 'properly addressed'.
Default implementation of
* addressed by means that one change request can be addressed
* by only one change notice and vice-versa.
* @param ChangeIssue
* @param ChangeRequest2
* @return void
* @throws WTException- If the cardinality is invalid, a
* ChangeException2 should be thrown along with the
* reason why the cardinality is not valid.
@Override
*/
public void validateCardinalityConstraints(ChangeRequest2 cr,
ChangeOrder2 co) {
//YOUR RULES IMPLEMENTED HERE
}
/**
* Overriding this method will handle the closure of the
ChangeRequest2
* object based on a delegate implementation.
* Ultimately, the closure of the ChangeRequest2 will require
the closure of all

1202 Customization Guide


* associated ChangeOrder2 objects
* which are registered against the same delegate.
*
* @param changeObjects
* @return
*/
@Override
public boolean isReadyForResolution(ChangeIssue ci,
Set<ChangeRequest2> set) {
//YOUR RULES IMPLEMENTED HERE
}
}

Note
When defining this xconf configuration, it is important that the requestor
(in this case the ext.change2.YourChangeRequest2) is not an
abstract type, this is because the framework performs the lookup based on
a concrete class name (and it does not support hierarchical lookup of
types). The selector class, however, can be an abstract type. If you do not
register your delegate, then the default Windchill implementation would be
used instead of your delegate. This default implementation supports 1-N,
N-1, N-N (if the change object cardinality preference is enabled).
Modifying the cardinality of out of the box Windchill types:
For example, if you wanted to apply 1-1 cardinality between the
WTVariance and the WTChangeRequest2, you would have add the
following properties to xconf configuration:
<Service context="default" name="wt.change2.ChangeCardinalityDelegate">
<Option requestor="wt.change2.WTChangeRequest2" cardinality="singleton"
serviceClass="wt.change2.DefaultFormalizedByDelegate"
selector="wt.change2.WTVariance"/>
</Service>

Customizing Change Management 1203


Change Management Delegate
The wt.change2 package has a delegate defined to allow customization. The
following is an overview to help you know where to start.

ConcreteAssociationDelegate
ConcreteAssociationDelegate is used within
StandardChangeService2. It is obtained from the
Change2DelegateFactory.
There are many subclasses of ConcreteAssociationDelegate. Each one
takes two arguments: the two objects being linked. Each one returns the link
object that links the two objects. There is no mechanism for adding additional
values for attributes that belong on the link object, so this mechanism works best
for link objects that have not been customized with additional attributes.
One other complication with this delegate is that if you customize some of the
main classes, you may have to add properties file entries that may not seem
intuitively obvious.
Assume that you customize change order (that is, make a subclass of
wt.change2.WTChangeOrder2) in your myChange2 package within your
customization package and call it MyChangeOrder.
When looking up the appropriate subclass of
wt.change2.ConcreteAssociationDelegate, the following entry in
section 9 of wt.change2.change2.properties is being used when
linking the change order to a change request:
wt.services/svc/default/wt.change2.ConcreteAssociationDelegate/
wt.change2.WTChangeOrder2/wt.change2.WTChangeRequest2/
1=wt.change2.AddressedBy2Delegate/singleton

• The reference to wt.change2.WTChangeRequest2 is in a field where


inheritance is applied. In other words, if you subclassed
wt.change2.WTChangeRequest2 as customization.myChange2.
MyChangeRequest, then the delegate lookup process could still use this line in
the properties file, because
customization.myChange2.MyChangeRequest is a
wt.change2.WTChangeRequest2.
• The reference to wt.change2.WTChangeOrder2 is in a field where
inheritance is not applied. In other words, if you subclassed
wt.change2.WTChangeOrder2 as
customization.myChange2.MyChangeOrder, then the delegate
lookup process could not use this line in the properties file because the string
"customization.myChange2.MyChangeOrder2" does not match

1204 Customization Guide


exactly the string "wt.change2.WTChangeOrder2".All that is needed is
another line in the properties file:
wt.services/svc/default/wt.change2.ConcreteAssociationDelegate/
customization.myChange2.MyChangeOrder/
wt.change2.WTChangeRequest2/
1=wt.change2.AddressedBy2Delegate/singleton

Customizing Change Management 1205


Change Management Transitions
When releasing a Change Notice, you might not always want the Resulting
Objects to go to the Released state. You may want them to go into a different state.

Scope/Applicability/Assumptions
This information assumes familiarity with the Resulting Objects table found on
the Change Task wizard. Knowledge regarding Life Cycle Transitions will also be
helpful.

Intended Outcome
To understand how to choose what state you want Resulting Objects to enter into
once the Change Notice is released.

Solution
In order to choose what state the Resulting Objects will go into when they are
released, you will need to select a Release Target for the Resulting Object on the
create or edit the Change Task wizard. If a Resulting Object has a Release Target
set during the time of the Change Notice release, the Resulting Object will go into
the state defined by the Release Target transition. Release Target Transitions can
be customized to include additional Change Management Transitions. See Create
Change Management Transitions on page 1206 for more information on
customizations.

Prerequisite Knowledge
To complete this process you must have an understanding of the following:
• Concepts:
○ Change Task Resulting Objects Table
○ Life Cycle Transitions
○ Workflow Template Administration
• Properties:
○ wt.change2.changeTransitions
○ wt.change2.showAllChangeTransitions
• Preferences:
○ Change Management/Multiple Transitions on the Release Target Column

Create Change Management Transitions


Follow these steps to create Change Management transitions.

1206 Customization Guide


1. Create new enumerated types to represent transitions. For more information
see Enumerated Types on page 1973.
2. Once the enumerations are successfully created, in order to make the new
transitions official “Change Management Transitions”, you must add the
transition to the wt.change2.changeTransitions property. This
property is a comma delimited list of Transitions. The set of transitions
identified by this property are the Change Management Transitions.

Setup the Life Cycle to use the Change Management


Transitions
Once you have a Change Management Transition setup, you must pick the State
you want the Transition to go into when the Change Notice is released.
1. From the Utilities page, open Life Cycle Template Administration.
2. Edit the Life Cycle that represents your Resulting Object. This example shows
a Basic life cycle.
3. Setup a Transition such that when you are in any state, the Obsolescence
Transition sets the object to the Canceled state. This is how you configure
what State the Obsolescence transition will navigate to.

Customizing Change Management 1207


Change Notice Workflow Modifications for Updated or
Upgraded Systems
1. In order to use alternate transition targets on Windchill installation that have
been updated or upgraded from a release prior to 10.1 M010 you will need to
modify the change notice workflow template.

Note
New Windchill installations of release 10.1 M010 and beyond do not
require this modification.

2. Open Workflow Template Administration found on the Utilities page.


3. Edit the change notice workflow used for your change process.
4. Find all expressions like:
com.ptc.windchill.pdmlink.change.server.impl.Work
flowProcessHelper.promoteChangeables((wt.chan
ge2.WTChangeOrder2)primaryBusinessObject);
5. And change them to:
com.ptc.windchill.pdmlink.change.server.impl.Work
flowProcessHelper.releaseChangeables((wt.chan
ge2.WTChangeOrder2)primaryBusinessObject);
In an out-of-the-box Windchill installation the above change would be made in the
Release Changeables expression robot of the Change Notice Workflow

Executing the Case


1. Create a part.
2. Reassign the part so that is has the same life cycle as the one you configured
above.
3. Create a change notice.
4. When creating the change notice, add the part to the resulting objects table of
the default change task.
5. In the Release Target drop-down , select Obsolescence.

1208 Customization Guide


6. Click Finish to create the change notice
7. Once the change notice is resolved, the resulting object will go into a Canceled
state because the Obsolescence transition was selected.

Customizing Change Management 1209


Change Template Initialization Rules
Administrators can configure change notice or task rules for number, life cycle
template, and other attributes to a specific or generated value on creation. The
only difference between a change notice or task and a change notice or task
template is a template attribute specifying that the object is a template. Since the
change notice or task and change notice or task template are the same object type,
they use the same loaded object initialization rules.
You can customize a change notice or task template to use different object
initialization rules from what is used for a change notice or task that is not a
template.

Intended Outcome
The creation of change notices that are not templates are unaffected and keep the
current generated number sequence and life cycle template. The change notice
templates are generated with numbers that have 10 digits and use the “Basic” life
cycle template.

Solution
Update the change notice or task object initialization rule to conditionally
configure the number and life cycle template when the change notice or task
template attribute is set to true.

Prerequisite Knowledge
To achieve this result, you need to have an understanding of the following:
• XML
• Loading Windchill object initialization rules. For more information on how to
load and configure object initialization rules, see Loading Object Initialization
Rules.

Solution Elements
Element Type Description
Rule for Change Notice XML The rule for change
or task notice or task.

Procedure
When setting the argument for an attribute value in which the change notice or
task template value should be different than for the change notice or task creation,
use the wt.rule.algorithm.BooleanBranch value algorithm and test if

1210 Customization Guide


the template.templated attribute is set to True. The first argument is for
change notice or task template and the second argument is used for the change
notice or task.
<!-- if (template.templated) -->
<Value algorithm="wt.rule.algorithm.BooleanBranch">
<!-- test this value -->
<Attr id="template.templated"/>
<!-- if true -->
<Arg>Value for change notice or task template</Arg>
<!-- if false -->
<Arg>Value for change notice or task</Arg>
</Value>

Limitations
It is not possible to configure the number attribute to be empty for change notice
or task template and generated for change notice or task because the template
attribute is not set until the create wizard is submitted. Instead, it is recommended
to use a generated sequence for both the change notice or task template and
change notice or task if a generated sequence number is required for creation of
change notice or task.

Sample Code
Updated object initialization rules (OIR) in file
ChangeMgmtInitRules.xml:
Change notice or task Regular Change
template notice or task
Life cycle template Basic Change Notice Life Cycle
Number 10-digit number 5-digit number
<!-- set the lifecycle -->
<AttrValue id="lifeCycle.id" algorithm="com.ptc.core.foundation.lifecycle.
server.impl.LifeCycleTemplateAttributeAlgorithm">
<!-- if (template.templated) -->
<Value algorithm="wt.rule.algorithm.BooleanBranch">
<!-- test this value -->
<Attr id="template.templated"/>
<!-- if true -->
<Arg>Basic</Arg>
<!-- if false -->
<Arg>Change Notice Life Cycle</Arg>
</Value>
</AttrValue>

<!-- set the number to a generated number -->


<AttrValue id="number" algorithm="com.ptc.windchill.enterprise.

Customizing Change Management 1211


revisionControlled.server.impl.NumberGenerator">
<!-- if (template.templated) -->

<Value algorithm="wt.rule.algorithm.BooleanBranch">
<!-- test this value -->
<Attr id="template.templated"/>
<!-- if true -->
<Arg>{GEN:wt.enterprise.SequenceGenerator:WTCHANGEORDERID_seq:10:0}</Arg>
<!-- if false -->
<Arg>{GEN:wt.enterprise.SequenceGenerator:WTCHANGEORDERID_seq:5:0}</Arg>
</Value>
</AttrValue>

Examples of Usage in Windchill Code


• <Windchill>/loadFiles/pdmlink/
ChangeMgmtInitRules.xml

1212 Customization Guide


Replicated Objects as Change Task
Resulting Objects
You can add a replicated object as resulting object of a change task, and optionally
assign it an effectivity value.

Background
The term replicated object defines a non-modifiable object that is copied, or
replicated, from a different Windchill installation. Replicated objects are by
importing a ZIP file with the Received Delivery Management utility. Replicated
objects are subject to a special mechanism called an administrative lock that
prevents them from being modified on the importing system.
Under normal circumstances a replicated object could not be added as a resulting
object to a change task because the change process would not be able to update its
life cycle state. If such an attempt is made, then the following error message is
given when the change notice is completed:

In some circumstances to be able to add a replicated object that has already been
released to a change task (for example, as a new component of an assembly) is
required. It may also be required to add an effectivity value to the replicated object
when it is used a resulting object.

Scope/Applicability/Assumptions
To complete this customization, you must be familiar with the following:
• Creating change tasks
• Adding resulting objects
• Assigning effectivity values

Customizing Change Management 1213


Intended Outcome
A replicated object is added to a change task as a resulting object. In the following
example, ‘Pump” is a replicated object that is added to the “Engine” change task
as a resulting object. Note that the padlock glyph indicates that Pump has an
administrative lock and is common to all replicated objects.

Also, a serial effectivity has been added Pump.

“Pump” is added to the “Engine” structure to implement the change.

1214 Customization Guide


When the change notice is completed, the “Engine” is advanced to a Released
state. The “Pump”, which was already in a Released state, is not changed.

Solution
Customize Windchill to allow replicated objects as change task resulting objects,
and prevent the change process from attempting to promote replicated objects to a
Released state.

1. Prerequisite Knowledge
To complete this process, you need to have an understanding of the following:
• Setting a system property
• Creating a custom life cycle template
• Creating an import life cycle mapping

Customizing Change Management 1215


Customization Points
Complete the customization steps in this section before importing replicated
objects that are used as change task resulting objects. If they are completed after
the import is complete, then, you can use the Reassign Life Cycles action to
reassign the life cycle template of a replicated object to the custom one created in
Create Custom Life Cycle Template for Replicated Objects on page 1216.

Set System Property for Replicated Resulting Objects


A system property allows a replicated object to be added as a change task
resulting object.
Perform the following steps to set the property:
1. Add the following line to <Windchill>/site.xconf :
<Property name="wt.fc.adminlock.AdministrativeLockType.change2.ProductDesignPkg"
overridable="true" targetFile="codebase/wt.properties" value="RESULTING_OBJECTS"/>

2. Run this command in a Windchill shell: xconfmanager -pF


3. Restart the method server(s).

Create Custom Life Cycle Template for Replicated Objects


The out of the box (OOTB) Windchill change notice workflow includes a step to
promote resulting objects to a Released state. This should not be attempted for
replicated objects, however, because their life cycle states are controlled by a
different Windchill installation. To prevent this you can create special life cycle
templates for replicated objects that, do not include change transitions from non-
Released to Released states. The only change transition such templates should
include is from the Released state back to itself.
For example, the OOTB Basic workflow includes these change transitions:
1. In Work ▶ Released
2. Released ▶ Released
Replicated objects that use the Basic life cycle template should not include
transition In Work ▶ Released , so a new template that does not include this
transition should be created.
1. Open the Life Cycle Template Administration utility and use the Save As action
to make a copy of an existing template that you want to customize for
replicated objects. For example, copy the Basic life cycle to a new one named
Basic-ReplicatedObject.
2. Edit the copied template and remove all change transitions from non-Released
to Released states, and keep only a change transition from the Released to
Released. For example:

1216 Customization Guide


3. Save and Check In the custom life cycle template.
4. Repeat this process for all life cycle templates that are used for replicated
objects.

Customizing Change Management 1217


Create Import Mappings for Replicated Object Life Cycles
When replicated objects are imported, they are normally assigned to the life cycle
template that is specified in the exported ZIP file. In this case, they should be
assigned to the custom life cycle templates described in Create Custom Life Cycle
Template for Replicated Objects on page 1216. This is accomplished by creating
life cycle import mappings before importing the objects.
1. Open the Mapping Management utility and select the Define Mapping action for
the exporting Windchill installation.
2. Select the Life Cycle tab from the Define Mapping window and add rows as
needed to map all states from the exported life cycle template to the custom
template. For example, the OOTB Basic life cycle has three states: In Work,
Released and Canceled. So three rows are needed for mapping.
3. Fill in the mapping fields so each source state maps to its associated target
state. Note that this utility defines “Source” values as those coming from the
exporting Windchill installation and “Mapped” values as those defined in the
importing Windchill installation. Also note that the “Source” values are taken
directly from the Zip file, and are not localized, whereas the “Mapped” values
show localized text. For example, the mappings for the Basic life cycle
template example to be used for replicated WTPart objects are:

4. Repeat this process for all object types being replicated.


5. When all mappings are complete select “OK” or “Apply” to save them.
6. After an import is complete, you can verify that the mappings are correct by
viewing the Life Cycle History of replicated objects. Note that if the
information page of a replicated object does not already display the Life Cycle
History, a new tab can be added to include this information. For example, the
replicated Pump object described in Intended Outcome on page 1214 shows
the following Life Cycle History:

1218 Customization Guide


Evaluating Business Rules On Demand
You want to create an action associated with a business object which will
immediately execute a set of business rules and provide feedback on the outcome.

Background
Business rules can be executed using the workflow and the results are displayed
on a workflow task. The change notice workflow, for example, executes the
Changeable Pre-Release rule set for the Audit Change Notice task and again prior
to releasing the resulting objects on the change notice. Users working on or
reviewing Change Tasks may want to get feedback before the Change Notice
Audit task runs, to verify that there are no conflicts before completing the task.

Scope/Applicability/Assumptions
This best practice provides steps to define a new action on the Change Notice
details page to execute a set of business rules and display the results. In order to
configure business rules see Customizing Business Rules on page 1264.

Customizing Change Management 1219


Intended Outcome

1220 Customization Guide


Solution
Create a new single step wizard which calls a customized MVC builder to execute
a set of business rules and view the results.

Prerequisite Knowledge
To apply this best practice you need to have an understanding of the following:
• Basic development involving HTML forms, JSP, and XML.
• The actions framework in the Windchill client architecture.
• The MVC component framework in the Windchill client architecture.
• The management of RBINFO file customizations.
• The Business Rules and how to execute business rules.
The Related Documentation on page 1227 section includes references to many or
all of these subjects.

Customizing Change Management 1221


Solution Elements
Element Type Description
com.ptc.windchill. Java Given the result of
enterprise.businessRules. executing the business
mvc.builders. rules displays the failed
AbstractBusinessRules- results. The results are
ResultsTable displayed in a table or
tree, depending on the
table view selected. The
"Group by Object" view
results are listed by object
in a simple table. The
"Group by Rule" results
are listed by rule in a tree
table.
CustomBusinessRulesRe- Java An example of a custom
sultsTable business rules result table
builder which executes
the business rules for the
resulting object on a
change notice.
config/mvc/custom.xml xml Registers the new
CustomBusinessRulesRe-
sultTable builder.
config/actions/custom- xml Defines a new custom
actions.xml action to evaluate a set of
business rules.
Custom Action Resource rbInfo Localized properties for
Info File your action (optional).
config/actions/custom- xml Include an action in
actionModels.xml action menu.

1222 Customization Guide


Procedure — Creating a Custom Business Rule Result
Action
The following steps provide an example of how to create a custom action which
executes a set of business rules for Change Notice resulting objects and display
the results. The action to evaluate the business rule results is made available in the
change notice action menu.

Extend Business Rules Results Table


Extend the AbstractBusinessRulesResultsTable class and override the
getRuleValidationResultSet API to execute the desired rule sets. See
Customizing Business Rules on page 1264 for more details on executing a set of
business rules. The following is an example of a custom business rules result table
builder which executes the business rules for the resulting object on a change
notice:
package com.custom.businessRules.mvc.builders;

@ComponentBuilder("CustomBusinessRulesResultsTable")
public class CustomBusinessRulesResultsTable extends
AbstractBusinessRulesResultsTable {

private static final Logger logger =


LogR.getLogger(CustomBusinessRulesResultsTable.
class.getName());

/**
* {@inheritDoc}
*/
@Override
public RuleValidationResultSet
getRuleValidationResultSet(NmCommandBean commandBean)
throws WTException {
RuleValidationResultSet resultSet = new RuleValidationResultSet();
logger.debug("Get context object.");
NmOid contextOid = commandBean.getActionOid();
if(contextOid.isA(WTChangeOrder2.class)) {
logger.debug("Context object is a change notice.");

BusinessRuleSetBean[] ruleSetBeans = new BusinessRuleSetBean[] {


BusinessRuleSetBean.newBusinessRuleSetBean
("CHANGEABLE_PRE_RELEASE",
ChangeRecord2.class.getName())
};
logger.debug("Executing the CHANGEABLE_PRE_RELEASE rule
set for the change notice resulting objects.");
resultSet = BusinessRulesHelper.
engine.execute(contextOid.getRefObject(),
ruleSetBeans);
}

Customizing Change Management 1223


return resultSet;
}
}

Register the Custom Table Builder


The builder is registered by adding the following line in /<windchill>/codebase/
config/mvc/custom.xml.
<mvc:builder-scan base-package="com.custom.businessRules.mvc.builders"/>

Define Actions
• Define Business Rules Results Action
Define a new action in <Windchill>/codebase/config/actions/
custom-actions.xml to launch a popup window that displays the
business rules results.
<objecttype name="customBusinessRules"
resourceBundle="com.custom.customClientActionsRB">
<action name="customBusinessRulesResultWizard">
<command windowType="popup"/>
</action>
</objecttype>

The new action requires new action properties defined in a custom resource
file. See Action Framework for Windchill Client Architecture on page 512 for
more details on defining new actions. The following is an example of
properties configured for the custom action:
@RBEntry("View Rule Conflicts")
@RBComment("Title of the wizard that displays business rules results")
public static final String PRIVATE_CONSTANT_0 =
"customBusinessRules.customBusinessRulesResultWizard.description";

@RBEntry("View Rule Conflicts")


@RBComment("Title of the wizard that displays business rules results")
public static final String PRIVATE_CONSTANT_1 =
"customBusinessRules.customBusinessRulesResultWizard.title";

@RBEntry("View Rule Conflicts")


@RBComment("Title of the wizard that displays business rules results")
public static final String PRIVATE_CONSTANT_2 =
"customBusinessRules.customBusinessRulesResultWizard.tooltip";

@RBEntry("width=940,height=600")
@RBPseudo(false)
@RBComment("DO NOT TRANSLATE")
public static final String VIEW_CONFLICTS_MOREURLINFO =

1224 Customization Guide


"customBusinessRules.customBusinessRulesResultWizard.moreurlinfo";
• Define Business Rules Results Table Step Action
Using the ComponentId defined in the custom table builder in the “Define
Business Rules Results Action” section above, define a new action to display
the business results table in /<windchill>/codebase/config/actions/custom-
actions.xml.
<objecttype name="customBusinessRules" resourceBundle=
"com.custom.customClientActionsRB">
<action name="customBusinessRulesResultStep">
<component name="CustomBusinessRulesResultsTable"/>
</action>
</objecttype>

Define Business Rules Results Action JSP


In order to display the table when launching the custom business rule action a
single step wizard needs to be defined using a jsp file. The name of the jsp should
match the name of the action and should be in a package with the same name of
the action object type under directory <Windchill>/codebase/
netmarkets/jsp. For the action defined in the “Define Business Rules
Results Action” section above, the package and name is:
<Windchill>/codebase/netmarkets/jsp/
customBusinessRules/customBusinessRulesResultWizard.jsp
The following jsp sample describes a single step wizard which includes the action
defined in the “Define Business Rules Results Table Step Action” section above.
For more details about describing wizards see Windchill Client Architecture
Wizard on page 838.
<%@ taglib prefix="jca"
uri="http://www.ptc.com/windchill/taglib/components"%>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<!-- Need to set isWizard and popupWindow to false in
order to display links on number and the info
page action icon. -->
<% request.setAttribute("isWizard","false"); %>
<script src="netmarkets/javascript/businessRules/
businessRulesResultsPlugin.js"></script>
<script type="text/javascript">
<!-- Converts all links to open in new window -->
PTC.onReady(function() {
JCAappendFormHiddenInput(getMainForm(), "popupWindow", "false");
});
</script>

<jca:wizard buttonList="OkCancelWizardButtons">
<jca:wizardStep action="customBusinessRulesResultStep"
type="customBusinessRules"/>
</jca:wizard>

Customizing Change Management 1225


<%@include file="/netmarkets/jsp/util/end.jspf"%>

Add the Business Rules Results Action to a Menu


The new custom action must be added to an object action model. A /<windchill>/
codebase/config/actions/custom-actionModels.xml is available for adding or
overriding actions models. The following sample shows how to add a custom
action to existing action model for a change notice:
<actionmodels resourceBundle="com.ptc.windchill.enterprise.
change2.changeManagementActionsRB">
<model name="more change notice row actions"
menufor="wt.change2.WTChangeOrder2">
<description>Change notice row actions</description>
<action name="customBusinessRulesResultWizard"
type="customBusinessRules"/>
.
.
<!-- Existing Actions -->
.
.
</model>
</actionmodels>

Limitations
The execution of Business Rules against large data sets may take longer to
complete than is normally expected from an on-demand action. In these cases it
may be better to execute the Business Rules as part of a workflow process.

Sample Code
Examples of Usage in Windchill Code
• Viewing Workflow Task Business Rules Conflicts
Uses the work flow task page object to get the Business rules validation results
and returns the list of target objects with Business Rule conflicts. See Viewing
Rule Conflicts topic
○ com.ptc.windchill.enterprise.businessRules.mvc.builders.
BusinessRulesResultsTable
○ config/mvc/BusinessRulesClient-configs.xml
○ config/actions/BusinessRulesClient-actions.xml

1226 Customization Guide


○ nemarkets/jsp/businessRules\businessRulesResultWizard.jsp

Related Documentation
Related Customization Documentation
• Constructing and Rendering a Table Using the JSP Framework on page 606
• Action Framework for Windchill Client Architecture on page 512
• Resource Info (.rbInfo) Files on page 2071
• MVC Components Overview on page 258
• Windchill Client Architecture Overview on page 232
• Customizing Business Rules on page 1264

Related Package/Class Javadoc


• com.ptc.core.businessRules.engine.BusinessRulesEngine

Customizing Change Management 1227


Editing Attributes on the Links of Change
Relationship Tables
This section provides a detailed example of how to allow editing of global
attributes on the links of change relationship tables. It focuses specifically on the
Affected Objects and Resulting Objects tables of the change task. As appropriate,
other change tables are mentioned. This information illustrates two ways to
accomplish this task and provides some guidance on when one way is desirable
over another way. Both methods can be combined as well.

Overview
In this example, you add two global attributes to the Affected Objects and
Resulting Objects tables.
One the Affected Objects, using a subtype of the
AffectedActivityDatalink class a new attribute called “Regulatory
Affected” (boolean type) is added.
• The values should appear as “Yes/No” and read only in the table.
• You should be able to select one or more changeables and set the value at one
time on the set of selected changeables.
• The value set should be retained if you sort or filter the table. This includes
showing a view that removes the column.
One the Resulting Objects, using a subtype of the ChangeRecord2 link class a
new attribute called “Distribution List” is added (string type) is added.
• The value should appear as editable inline single-row of text within the table
row for parts only.
• The value should be required

Note
For this example, no validation other than the type (and distribution list is
required) is done.

1228 Customization Guide


Example: Edit Change Task

Constraints and Limitations


• The global attributes reference reusable attributes. In order to use other forms
of attributes additional generation may be required. For more information, see
the “Managing Reusable Attributes” help topic in the Windchill Help Center
for further details.
• Two subtypes of the links (CustomAffectedActivityDataand,
CustomChangeRecord2) are created to store the global attributes. This
also shows the ease at which you can now use subtype links for the Affected/
Resulting Objects tables for all change wizards.

Note
Change link Configuration Management only supports one link type per
RoleA. If multiple are defined, only the most specific is used. The user
cannot choose which link to use.

• Two constraints are created with RoleA being the base class
WTChangeActivity2 and RoleB being either the
CustomAffectedActivityData or CustomChangeRecord2 links.

Customizing Change Management 1229


• Only supported APIs are used in the examples
• The code samples provide a good starting point for extending this
customization to larger more complex scenarios (multiple attributes,
embedded objects etc.)

Customization Procedure
The follow procedure outlines the steps required to perform the customization:
1. Create a table view class extending the existing table view class and add the
new attribute to one or more views. Define the attribute(s) as a special column
to allow it to be used in the View Manager. The column does not need to be
rendered in all (or any views). But to add it to views it needs to be defined as a
special column (since the table is against changeables and knows nothing
about links)
See Custom Table Views (Step 1) on page 1231 for more information.
2. Create an MVC Table Builder extending the one registered for the table.
Annotate the builder with @OverrideComponentBuilder and override
any of the following:
• buildConfigurableTable() to return the custom view class.
• buildComponentData() if there is custom data acquisition logic.
• buildComponentConfig() to define other custom configurations
(models, help files)
See Create MVC Builder Table (Step 2) on page 1233.
3. Define a custom Data Utility to render the attribute in Create, Edit and View
modes. See Create a Data Utility (Step 3) on page 1234 for more information.
4. (Optional) Provide a Javascript or pop-up editors needed to support multi-
object edits. See Add Support for Multi-Edit Actions (Step 4) on page 1236
for more information.
5. Define a custom form delegate to process the attributes (The change task
affected/resulting objects step requires a second form delegate to be created)
See Create a Form Delegate (Step 5) on page 1238 for more information.
6. Define a custom actions.xml referring to the custom form delegate for the
wizard step. See Register Form Delegate with Step (Step 6) on page 1242 for
more information.

1230 Customization Guide


Custom Table Views (Step 1)
1. Extend one of the out-of-the-box Table View classes:
Table View Class Change Object
Affected Objects ChangeTaskAffec Change Task
tingItemsTable Variance
Views
Problem Report and
VarianceAffected Change Request
DataTableViews
AffectedDataTa
bleViews
Resulting Objects ChangeTaskResul Change Task
tingItemsTable
Views
2. Override the getSpecialTableColumnsAttrDefinition() method
to include the new attributes.
3. Add the column to all views or only to selected views.
• To add the column to all views, override the method
getDefaultColumns() and insert the column in the appropriate
location.
• To add a column to selected views override the method
getOOTBTableViews() first calling the
super.getOOTBTableViews(), find the view(s) needed to be
updated and update those views by changing the
TableColumnDefinitions.

Sample Code

public class DistributingResultingItemsTableViews extends


ChangeTaskResultingItemsTableViews {

/**
* The distributionList will only be added to the Parts and All views
immediately after
* the name column.
*/
@SuppressWarnings("unchecked")
@Override
public List getOOTBTableViews(String tableId, Locale locale)
throws WTException
{
List<TableViewDescriptor> result =
super.getOOTBTableViews(tableId, locale);
for(TableViewDescriptor descriptor: result) {

Customizing Change Management 1231


if( descriptor.getName().equals(PARTS_VIEW) ||
descriptor.getName()
.equals(ALL_VIEW)) {
Vector<ableColumnDefinition> columns =
descriptor.getTableColumnDefinition();
for(int c = 0; c < columns.size(); c++) {
if( "name".equals(columns.get(c).getName())) {
String key = DistributingChangeRecordConstants.
DISTRIBUTION_ATTRIBUTE;
columns.add(c++,TableColumnDefinition.
newTableColumnDefinition
(key,isColumnLocked(key)));
break;
}
}
}
}
return result;
}

@Override
@SuppressWarnings("unchecked")
public List<?> getSpecialTableColumnsAttrDefinition(Locale locale) {
List<Attribute.TextAttribute> results = (List<TextAttribute>)
super.getSpecialTableColumnsAttrDefinition(locale);
results.add(new Attribute.TextAttribute
(DistributingChangeRecordConstants.
DISTRIBUTION_ATTRIBUTE,
"Distribution List" /*Should be localized label*/, locale));
return results;
}
}

1232 Customization Guide


Create MVC Builder Table (Step 2)
1. Create a new MVC table builder extending the existing table builder from the
following
Table View Class Change Object
Affected Objects AffectingItemsTa Change Task
bleBuilder Variance, PR and
AffectedDataTa Change Request
bleBuilder
Resulting Change ResultingItemsTa Change Task
bleBuilder
2. Declare the annotation @OverrideComponentBuilder on the class.
3. Override the method getConfigurableTable() to return a new instance
of your table view.
4. If a unique actionModel is needed, help files or custom view you need to
override the method getComponentConfig().

@OverrideComponentBuilder
public class DistributingResultingItemsTableBuilder extends
ResultingItemsTableBuilder {

@Override
public ConfigurableTable buildConfigurableTable(String id)
throws WTException {
return new DistributingResultingItemsTableViews();
}
}

Customizing Change Management 1233


Create a Data Utility (Step 3)
Overview
What is different?
• You are rendering a column in a table of changeables (ie. parts, documents)
which represents a value on the binary link associating the changeable to the
change object.
• The value must be retained between:
○ Paging beyond the page limit
○ Sorting the table
○ Changing table views (which may not even display the column or the
row!)
○ Survive additions and removals to the table.
• The class ChangeLinkAttributeDataUtility has many helper
methods and provides useful customization points to extend to assist with
handling the above cases.
• For performance, using the ChangeLinkAttributeDataUtility will
cache the links for the method request so multiple attributes can be processed
efficiently.

Process
The following are the key points that are required to make a working change link
attribute data utility:
1. Extend the class ChangeLinkAttributeDataUtility.
2. Override the method createGuiComponent(String id,Object
datum,ChangeLinkAttributeBean linkBean); The
ChangeLinkAttributeBean is a specialized bean class to support
managing the links in the request.
3. Use linkBean.getObjectReference(datum) to get the
ObjectReference of the changeable from the datum (normalizes the
reference type for the table).
4. Leverage getGUIComponentId() to generate an ID for component based
on the reference object and the component ID.
5. Set the name and ID of the GuiComponent to the generated value above.
6. For in-place editable fields, call
super.setEventListener(component,linkBean); to setup a
listener to copy the edited value onBlur for the component.

1234 Customization Guide


7. Override retrieveValue(String id, BinaryLinklink); to
extract the attribute value from the link (for VIEW and initial EDIT
component modes).
8. To get the current value use retrieveValue( )
9. Override ProcessExistingLinks(NmOid oid,String
componentId) to load the links into the dataUtility.

Customizing Change Management 1235


Add Support for Multi-Edit Actions (Step 4)
In order to support multi-select actions in either a light-box or popup dialog, upon
dismissing the prompting window, it is important to ensure the data is properly
updated. The change link tables take advantage of a new table data manager store
that has been added to support:
• Retaining values when paging and sorting
• Efficient storage of values without serialization of DOM elements (only
META data)
• After edit, items should be placed in the table data manager store by accessing
the JavaScript method:
PTC.change.linkAttributeHelper.update(item, tableId);
• Item is a Javascript object made up of an id and value. The id should be of the
form:
rowOid#component_id (… VR:wt.part.WTPart:5556#regulatoryAffected)
• It is recommended to disable events while manipulating the data stores
(suspendEvents/resumeEvents)
• The table may be updated by calling the following if the table’s records are
committed in their store:
table.view.doPartialDataChange();

Example
The following code provides an example for the operations needed on completing
the editing multiple rows and updating the table.
01 function updateRecords(isChecked, componentId, tableId) {
02 var table = tableUtils.getTable(tableId);
03 var store = table.getStore();
04 store.suspendEvents();
05 var selections = table.getSelectionModel().getSelections();
06 for(var i=0,l=selections.length; i<l; i++) {
07 var record = selections[i];
08 record.data[componentId] = isChecked;
09 record.commit();
10 var oid = record.get('oid');
11 if(oid) {
12 var item = {
13 id : oid+SEP+componentId,
14 value : isChecked
15 };
16 PTC.change.linkAttributeHelper.update(item, tableId);
17 }
18 }
19 store.resumeEvents();
20 // re-draw displayed rows where data has changed.
21 table.view.doPartialDataChange();
22 }

1236 Customization Guide


23
Key to code sample:
• Line 04 – Suspend Events
• Line 08 – Updates text in table cell
• Line 13 – Generate ID readable by change data utilities and form delegates
• Line 16 – Store the data item in the Table Data Manager store
• Line 19 – Resume Events
• Line 21 – Visually update the table with just what changed

Process
In order to use a lightbox or popup dialog from the tables, the launch action must
be added to the actions list of the table.
1. Create a custom actions file based on ChangeManagement-
actions.xml, and register this file at the end of the property
“com.ptc.netmarkets.util.misc.defaultActions“ in
wt.properties.
2. Create a custom action models file based on ChangeManagement-
actionsModel.xml and register this file at the end of the property
com.ptc.netmarkets.util.misc.defaultActionmodels in
wt.properties.
3. Copy the change objecttype and only the desired actions to be overridden
to the custom actions.xml file. For this customization example use
“regulatoryAffected” and action “setRegulatoryAffected”
with selectRequired=“true”.
4. Set the command to onClick a JS function to launch your lightbox/popup
dialog.
5. Add the action “regulatoryAffected.setRegulatoryAffected”
in the custom actionModels.xml file.

Note
By overwriting the action model in a custom actionModels.xml, it is not
necessary to update the MVC table builder because it is already pointing to
this named action model.

Customizing Change Management 1237


Create a Form Delegate (Step 5)
Most of the change management wizard steps have a 1:1 mapping between the
table present on the step and the step themselves. The Change Task wizard is
different because it has two tables present. Each table is processed by its own
unique form delegate. The list of supported form delegates by table is listed
below.
Table Name / Step Name Supporting Classname
Affected Objects (Change Task) ChangeTaskAffectedItems
Affected Objects (PR, CR and Var.) FormDelegate
AffectedDataFormDelegate
Affected End-Items AffectedEndItemsFormDele
gate
Resulting Objects ChangeTaskResultingItems
FormDelegate
Associated Changes RelatedChangeItemFormDele
gate
Affected/Resulting Objects AffectedAndResultingItems
FormDelegate

It is recommended that you utilize a single form delegate / table. This keeps a
clean separation of step vs. table functionality. If you have embedded objects,
multiple tables or other scenarios using a step form delegate and delegating this to
the table/component sub form delegates is recommended.

Processing Global Attributes of the Link


To process attributes (global attributes or modeled attributes) for a change link
table the following is required:
1. Extend the out-of-the-box form delegate. This provides a lot of APIs and
plug-in points for extension as well as handle all of the existing attributes
(description, approved quantity, disposition etc.)
2. Override the processLinkAttributes(). This method is called after:
a. The binary links have been created.
b. The type definition reference is set on the link.
c. The link is saved along with the change object.

1238 Customization Guide


Note
The purpose of this method is to detect attributes that need to be modified on
the links, perform these attribute updates and return a collection of all the links
that were modified. These links are subsequently persisted as a collection.

Caution
It is important to only update attributes if they are detected as modified (or
cleared)

A new object PersistableAdapter which drastically reduces the amount of


code needed to process global attributes. The following code example uses this
API.
Several methods on the ChangeLinkAttributeHelper and
ChangeManagementClientHelper may prove useful in processing the
attributes and extracting FORM data using the changeable reference.

Sample Code
public class DistributingResultingItemsFormDelegate extends
ChangeTaskResultingItemsFormDelegate {

/**
* This method is used to post-process attributes on the change activity
* and change records.
* Note: In the example below we are not checking whether the change
* record is of the type DistributingChangeRecord. This could be done
* by comparing the Type Definition reference of the change record.
* However since this demo is focused on attribute manipulation using the
* new code>LWCNormalzedObject we have left it out for brevity.
*/
@SuppressWarnings("unchecked")
@Override
protected WTCollection processLinkAttributes(ChangeItemIfc item,
WTCollection binaryLinks) throws WTException {
WTCollection modifiedLinks = super.processLinkAttributes(item,
binaryLinks);
if (binaryLinks != null && !binaryLinks.isEmpty() && item instanceof
WTChangeActivity2) {
// The link bean has knowledge of how of link attributes and supports
the JCA interfaces.
ChangeLinkAttributeBean linkBean = ChangeLinkAttributeHelper.
getChangeLinkAttributeBean();
linkBean.setFormData(getObjectBean());

Customizing Change Management 1239


for(Iterator<ChangeRecord2> iter = binaryLinks.persistableIterator(ChangeRecord2
.class, true); iter.hasNext(); ) {
ChangeRecord2 record = iter.next();
// The getTableDataValue() will get the attribute from the FORM data
supporting any specific change table handlers
String value = ChangeLinkAttributeHelper.getTableDataValue
(DistributingChangeRecordConstants.DISTRIBUTION_ATTRIBUTE,
ChangeManagementClientHelper.getReference(record.getChangeable2()),
linkBean);
// The new LWC API for getting and setting attributes.
PersistableAdapter lwc = new PersistableAdapter(record, null, null, new
UpdateOperationIdentifier());
lwc.load(DistributingChangeRecordConstants.DISTRIBUTION_ATTRIBUTE);
Object currentValue = lwc.get(DistributingChangeRecordConstants.
DISTRIBUTION_ATTRIBUTE);
// Only set the attribute if it is different than the current value
if(( value != null && currentValue != null && !value.equals
(currentValue.toString())) || (value == null && currentValue != null) ) {
lwc.set(DistributingChangeRecordConstants.DISTRIBUTION_ATTRIBUTE, value);
lwc.apply();
// calling apply() will require verification, however since this form
delegate is setting the changes we can set it as verified.
try {
record.getPersistInfo().setVerified(true);
} catch (WTPropertyVetoException e) {
e.printStackTrace();
}
modifiedLinks.add(record);
}
}
}
return modifiedLinks;
}
}

Overriding the Step Form Delegate


To override the Affected/Resulting Objects wizard step form delegate:
1. Extend the class AffectedAndResultingItemsFormDelegate
2. Override either the method getAffectedDataFormDelegate() or
getResultingDataFormDelegate() and return your custom form
delegate for the table.
public class CustomAffectedAndResultingItemsFormDelegate extends
AffectedAndResultingItemsFormDelegate {

@Override
public ObjectFormProcessorDelegate getResultingDataFormDelegate() {
return new DistributingResultingItemsFormDelegate();
}

1240 Customization Guide


}

Customizing Change Management 1241


Register Form Delegate with Step (Step 6)
To update the form delegate for the step:
1. Create a custom actions file based on ChangeManagement-
actions.xml, and register this file at the end of the property
“com.ptc.netmarkets.util.misc.defaultActions“ in
wt.properties.
2. Copy the change objecttype and only the desired actions to be overridden
to the custom actions.xml. For the example in this presentation use
“changeTask” and action “affectedAndResultingItemsStep”.
3. Update the command class to point to the new form delegate created in Create
a Form Delegate (Step 5) on page 1238.
4. Other attributes (like the step JSP) can be updated if needed.
<?xml version="1.0"?>
<!DOCTYPE listofactionsSYSTEM '../../actions.dtd'>
<listofactions>

<objecttypename="changeTask" class="wt.change2.WTChangeActivity2"
resourceBundle="com.ptc.windchill.enterprise.change2.changeManagementActionsRB">
<action name="affectedAndResultingItemsStep"
id="affectedAndResultingItems" preloadWizardPage="false" required="false">
<description>Affected and resulting objects wizard step</description>
<command class="com.ptc.windchill.enterprise.custom.delegates.
CustomAffectedAndResultingItemsFormDelegate“
windowType="wizard_step"/>
</action>
</objecttype>
</listofactions>

1242 Customization Guide


Change Workflow Closure
This information details how to support closure for change object associations
using flexible change process associations.

Background
In prior releases change object associations were prescriptive in that problem
reports can associate to a change request and change requests to a change notice.
The supported API’s for closing the change objects are also specific to the
supported relationships. Flexible change process associations now allow for
configurable change object associations. Updated APIs are now available to fully
support flexible change process associations.
A change object is considered closed when the resolution date and resolved state
(i.e. Canceled or Resolved) are set on a change object. The two ways to close
change objects are forced and synchronized closure. Synchronized closure is when
a change object listens for an event and checks to see if it can close itself. Forced
closure is when a different change object’s workflow process closes another
related change object, forcing the state and resolution date to be set. For most
cases synchronized closure is a better practice as this technique avoids dead lock
and stale object issues that can sometimes occur when using forced closure for
change objects having their own workflow process.

Scope/Applicability/Assumptions
The scope of this information is to outline recommendations for supporting
closure of change object associations using flexible change links.

Intended Outcome
The intended outcome of this information is to help provide guidance on how to
configure workflows to work with flexible change process associations.

Solution
There are APIs and Change Events available to support closure of Change Objects
associations using flexible links.
The Related Information on page 1252 section includes references to the APIs and
code samples.

Prerequisite Knowledge
To complete this process you must have an understanding of the following
• Basic development involving JAVA
• Defining workflow expressions

Customizing Change Management 1243


Solution Elements
Element Type Description
com.ptc.windchill. Class This class contains static
pdmlink.change.server. methods to support the
impl. change management
WorkflowProcessHelper workflow processes. The
static methods in this
class are intended to be
called by routing
expressions and
synchronization robot
expressions.
wt.change2. Class The flexible change
ChangeProcessLink association link class.
wt.change2.AddressedBy Class Deprecated association
link for Change Request
to Change Notice.
wt.change2. Class Deprecated association
FormalizedBy2 link for Problem Reports
or Variances to Change
Request.
handlesClosure boolean A Boolean property that
can be specified as a
workflow template
property variable to
specify if a change object
workflow process is able
to close itself.
CHILD_CHANGE_ ChangeService2Event The state was changed on
OBJECT_STATE_ child change object. The
CHANGE event target contains the
parent change object and
have the child as a
secondary target
PARENT_CHANGE_ ChangeService2Event The state was changed on
OBJECT_STATE_ parent change object. The
CHANGE event target contains the
child change object and
have the parent as a
secondary target.
isRelatedParentsInStates WorkflowProcessHelper Looks up the related

1244 Customization Guide


Element Type Description
API parent change objects and
determines if each one is
in one of the given states.
isRelatedChildrenInStates WorkflowProcessHelper Looks up the related child
API change objects and
determines if each one is
in one of the given states.
setResolutionDate WorkflowProcessHelper This method sets the
API resolution date of a
change object. It does not
set the resolution state.
closeChangeChildren WorkflowProcessHelper Looks up the children of
API the given change object
and closes them with the
given states.
closeChangeParents WorkflowProcessHelper Looks up the parents of
API the given change object
and closes them with the
given states.

Customizing Change Management 1245


Procedure – Update Workflow to use Synchronized Closure
The following example will start with a basic workflow that goes from Under
Review to Resolved state after a review task is completed with synchronized
closure.

1. Select the workflow template Properties link. Go to the Variables tab and add a
new boolean variable named handlesClosure with the default value set to
true.

2. Add a new Synchronize expression between Review Task and Set State
Resolved.

1246 Customization Guide


3. Update the new Synchronize expression to synchronize on an “Object Event”.
Select either the “PARENT CHANGE OBJECT STATE CHANGE” or
“CHILD CHANGE OBJECT STATE CHANGE” event. See Solution on page
1243 for descriptions of each event. Add one of the following two expressions
in the Initial Expression and Routing Expression:
• When listening for “PARENT CHANGE OBJECT STATE CHANGE”:
if(com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.
isRelatedParentsInStates (primaryBusinessObject,
new String[]{"RESOLVED"})) {
result = "Resolved";
}
• When listening for “CHILD CHANGE OBJECT STATE CHANGE”:
if(com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.
isRelatedChildrenInStates(primaryBusinessObject,
new String[]{"RESOLVED"})) {
result = "Resolved";
}

Note that the role A of the change object relationship is considered to be the
parent and the role B is the child object.

Customizing Change Management 1247


4. Add a new Expression between Synchronize and Set State Resolved. Set its
name to “Set Resolution Date”.

5. Update “Set Resolution Date” to set the resolution date on the change object.
com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.
setResolutionDate(primaryBusinessObject);

1248 Customization Guide


6. If force closure is required for the change process a new Expression can be
added after “Set State Resolved” to close either the parent or child
associations. The following is an example expression implementation which
forces the associated parent change objects to close in the Resolved state.
java.util.Map<java.lang.Class, wt.lifecycle.State> parentStateMap = new
java.util.HashMap<java.lang.Class, wt.lifecycle.State>(1);
parentStateMap.put(wt.change2.FlexibleChangeItem.class,
wt.lifecycle.State.toState("RESOLVED"));
com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.
closeChangeParents(primaryBusinessObject, parentStateMap);

Customizing Change Management 1249


Deprecated Link Support
The deprecated wt.change2.AddressedBy2 and
wt.change2.FormalizedBy links are also supported by the new change
workflow closure APIs and events. Any custom workflow processes can be
updated prior to using Flexible change process links. The provided example
change workflow process templates support both the new change process
associations and the deprecated associations.
Review the following table in order to determine which APIs and events to use for
the deprecated links:
Deprecated Link Parent Child
wt.change2. Change Request Change Notice
AddressedBy2
wt.change2. Problem Report or Change Request
FormalizedBy Variance

Limitations
Old and New Workflow Processes
In some cases, old workflow processes can be configured to work with new
workflow processes. For example, Problem Reports or Variances that complete
their workflow process after being approved can still work with a new Change
Request workflow, but the Change Request workflow process will still need to
call the force close on the parent associations. If the Problem Reports or Variances
with a new workflow process are also associated they will not be forced to closed
when the handlesClosure is set to true. The Change Request workflow
process template provided in Windchill Release 11.0 is configured to support both
the previous release and new Problem Report and Variance workflow processes.
Using the force closure API on existing associated change object processes that
already have synchronized closure will likely cause unexpected results. For
example, the Change Request workflow process already has a synchronized
closure for when the Change Notice is resolved. If the Change Notice workflow
process was updated to force close the parent associations, then additional
sequences in the Change Request process such as locking annotations would not
happen.

Required Updates to the Change Request Workflow Process


The Change Request workflow process must be updated in order for it to work
with the flexible change process associations. The
ChangeService2Event.CN_STATE_CHANGED is no longer supported with
flexible change process associations. The event will still work for the deprecated
wt.change2.AddressedBy2 associations.

1250 Customization Guide


Closure with Multiple Associations
Direction of closure should be considered when determining which change object
types are defined as the parent (role A) and child (role B) role of the flexible
change process association. Note that the owning role can be defined separately
from the parent or child role. For example, given the following relationships:
• Problem Reports associate to Change Requests
• Change Request associate to Change Notices
The recommendation is to use the direction of closure when defining the
association rules. Defining the association rule in the direction of closure
guarantees that the Change Request waits for all associated Change Notices to
close and a Problem Report waits for all associated Change Requests to close. If
the Change Request is considered to be the owner role for both associations then
consider defining the change process association rules with the roles defined in the
direction of closure as follows:
Role A (Parent) Role B (Child) Owner Role
Problem Report Change Request Role B
Change Request Change Notice Role A

Additional considerations are required if the rules are not defined in the direction
of closure. Consider the following changes to the rule definitions:
Role A (Parent) Role B (Child) Owner Role

Change Request Problem Report Role A


Change Request Change Notice Role A

If the general isRelatedChildrenInStates API is used in the Change


Request workflow process without specifying a specific change object type it
would result in the Change Request waiting for the Problem Reports to close. The
Problem Report workflow process is also waiting for the Change Request to close
resulting in a closure deadlock. In order to prevent closure deadlock the specific
change object types should be specified when using the
isRelatedChildrenInStates API. In the Change Request workflow
process the Change Notice type should be specified so that the associated Problem
Reports are ignored.

Customizing Change Management 1251


Related Information
Sample Code
Example change object workflow templates are provided within Windchill. They
can be found by navigating to Site ▶ Utilities ▶ Workflow Template Administration.

Related Package/Class Javadoc


• com.ptc.windchill.pdmlink.change.server.impl.Work
flowProcessHelper

1252 Customization Guide


Flexible Change Links for Query Builder
You have an existing report that displays Legacy Change Associations
(wt.change2.FormalizedBy or wt.change2.AddressedBy2) and you
need to convert the report to display Associated Process or Associated Reference
Objects (Flexible Change Associations).

Scope/Applicability/Assumptions
The scope of this information is to outline recommendations for creating a Query
Builder Report that displays Flexible Change Associations to replace a report
displaying the Legacy Change Associations (wt.change2.AddressedBy2 or
wt.change2.FormalizedBy).

Intended Outcome
The intended outcome of this information is to help provide guidance on how to
create a report template that uses Flexible Change Links to display Flexible
Change Associations.

Solution
New link types are available to support a Query Builder Report Template for
associated Change Objects using Flexible Change Links.

Prerequisite Knowledge
To complete this process you must have an understanding of the following:
• Flexible Change Links
• Associated Change Objects
• Report Templates
• Change Objects

Solution Elements
Element Type Description
wt.change2. Class Abstract link for flexible
FlexibleChangeLink associations between two
FlexibleChangeItem
objects.
FlexibleChangeItem
objects include Problem
Reports, Variances,
Change Requests, and
Change Notices.
wt.change2. Class Link for flexible process

Customizing Change Management 1253


Element Type Description
ChangeProcessLink associations between two
FlexibleChangeItem
objects.
wt.change2. Class Link for flexible
ChangeReferenceLink reference associations
between two
FlexibleChangeItem
objects.
wt.change2. Class Deprecated association
FormalizedBy link for Problem Reports
or Variances to Change
Request.
wt.change2. Class Deprecated association
AddressedBy2 link for Change Request
to Change Notice.

1254 Customization Guide


Procedure – Creating Report Template for
Displaying Flexible Change Associations
Existing Report
The following example represents a report you currently have that displays
Change Requests associated to Problem Reports through the Formalized By link.

Customizing Change Management 1255


Creating a New Report
The following steps create a new report to replace the report in the above
example. This report shows all Problem Reports linked to Change Requests
through the Change Process Links.
1. Create a new report template by navigating to Site ▶ Utilities ▶ Report
Management, then by clicking New Report Template. In the Properties tab give
the template a name.

2. Select the Tables and Joins tab. Click the Add button. Search and select
Change Process Link, then click OK.

1256 Customization Guide


3. Click the Add button again and this time select Problem Report and click OK.

4. Click the Add button again and this time select Change Request and click OK

5. Click and hold the yellow box in the bottom right corner of the Problem
Report box. Drag and drop over the Change Process Link Box. This should
bring up the Create Join Wizard.

Customizing Change Management 1257


6. Select Role A Object Ref (from Change Process Link) and click OK.

7. Create another join between Change Request and Change Process Link.

8. Select Role B Object Ref (from Change Process Link) and click OK

1258 Customization Guide


9. Switch to the Select or Constrain Tab. Click the add drop down near the top
left corner. Select Reportable Item to get the Select Attributes to Add pop up.

10. Add the columns you would like to see on the report.

Customizing Change Management 1259


11. Click Apply and then select View Report

12. Click the Generate Button

1260 Customization Guide


Report displaying Change Reference Links
When creating this report template follow the steps above but select the Change
Reference Link table instead of the Change Process Link table.

Report displaying both Change Process Links and Change Reference


Links by using Flexible Change Associations
When creating this report template follow the steps above but select the Flexible
Change Association table instead of the Change Process Link table.

Customizing Change Management 1261


Limitations
Separate Reports for Legacy and Flexible Change Associations — Creating one
report to display both Legacy Change Associations and Flexible Change
Associations is not supported using the Query Builder UI.

1262 Customization Guide


28
Business Rules
Customizing Business Rules .................................................................................. 1264
Bypassing Business Rules ..................................................................................... 1284
Loading Business Rule Objects .............................................................................. 1291

This section contains information on how to create business rules to provide


custom validation logic for objects.

1263
Customizing Business Rules
You can create business rules to provide custom validation logic for objects in
PDMLink. These rules are used to determine eligibility of an object to go through
defined checkpoints in the change management or promotion processes. You can
require feedback on the result of the evaluation. The business rules validation is
scalable and configurable.
Business Rules offer a validation framework which can be utilized within
workflow execution. For example, before objects are released through the Change
Notice workflow, you must ensure that none of the Resulting Objects are checked
out. You can make a Business Rule to perform this validation.
This section focuses on the Business Rules Engine and provides a few working
examples.

Intended Outcome
After going through this information, you should be able to start using the rules
that are provided with Windchill 10.1 M010, or you should be able to create
custom business rules for your change process.
You will then be able to use business rule sets and rules to validate that the objects
are valid to be processed.

Prerequisite knowledge
To apply this information, you need to have an understanding of the following:
• Basic development involving Java and XML
• The management of Windchill properties
• Business Rules (see the “Business Rules” chapter of Windchill Administration
- Configuring Your Windchill Environment for more information)

Solution Elements
Element Type Package Description
BusinessRuleSet Java class wt.businessRules A BusinessRuleSet
instance is the
configuration used
to navigate a set of
business rules for a
container.
BusinessRule Java class wt.businessRules BusinessRule will
hold the
information about
the rule to be
executed. Each

1264 Customization Guide


Element Type Package Description
rule may have
unique
configuration
requirements
associated to it.
BusinessRuleLink Java class wt.businessRules An
ObjectToObject
binary link holding
the references to
BusinessRuleSet
and BusinessRule.
Each
BusinessRuleSet is
associated to
BusinessRules
using
BusinessRule-
Links.
BusinessRule- Java Class wt.businessRules Helper for the
sHelper business rules
service and engine.
BusinessRulesEn- Java Class com.ptc.core. The business rules
gine businessRules. engine will execute
engine the validation of
each business rule
in order as defined
by the execution
plan set in the
business rule set.
BusinessRuleSet- Java Class com.ptc.core. Used to specify
Bean businessRules. more than one
engine business rule set
and target
collection
relationship key at
a time in order to
generate an
accumulation of
results with one
call to the business
rule engine.

Business Rules 1265


Element Type Package Description
RuleValidationCri- Java Class com.ptc.core. Contains
teria businessRules. information that is
validation used by all
business rules
within a business
rule set.
RuleValidation Java Class com.ptc.core. Interface for the
businessRules. business rule
validation validators. Custom
validators should
implement this
interface.
RuleValidationRe- Java Class com.ptc.core. Contains one
sult businessRules. validation output
validation per business rule.
It contains a rule
validation key to
indicate the
business rule that
was executed. It
will hold a
validation status
attribute to indicate
if the business rule
successfully
passed the
validation or not.
The
RuleValidationRe-
sult will also
contain the target
object, which links
the result to a
specific
WTReference, and
a list of feedback
messages which
contains text that
could optionally be
displayed in a
report.

1266 Customization Guide


Element Type Package Description
RuleValidationRe- Java Class com.ptc.core. A set of
sultSet businessRules. RuleValidationRe-
validation sult objects.
BusinessRuleSe- Java Class com.ptc.core. Used to get the
tRelationshipDele- businessRules. seed objects for a
gate relationship primary business
object that is to be
evaluated for a
particular business
rule set.
Relationship
delegates are
registered in
service.properties.
See the “Retrieval
of Seed Objects”
for more
information on
these delegates.

Creating Business Rules


See the “Business Rules” chapter of Windchill Administration - Configuring Your
Windchill Environment for details on how create, modify and remove business
rule sets, business rules, and business rule links.

Business Rules Configuration and Execution


The business rules engine executes the registered rules in a business rule set and
return validation results. The business rules engine retrieves the set of business
rules given the specified business rule set unique keys and the container references
from the seed objects. With the set of business rules, the engine executes them
against the seed objects.
The following phases describe the execution of business rule sets by the business
rules engine:
1. Retrieves the specified seed objects to be validated
2. Retrieves the business rule sets

Business Rules 1267


3. Generates and executes an execution plan for the business rule sets
4. Reports of the results of the plan executed.

1268 Customization Guide


Business Rules Execution Flow

Business Rules 1269


Calling the Business Rules Engine
There are examples in the default Change Notice and Promotion Request
workflows that show how to call the business rules engine from a workflow. The
default Change Notice workflow comes with two different conditionals which call
the business rules engine. If there are any failures, the Audit Change Notice Task
will show a link called “View Conflicts” on the task. The Audit Change Notice
Task allows you to proceed without fixing the failures. Similarly, the Resolve
Release Conflicts Task shows the conflicts if there are any. You must fix the
problems before proceeding on this task.

Here is another example of how you might want to set up a rework loop in the
Promotion Request Approval Process. The Business rule is executed in the OR
conditional. If it fails, then an email is sent and the Rework Promotion Request
task appears.

1270 Customization Guide


There are two supported APIs to execute business rule sets.
• BusinessRulesHelper.engine.execute(primaryBusinessOb
ject, BusinessRuleSetBean[]) : RuleValidationResultSet
The second option allows for overriding the container for all objects regardless
of the container that the seed objects are in. This API requires that the seed
objects be specified up front and only supports executing one business rule set
at a time.
• BusinessRulesHelper.engine.execute(“Business rule
set”, RuleValidationCriteria) :
RuleValidationResultSet
See Javadoc for more details.

Retrieval of Seed Objects


The relationship delegate is used to get the seed objects for a primary business
object that is to be evaluated for a particular business rule set. All relationship
delegates implement the RuleValidation interface.

Business Rules 1271


Relationship delegates are registered in service.properties. The following
is an example of a delegate for getting the resulting objects for a primary object:
<Service context="default" name="com.ptc.core.businessRules.relationship.
BusinessRuleSetRelationshipDelegate">
<Option serviceClass="com.ptc.core.businessRules.relationship.
ResultingObjectsRelationshipDelegate"
selector="wt.change2.ChangeRecord2"
cardinality="singleton"
requestor="null"/>

The selector is the relationship key which is used to look up the relationship
delegate instance. The relationship key naming convention is to use the link class
name but is not a requirement. Note that if the relationship delegate returns the
links for the relationship, then the role B objects of the links will be used as the
seed objects. The target link role can be optionally specified in the
BusinessRuleSetBean or RuleValidationCriteria. See the Javadoc
for BusinessRuleSetBean for details on how to specify the relationship for a
business rule set and current supported relationship delegates.
The following table shows the default delegates that are provided in a standard
Windchill installation:
Relationship Relationship Delegate Description
wt.change2. com.ptc.core. Gets the affected object
AffectedActivityData businessRules. links of the primary
relationship. business object if it is a
AffectedObjectsRelation- change notice or change
shipDelegate task.
wt.change2. com.ptc.core. Gets the affected object
ReportedAgainst businessRules. links of the primary
relationship. business object if it is a
AffectedObjectsRelation- problem report or
shipDelegate variance.
wt.change2. com.ptc.core. Gets the affected object
RelevantRequestData businessRules. links of the primary
relationship. business object if it is a
AffectedObjectsRelation- change request
shipDelegate
wt.change2. com.ptc.core. Gets the resulting object

1272 Customization Guide


Relationship Relationship Delegate Description
ChangeRecord2 businessRules. links of the primary
relationship. business object if it is a
ResultingObjectsRela- change notice or change
tionshipDelegate task.
wt.change2.IncludedIn2 com.ptc.core. Gets the change tasks of
businessRules. the primary business
relationship. object if it is a change
IncludedInRelationship- notice or the change
Delegate notice if the primary
business object is a
change task.
wt.maturity. com.ptc.core. Gets the baseline items of
MaturityBaseline businessRules. the primary business
relationship. object if it is a promotion
MaturityBaselineObjects- notice.
RelationshipDelegate
wt.maturity. com.ptc.core. Gets the promotion seeds
PromotionSeed businessRules. of the primary business
relationship. object if it is a promotion
PromotionSeedObjects- notice.
RelationshipDelegate
wt.maturity. com.ptc.core. Gets the promotion
PromotionTarget businessRules. targets of the primary
relationship. business object if it is a
PromotionTargetObjects- promotion notice.
RelationshipDelegate

Retrieval of the Business Rule Set Based on Container


The following information is required to obtain a business rule set from the
system:
1. The unique key for a business rule set
2. The container reference of which the rules should be evaluated
The business rules engine will be responsible for acquiring the appropriate
business rule set from the Windchill services. The business rule sets will be
discovered using a hierarchical container lookup. Business rule sets that are not
enabled will be ignored.

Business Rules 1273


The following flow chart explains flow of the container look up for a rule set key
and a container.

Executing the Business Rule Set Execution Plan


The generation of the execution plan of a business rule set will involve:
1. Creation of a specific RuleValidation instance based on the selector
defined in the business rule.
2. The RuleValidation instance will be used to determine if the
configuration of the business rule is valid using the
isConfigurationValid method. If the configuration is not valid, the
RuleValidation will be skipped for the business rule set execution plan
and error will be logged.
3. For each business rule the RuleValidation instance is called with the
following items:
a. Collection of objects that rules are to evaluate
b. Context specific criteria (such as the container reference) that may be used
by a RuleValidation to configure its execution.
4. The RuleValidation instance is added to the execution plan.
All the business rule validators will implement the RuleValidation interface.
A typical business rule will fall under two primary categories:

1274 Customization Guide


• Simple validation: The rules check is done on the business object itself or on
the seed objects as configured by the relationship. An example could be
checking for attribute validation or checking a life cycle state of the object
prior to release.
• Structured validation: The rules may or may not be performed on the business
objects but will include some validation checks on its associated objects like
the children of the part or document. In this type of validation, typically more
complex set of algorithm might be required to calculate the business validation
rules and populate the validation result with appropriate flag. An example of
structured validation rule is a validation check that makes sure that all
resulting objects and all first level dependents are in the correct state.
The following are supported RuleValidation implementations that are
provided with the default Windchill installation:
Business Rule RuleValidation Description
Selector
CHECKOUT_RULE com.ptc.core. Validates that objects are
businessRules.validation.
not checked out or
CheckoutRuleValidator
checked out to a project.
RELEASE_TARGET com.ptc.core. Ensures that all
businessRules.validation.
“Resulting Objects” are at
ReleaseTargetValidator
an appropriate state for
release and have an
appropriate change
management transition
specified that is consistent
with the assigned
lifecycle transition rules.
ATTRIBUTE_RULE com.ptc.core. Validates that the
businessRules.validation. specified attribute rule
AttributeRuleValidator configuration for an
object type is valid.
BOM_RELEASE_RULE com.ptc.core. Ensures that all resulting
businessRules.validation. objects are at an
BOMReleaseRuleValida- appropriate state and all
tor their first level children
are at an appropriate state.

Business Rules 1275


Note
As of the 11.0 release, the Promotion Request supports the Attribute Rule and
the Check Out rule. The Change Notice supports any rule.

The instantiation of the RuleValidation will be based on the selector defined


in the business rule. Application services will be used to lookup the implementing
class for the defined selector. If no implementing class is defined, or the class fails
to be instantiated an error will be logged.
Prior to executing any validation the engine will call the
RuleValidation.isConfigurationValid which will determine if the
business rule configuration is valid. This validation of the business rule
configuration is also called when loading the business rule (see Creating Business
Rules on page 1267), but since it is possible to change the registered
RuleValidation, validation of configuration is also called prior to executing
the business rule validation.
TheRuleValidation initialization method called prepare is used to
perform some initial preprocessing of the entire set of seed objects that will be
validated against the set of business rules. This is to allow any pre-validation to
occur within the Windchill server (example might be retrieving the lifecycle
template which would be common to many of the items). It is best to call multi-
object APIs from the RuleValidation.prepare method. It is advised not to
use the RuleValidation.peformValidation method to perform multi-
object calls.
If the method RuleValidation.isConfigurationValid returns true,
the RuleValidation performValidation is called for each seed object.
The seed object is passed inside the RuleValidationObject. The
RuleValidationObject holds the target object (the seed object if it is not a
link or the role A or role B if seed object is a link) and the link (if the seed object
is a link). When the business rule is a structured type RuleValidation, the
RuleValidationObject also contains the collected children and a map of
the collected children to the links that they were collected with. The
performValidation should always return a new
RuleValidationResult that has a reference to the target object and not the
link.

1276 Customization Guide


Business Rules Engine and Sequence Diagram

Business Rules 1277


Business Rules Engine and Validation Interaction Diagram

RuleValidation implementations are registered in


service.properties. To create or override a RuleValidation
implementation, add the following to a custom service.properties xconf
file:
<Service context="default" name="com.ptc.core.businessRules.validation.
RuleValidation">
<Option serviceClass="com.ptc.core.businessRules.validation.
CheckoutRuleValidator"
selector="CHECKOUT_RULE"
cardinality="singleton"
requestor="null"/>
</Service>

When possible the cardinality of the RuleValidation should be set to


“singleton” in order to reduce the number of instances of a particular
RuleValidation implementation. The
RuleValidationKey.processingMap can be used for storing pre-
validation data in order to support thread safe processing of RuleValidation
implementations when the cardinality is set to “singleton”.

1278 Customization Guide


Returning Results
The single validation result is generated for each target object that is evaluated is
combined into an aggregated set of validation results
(RuleValidationResultSet). The RuleValidationResultSet may
contain only partial results if there are failures during the execution of the
business rule set. The business rules engine may be invoked with an optional
parameter indicating that the execution plan should abort further rule validation
upon hitting a failure in a rule. Since the failure could occur in different rules for
different objects, the execution plan will continue to the next seed object if the
failure on error flag is set. The caller of the business rules engine must determine
which mode the execution plan so execute in.
To show the results of the business rule sets on a workflow task, you need to
create a workflow variable named businessRulesResultSetGlobal and
set the type to serialized string of the validation result set. Then, for any task that
you want to show the results in, you should create a new workflow variable on
that task named businessRulesResultSet. On the InitializeFrom
field, you should set the value to be businessRulesResultSetGlobal,
and the copy into should be businessRulesResultSet. This copies the
global value into the current task value so that history can be maintained on the
workflow task results. Use BusinessRulesHelper.serialize to create a
serialized string of the validation result set. When the
businessRulesResultSetGlobal is set a “View Conflicts” report link
icon will display as part of the subject in the workflow task. To see the report of
the evaluated business rule sets click on the “View Conflicts”.

Audit Change Notice with View Conflicts

Business Rules 1279


Business Rule Set Validation Report

Limitations
The execution of business rules in Windchill release 10.1 M010 is a single
threaded operation.

Sample Code
The following is an example of the workflow conditional syntax in the delivered
Change Notice workflow template. The workflow conditional makes a call to the
business rules engine for the CHANGEABLE_PRE_RELEASE business rule set.
The CHANGEABLE_PRE_RELEASE business rule contains the CHECKOUT_
RULE and RELEASE_TARGET business rules.

Routing Expression
result = "NOT_READY";

com.ptc.core.businessRules.engine.BusinessRuleSetBean[] ruleSetBeans =
new com.ptc.core.businessRules.engine.BusinessRuleSetBean[] {
com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean("CHANGEABLE_PRE_RELEASE", "wt.change2.ChangeRecord2")
};

1280 Customization Guide


//Invoke the business rule engine
com.ptc.core.businessRules.validation.RuleValidationResultSet resultSet =
wt.businessRules.BusinessRulesHelper.engine.execute(primaryBusinessObject,
ruleSetBeans);

if ( !resultSet.hasResultsByStatus(com.ptc.core.businessRules.validation.
RuleValidationStatus.FAILURE)) {
result = "PROCEED";
}
else {
//This line of code will start exception handling for the business
rules that failed
businessRulesResultSetGlobal = wt.businessRules.BusinessRulesHelper.
serialize(resultSet);
preReleaseConflictsMsg = new wt.util.WTMessage("com.ptc.windchill.
enterprise.change2.change2ClientResource", com.ptc.windchill.enterprise.
change2.change2ClientResource.BUSINESS_RULES_PRERELEASE_VALIDATION_MSG,
null).getLocalizedMessage();
preReleaseConflictsMsg = preReleaseConflictsMsg + "\n" + resultSet.
getFailedRulesMessage(java.util.Locale.getDefault());
}
Note that if the validation results are not successful, the attribute
businessRulesResultSetGlobal is set to the serialized string of the
validation result set. The “View Conflicts” report link will show up on the “Audit
Change Notice” and “Resolve Release Conflicts” workflow task pages.

Business Rules 1281


Customization Example of Multiple Rules, Rule Sets, and
Relationships
Here is another example of how you might configure rules against multiple
products and multiple relationships. In this case, there are 4 rules, 4 rule sets and 4
containers.

After all the rules are created, you could configure the workflow to use these rule
sets by using some code that looks like this:
com.ptc.core.businessRules.engine.BusinessRuleSetBean[] ruleSetBeans =
new com.ptc.core.businessRules.engine.BusinessRuleSetBean[] {
com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean("CNOrgRuleSet",
com.ptc.core.businessRules.engine.BusinessRuleSetBean.PRIMARY_BUSINESS_OBJECT),
com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean("AffectedPartProdRuleSet",
wt.change2.AffectedActivityData.class.getName()),
com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean("ResultingPartProdRuleSet",
wt.change2.ChangeRecord2.class.getName())
};
com.ptc.core.businessRules.validation.RuleValidationResultSet
resultSet = wt.businessRules.BusinessRulesHelper.engine.execute(primaryBusinessObject,
ruleSetBeans );

Examples
If we had a part in Product 1 that was a Resulting Object, the part would have to
have a part name less than 10 characters, and it could not be checked out.
If we had a document in Product 2 that was a resulting object, then there are no
rules for it. This is because there are only rules for Parts.

1282 Customization Guide


Troubleshooting Configuration Issues
In order to troubleshoot configuration issues, it is recommend that you enable the
following loggers on the Method Server.
1. Navigate to <Windchill>\codebase\WEB-INF.
2. Open log4jMethodServer.properties with a text editor.
3. Add the following code to enable the appropriate loggers:
• To view potential configuration issues, such as rules or rule sets not being
found in a container, enable this logger:
log4j.logger.com.ptc.core.businessRules.engine=
WARN
• To view potential performance issues, such as execution time of a business
rule validation, enable this logger:
log4j.logger.com.ptc.core.businessRules.engine=
TRACE
• To view what rules are invoked by the business rules framework, set the
level to:
log4j.logger.com.ptc.core.businessRules.engine=
INFO
• To set the debug mode back to default, set the following logger, or just
remove what was previously added:
log4j.logger.com.ptc.core.businessRules.engine=
ERROR
4. Reboot your Method Server.

Business Rules 1283


Bypassing Business Rules
You want to be able to initially show some or all business rule failures but only
some business rule failures should prevent the workflow process from continuing
or completing.

Example Use Case 1


You want to check that certain attributes are filled in (e.g. Material), but it’s ok if
the attributes are blank but the life cycle state check must pass.

Example Use Case 2


You have requirements that the Material and Weight attributes have to be filled in
for parts. The part Number needs to start with PTC- and have a length of ten. The
part attributes such as Finish and Description should be filled, but if they are
blank, you should only get a warning.
This document assumes you have customized business rule sets and rules defined
that you would like to run as part of the workflow process.

Solution
Create two business rule sets. One of the business rule sets has business rules that
are required to continue or complete the workflow process. The second business
rule set has business rules that you want reported but are not required to continue
the workflow process. Having two separate business rule sets will allow you to
configure a workflow process that allows you to call both or one of the business
rule sets at different points in the workflow process. The workflow process can be
configured to execute all required and non-required business rule sets for a
workflow task such as the Change Notice Audit task.
This task is configured to continue once it has been completed For more
information see Execute All Required and Non-Required Business Rule Sets on
page 1287. A second workflow task in the process can be configured to execute
only the required business rule sets.This task will continue to be generated until all
errors are resolved. For more information see Execute Required Business Rule
Sets on page 1288.

Example
The following example uses Example Use Case 1 from above to show how to
create two sets of rules to execute in a change notice workflow process. The
example shows how to configure a set of rules to be required to proceed in the
workflow process and a second set of rules that are not required but shown as
informational data.

1284 Customization Guide


Create a Non Required Business Rule Set for the Attribute
Checks
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:10001</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=Demo Organization/
wt.pdmlink.PDMLinkProduct=Example1TestProduct</objectContainerPath>
<key>EXAMPLE1_NON_REQUIRED_ATTRIBUTE_RULE_SET</key>
<name>EXAMPLE1_NON_REQUIRED_ATTRIBUTE_RULE_SET</name>
<description>EXAMPLE1_NON_REQUIRED_ATTRIBUTE_RULE_SET</description>
<enabled>true</enabled>
<overridable>true</overridable>
<updateIfExists>true</updateIfExists>
</BusinessRuleSet>

Create an Attribute rule for Material


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:10002</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=Demo Organization/
wt.pdmlink.PDMLinkProduct=Example1TestProduct</objectContainerPath>
<key>EXAMPLE1_ATTRIBUTE_RULE</key>
<selector>ATTRIBUTE_RULE</selector>
<name>Example 1 Attribute Rule</name>
<description>Example 1 Attribute Rule</description>
<enabled>true</enabled>
<updateIfExists>true</updateIfExists>
<configs>
<config name="objectType" value="com.ptc.Part"></config>
<config name="Material" value="SET"></config>
</configs>
</BusinessRule>

Create a Link for the Attribute Rule and Non Required Rule
Set
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:10003
</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:10001
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:10002
</localId></ObjectReference></rule>
<blockNumber>1</blockNumber>
<updateIfExists>true</updateIfExists>
</BusinessRuleLink>

Business Rules 1285


Create a Required Business Rule Set for Release Target
Rule
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:20001
</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=Demo Organization/
wt.pdmlink.PDMLinkProduct=Example1TestProduct</objectContainerPath>
<key>EXAMPLE1_RELEASE_RULE_SET</key>
<name>Example1_ReleaseRuleSet</name>
<description>Example1_ReleaseRuleSet</description>
<enabled>true</enabled>
<overridable>true</overridable>
<updateIfExists>true</updateIfExists>
</BusinessRuleSet>

Reload Site Release Target Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:20002</localId></ObjectID>
<key>RELEASE_TARGET</key>
<selector>RELEASE_TARGET</selector>
<name>com.ptc.windchill.enterprise.change2.change2ClientResource:
RELEASE_TARGET_RULE_NAME</name>
<description>com.ptc.windchill.enterprise.change2.change2ClientResource:
RELEASE_TARGET_RULE_DESC</description>
<enabled>true</enabled>
<updateIfExists>true</updateIfExists>
</BusinessRule>

Create Link for the Target Rule and Required Rule Set
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:20003</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:20001
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:20002
</localId></ObjectReference></rule>
<blockNumber>1</blockNumber>
<updateIfExists>true</updateIfExists>
</BusinessRuleLink>

1286 Customization Guide


Execute All Required and Non-Required Business Rule Sets
In order to display all required and not required rule conflicts update the Audit
Change Notice workflow task conditional to use both rule sets EXAMPLE1_
RELEASE_RULE_SET and EXAMPLE1_NON_REQUIRED_ATTRIBUTE_
RULE_SET.

if (wt.change2.ChangeHelper2.isTrackingChange((wt.inf.container.WTContained)
primaryBusinessObject)) {
result = "Revisioning Enabled";
}else {
result = "Revisioning Disabled";
}
com.ptc.core.businessRules.engine.BusinessRuleSetBean[]
beans = new com.ptc.core.businessRules.engine.BusinessRuleSetBean[] {

// Configure to call non-required rule set


com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean
("EXAMPLE1_NON_REQUIRED_ATTRIBUTE_RULE_SET",
"wt.change2.ChangeRecord2"),

// Configure to call required rule set


com.ptc.core.businessRules.engine.BusinessRuleSetBean.newBusinessRuleSetBean
("EXAMPLE1_RELEASE_RULE_SET", "wt.change2.ChangeRecord2")
};
com.ptc.core.businessRules.validation.RuleValidationResultSet

Business Rules 1287


resultSet = wt.businessRules.BusinessRulesHelper.engine.execute
(primaryBusinessObject, beans);
if ( resultSet.hasResultsByStatus(com.ptc.core.businessRules.
validation.RuleValidationStatus.FAILURE)) {
businessRulesResultSetGlobal = wt.businessRules.BusinessRulesHelper.
serialize(resultSet);
preReleaseConflictsMsg = new wt.util.WTMessage("com.ptc.windchill.
enterprise.change2.change2ClientResource",
com.ptc.windchill.enterprise.change2.change2ClientResource.
BUSINESS_RULES_PRERELEASE_VALIDATION_MSG, null)
.getLocalizedMessage();
preReleaseConflictsMsg = preReleaseConflictsMsg + "\n" +
resultSet.getFailedRulesMessage(java.util.Locale.getDefault());
}
The following is an example shows the conflicts on the Audit Change Notice
workflow task.

Execute Required Business Rule Sets


In order to prevent the Change Notice workflow process from proceeding for the
required business rules update the conditional to only use the required rule set
EXAMPLE1_RELEASE_RULE_SET for the Resolve Release Conflicts workflow
task.

1288 Customization Guide


result = "NOT_READY";
com.ptc.core.businessRules.engine.BusinessRuleSetBean[] beans = new
com.ptc.core.businessRules.engine.BusinessRuleSetBean[] {

// Configure to call required rule set only


com.ptc.core.businessRules.engine.BusinessRuleSetBean.
newBusinessRuleSetBean
("EXAMPLE1_RELEASE_RULE_SET", "wt.change2.ChangeRecord2")
};
com.ptc.core.businessRules.validation.RuleValidationResultSet resultSet =
wt.businessRules.BusinessRulesHelper.engine.execute(primaryBusinessObject,
beans);

if ( !resultSet.hasResultsByStatus(com.ptc.core.businessRules.
validation.RuleValidationStatus.FAILURE)) {
result = "PROCEED";
}
else {
businessRulesResultSetGlobal = wt.businessRules.BusinessRulesHelper.
serialize(resultSet);
preReleaseConflictsMsg = new wt.util.WTMessage
("com.ptc.windchill.enterprise.
change2.change2ClientResource", com.ptc.windchill.enterprise.change2.
change2ClientResource.BUSINESS_RULES_PRERELEASE_VALIDATION_MSG,
null).getLocalizedMessage();
preReleaseConflictsMsg = preReleaseConflictsMsg + "\n" + resultSet.

Business Rules 1289


getFailedRulesMessage(java.util.Locale.getDefault());
}
The following is an example of the conflicts shown on the Resolve Release
Conflicts workflow task. Note that the Resolve Release Conflicts workflow task
will continue to regenerate the task until all conflicts have been resolved.

1290 Customization Guide


Loading Business Rule Objects
This section describes how to create load files for the business rule objects. While
creating the business rules object, you need to use the IXB framework for loading
the BusinessRules objects. The intended outcome is an XML output that
follows a defined DTD for the business rules objects.

Prerequisite Knowledge
To perform this task, you need to have an understanding of the following:
• General knowledge of using DTD for creating XMLs
• Validating the XML based on the DTD
• An understanding of the Import Export Framework. For more information, see
Import Export Framework on page 2129

Process
You can use any text editor to author an XML file for business rule objects.

Solution Elements
Element Type Description
standardX20.dtd DTD DTD for load files.
Location: <Windchill>\
loadXMLFiles
businessRules.dtd DTD Modularized business rule DTD.
Location: <Windchill>\codebase\
registry\ixb\dtds\
standardX20.dtd\
businessRules.dtd

DTD Definition
The business rules DTD is part of the standardX20.dtd definition. The
definition of the DTD can be located at: <Windchill>\codebase\
registry\ixb\dtds\standardX20.dtd\businessRules.dtd

Business Rule Objects


These are the Business Rule objects that are needed for using the Business Rules
engine.

Business Rules 1291


• BusinessRuleSet : A BusinessRuleSet instance is the persistence
configuration used to navigate persistent set of Validation business rule for a
container. This can be overridden at container level.
• BusinessRule : BusinessRule holds the information about the Rule to
be executed. Each Rule may have unique configuration requirements
associated to it. The selector is mapped to the actual implemented rule
validation class.
• BusinessRuleLink : A ObjectToObject binary link holding the
references to BusinessRuleSet and BusinessRule. Each
BusinessRuleSet is associated to a BusinessRule using the
BusinessRuleLink.
These are the attributes used for business rules objects:
Name Applicable Option- Comments Type
Object al
key BusinessRu No Key unique to the String - 256
leSetBusi business rule object. characters
nessRule For business rule set,
key, typically would
be something like
CHANGE_
RELEASE_
VALIDATION
name BusinessRu Yes Name of the String - 256
leSetBusi BusinessRule characters
nessRule Set or
BusinessRuleOb
ject. The name
field is localized.
descrip- BusinessRu No Description of the String – 4000
tion leSetBusi business rule object. characters
nessRule The description field
is localized.
configs Business Yes configs attribute Name value pair
Rule holds the information
that is required to
evaluate
BusinessRule
against objects.
configs element holds
0 or more than 0
config element. Each

1292 Customization Guide


Name Applicable Option- Comments Type
Object al
config element will
hold the name and
key attribute defining
the configuration
required to run the
Rule.
If the key needs to
specify more than one
value, it could specify
it using a new config
element as shown in
the example. If the
rule needs to specify
name “validType”, it
should specify as
below: <config
name="
validType "
value=
"WTPart.
class"></
config> <config
name="
validType "
value=
"WTDocument.
class"></
config>

Business Rules 1293


Name Applicable Option- Comments Type
Object al
enabled BusinessRu Yes The ability to boolean
leSetBusi configure the
nessRule business rule object
to be executed. When
the value is false, the
business rule object is
ignored and look for
the next available
enabled in the
container hierarchical
lookup.
overrida- BusinessRu The overridable boolean
ble leSet attribute can be set to
true if the system
could override the
BusinessRule
Set at the below
container. If the value
is set to false, even
though a
BusinessRule
Set is defined at
children container,
business rules
instance at the parent
container where the
overridable is set to
false are used. The
lookup mechanism
work similar to the
Windchill preferences
look for a container.
block- BusinessRu Yes A number indicating Numeric integer
Number leLink the execution of the value
rules. Multiple rules
can be configured to
the same
blockNumber. This
supports execution of
rules in parallel. A

1294 Customization Guide


Name Applicable Option- Comments Type
Object al
value of 1 indicates
the first rule to be
executed within the
business rule set.
Example: If
blockNumber 1a
ruleA
blockNumber 2a
ruleB and ruleC
The rules execution
engine executes ruleA
and could potentially
execute ruleB and
ruleC is parallel.

Creating an IXB Load XML File


Described below are the business rule objects that are using IXB load files.
The name and description attributes are supported for localization. The format of
the value is <Resourcebundle pacakage
name>.ResourceBundleFileName:ResourceKey. For example, the
format for specifying Business Rule name is:
com.ptc.windchill.enterprise.change2.change2ClientRe
source:CHECK_OUT_VALIDATOR_RULE_NAME
While retrieving the value for name and description, the resource bundle returns a
localized value for passed in locale.

Note
If invalid resource key is specified the name or description field will show
non-localized value of the field. In the above example if the resource bundle
did not exist, name is displayed as
com.ptc.windchill.enterprise.change2.change2ClientRe
source:CHECK_OUT_VALIDATOR_RULE_NAME

Business Rules 1295


BusinessRule
A BusinessRule object holds the information about the Rule to be executed.
Each Rule may have unique configuration requirements associated to it. A key
and the container should be unique for creating BusinessRule objects.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:45346</localId></ObjectID>
<objectContainerPath>/</objectContainerPath>
<key>IXBBusinessRule1_key</key>
<name> com.ptc.windchill.enterprise.change2.change2ClientResource:
CHECK_OUT_VALIDATOR_RULE_NAME</name>
<description> com.ptc.windchill.enterprise.change2.change2ClientResource:
CHECK_OUT_VALIDATOR_RULE_DESC</description>
<enabled>true</enabled>
<configs>
<config name="key1" value="value1"></config>
<config name="key2" value="value1"></config>
<config name="key1" value="value2"></config>
</configs>
</BusinessRule>

BusinessRuleSet
A BusinessRuleSet instance is the persistence configuration of a set of
Validation Rule. Typically holds the rules configured to be executed for the
container. A key and the container should be unique for creating
BusinessRuleSet objects.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:45345</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=
PTC/wt.pdmlink.PDMLinkProduct=GOLF_CART</objectContainerPath>
<key> IXBBusinessRuleSet1_key </key>
<name> com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_NAME </name>
<description> com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_DESC</description>
<enabled>true</enabled>
<overridable>true</overridable>
</BusinessRuleSet>

BusinessRuleLink
A ObjectToObject binary link holding the references to
BusinessRuleSet and Rules.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>

1296 Customization Guide


<ObjectID><localId>wt.businessRules.BusinessRuleLink:356747
</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:45345
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:45346
</localId>
</ObjectReference></rule>
<blockNumber>10</blockNumber>
</BusinessRuleLink>

Loading the Business Rule Objects


After defining new business rules, or updating existing rules, use this procedure to
load the business rules:
1. Add the load files to a zip file. For example, add the BusinessRulesObjects in
a zip file such as:<Windchill>/loadFiles/ixbImport/
BusinessRuleObjects.zip

Note
The zip file must be located in a folder path within the <windchill>
directory.

2. Create the XML load file to load the generated zip file created in step 1.
Here is an example:
<?xml version="1.0"?>
<!DOCTYPE NmLoader SYSTEM "standardX20.dtd">

<NmLoader>
<csvExecuteImport handler="wt.load.LoadImport.executeImport">

<csvimportFilename>loadFiles/ixbImport/businessRulesObjects.zip
</csvimportFilename>
</csvExecuteImport>
</NmLoader>

3. Using a Windchill shell, execute the following load command to load the
business rules objects.
windchill wt.load.LoadFromFile -d <PATH>\loadFileName
where loadFileName refers to the file created in step 2. Executing the
command stores the business rule objects in the database, ready to be
configured.

Business Rules 1297


Update Existing Business Rules
Existing business rules can be optionally updated. Users can enable the ability to
update existing rules by adding the updateIfExists attribute to the business
rules load files they want to update and setting the value of the attribute to true.
When the attribute is not found in the load file or the value is set to false, existing
rules cannot be updated and an error shall occur if a user attempts to reload the
load files. The attribute is not considered when loading the rules initially - non-
existing business rules shall be loaded successfully.

Note
Because the key and a container forms the BusinessRule object
uniqueness, both cannot be updated once created even if the ability to update
existing rules is enable.

Here is an example on how to enable update


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRule>
...
<updateIfExists>true</updateIfExists>
...
</BusinessRule>

Deleting Business Rule Objects


Existing business rule objects can be deleted using the command line utility
DeleteBusinessRuleObjects. To delete a business rule or business rule set the
arguments are
windchill wt.businessRules.DeleteBusinessRuleObjects “typeOfObjectToDelete:
key:containerPath”

1298 Customization Guide


Argument Name Description Applies to Examples
typeOfObjectTo- The type of object BusinessRule BusinessRule
Delete to delete BusinessRuleSet BusinessRuleSet
BusinessRuleLink BusinessRuleLink
key The key of the BusinessRule CHECKOUT_
object to delete BusinessRuleSet RULE
CHANGEABLE_
PRE_RELEASE
containerPath The container path BusinessRule /wt.inf.container.
of the object BusinessRuleSet OrgContainer=
PTC/wt.pdmlink.
PDMLinkProduct=
GOLF_CART

To delete a business rule link, the business rule set and business rule that it links
need to be specified.
windchill wt.businessRules.DeleteBusinessRuleObjects "typeOfObjectToDelete:
key:containerPath:key:containerPath"
The argument for the object to delete needs to be in quotes since container paths
may contain spaces. If a business rule or business rule set is deleted, then any link
the object was a part of is also deleted. One or more objects can be specified,
separated by a space.

Examples
• Deleting a business rule
windchill wt.businessRules.DeleteBusinessRuleObjects
"BusinessRule|keyToDelete|/
wt.inf.container.OrgContainer=Org Name/
wt.pdmlink.PDMLinkProduct=Product Name"
• Deleting 2 business rule sets
windchill wt.businessRules.DeleteBusinessRuleObjects
"BusinessRuleSet|keyToDelete|/
wt.inf.container.OrgContainer=Org Name/
wt.pdmlink.PDMLinkProduct=Product Name"
"BusinessRuleSet|anotherKey|/
wt.inf.container.OrgContainer=Org Name/
wt.pdmlink.PDMLinkProduct=Product Name"
• Deleting a business rule link

Business Rules 1299


windchill wt.businessRules.DeleteBusinessRuleObjects
"BusinessRuleLink|businessRuleSetKey|/
wt.inf.container.OrgContainer=Org Name/
wt.pdmlink.PDMLinkProduct=Product
Name|businessRuleKey|/wt.inf.container.OrgContainer=
Org Name/wt.pdmlink.PDMLinkProduct=Product Name"

Business Rule Types


The rule behavior can be extended or overridden by register a new rule validation
class for the rule selector in service.properties.
Rule Configurable? Selector Validation Class
Check Out False CHECKOUT_ com.ptc.core.
RULE businessRu
les.valida
tion.Checkou
tRuleValida
tor
Attribute True ATTRIBUTE_ com.ptc.core.
RULE businessRu
les.validatio
n.AttributeRu
leValidator
Release Target False RELEASE_ com.ptc.core.
TARGET businessRu
les.valida
tion.Release
TargetValida
tor
BOM Release True BOM_RELEASE_ com.ptc.core.
RULE businessRu
les.valida
tion.BOMRelea
seRuleValida
tor

Check Out Rule


The checkout rule validates that objects are not checked out or checked out to a
project. The checkout rule is not a configurable rule.

1300 Customization Guide


Examples
The following XML defines a set of business rule objects which implement the
checkout rule.

Business Rule Set that implements the Checkout rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:45346
</localId></ObjectID>
<key>CHANGEABLE_PRE_RELEASE</key>
<name>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_NAME</name>
<description>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_DESC</description>
<enabled>true</enabled>
<overridable>true</overridable>
</BusinessRuleSet>

Business Rule that implements the Checkout rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:158915
</localId></ObjectID>
<key>CHECKOUT_RULE</key>
<selector>CHECKOUT_RULE</selector>
<name>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHECK_OUT_VALIDATOR_RULE_NAME</name>
<description>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHECK_OUT_VALIDATOR_RULE_DESC</description>
<enabled>true</enabled>
</BusinessRule>

Business Rule Link that implements the Checkout rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:158919
</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:45346
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:158915
</localId></ObjectReference></rule>
<blockNumber>1</blockNumber>
</BusinessRuleLink>

Business Rules 1301


Attribute Rule
The attribute rule validates that the specified attribute rule configuration for an
object type is valid. The object type is the only required input for an attribute rule
configuration. The object type should be a wt.fc.Persistable type object.
For example com.ptc.Waiver is a soft type of
wt.change2.WTVariance.
<configs>
config name="objectType" value="com.ptc.Waiver"></config>
</configs>
The type string value can be specified using the just the type name or type
external name (com.ptc.Waiver or
WCTYPE|wt.change2.WTVariance|com.ptc.Waiver )
Subtypes of the specified object type can be excluded from attribute rule. For
example, the following attribute rule configuration for object type WTVariance
would exclude com.ptc.Waiver and com.ptc.Deviation type variances
from being evaluated.
<configs>
<config name="objectType" value="wt.change2.WTVariance "></config>
<config name="excludedType" value="com.ptc.Waiver"></config>
<config name="excludedType" value=" com.ptc.Deviation "></config>
</configs>
To configure a condition to valid on an attribute of the specified object type the
configuration name is the attribute name and the value is the condition. The
following attribute configuration would check if a com.ptc.Waiver has an
approved quantity between 10 and 100.
<configs>
<config name="objectType" value="com.ptc.Waiver"></config>
<config name="approvedQuantity" value="[10..100]"></config>
</configs>
The following is example where “weight” is the internal name of a soft attribute
on some soft type of part.
<configs>
<config name="objectType" value="com.ptc.SoftTypePart"></config>
<config name="weight" value="<=100"></config>
</configs>
The following table shows the supported operations and object types supported in
attribute rule configuration.

1302 Customization Guide


Operator Value Types Description Example
Conditions
>, >=, <, <= Long, String, Date, Validates that the >&gt;2012-01-12
Timestamp, object attribute 00:00:00
FloatingPoint, value is greater <=&lt;=20.002
FloatingPointWi- than, less than or
thUnits equal to the value >&gt;=10
specified. The less
than and greater
than characters are
reserved characters
in the import load
therefore the less
than operator
needs to be
specified as ‘&lt;’
and greater than
operator as ‘&gt;’.
[0..10] Long, String, Date, Validates that the [-10.09..10.09]
Timestamp, object attribute [2012-01-12
FloatingPoint, value is within the 00:00:00..2012-02-
FloatingPointWi- specified range. If 12 00:00:00]
thUnits no minimum value
[..100]
in the range is
specified the [0..]
condition is
equivalent to less
than or equal to.
The same for if the
max value in the
range is not
specified the
condition is treated
a greater than or
equal to.
=, != Boolean, Long, Validates that the =true
String, Date, object attribute &#33;=2012-02-
Timestamp, value is or is not 12 00:00:00
FloatingPoint, the value specified.
=10.09
FloatingPointWi-
thUnits
[A,B] Boolean, Long, Validates that the [true]

Business Rules 1303


Operator Value Types Description Example
Conditions
String, Date, object attribute [2012-02-01
Timestamp, value is within the 00:00:00,2012-02-
FloatingPoint, discrete set. 15 00:00:00,2012-
FloatingPointWi- 02-30 00:00:00]
thUnits
[MAJOR,
CRITICAL]
[10.01,10.02]
[10,100,1000]
SET Boolean, Long, Validates that the SET
String, Date, object attribute
Timestamp, value is not null.
FloatingPoint, Only the keyword
FloatingPointWi- SET is needed to
thUnits specify the
operation
NOT_SET Boolean, Long, Validates that the NOT_SET
String, Date, object attribute
Timestamp, value is null. Only
FloatingPoint, the keyword NOT_
FloatingPointWi- SET is needed to
thUnits specify the
operation
EQUALS String Validates that the EQUALS
object attribute (MAJOR)
value is the
specified string.
NOT_EQUALS String Validates that the NOT_EQUALS
object attribute (MAJOR)
value is not the
specified string.
BEGINSWITH String Validates that the BEGINSWITH
object attribute (PN)
value starts with a
specified string.
NOT_ String Validates that the NOT_
BEGINSWITH object attribute BEGINSWITH
value does not start (PN)
with a specified

1304 Customization Guide


Operator Value Types Description Example
Conditions
string.
ENDSWITH String Validates that the ENDSWITH(0)
object attribute
value ends with a
specified string
NOT_ENDSWITH String Validates that the NOT_ENDSWITH
object attribute (0)
value does not end
with a specified
string
CONTAINS String Validates that the CONTAINS(PN0)
object attribute
value contains the
specified string.
NOT_CONTAINS String Validates that the NOT_CONTAINS
object attribute (PN0)
value does not
contain the
specified string.
LENGTH String Validates that the LENGTH(0..40)
object attribute LENGTH(0..)
string length is
within the LENGTH(..40)
specified range.

Note that the system locale is used for the format of the dates and timestamps in
the attribute condition.

Examples
If you have a specific soft type of a part, and it has an attribute called weight to
represent how heavy the part is. Before releasing parts that have a weight, you
want to ensure that a weight is set to a reasonable figure. In order to do this, you
want to construct a business rule to verify that the weight attribute falls within the
range 1-100.

Business Rule Set that Implements the Attribute Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:45347
</localId></ObjectID>

Business Rules 1305


<objectContainerPath>/wt.inf.container.
OrgContainer=BusinessRulesTestOrganization
/wt.pdmlink.PDMLinkProduct=BusinessRulesTestProduct
</objectContainerPath>
<key>CHANGEABLE_PRE_RELEASE</key>
<name>Test_Changeable_ReleaseRuleSet</name>
<description>To test basic Attribute RuleSet Validation
</description>
<enabled>true</enabled>
<overridable>true</overridable>
<updateIfExists>true</updateIfExists>
</BusinessRuleSet>

Business Rule that Implements the Attribute Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:
168926</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer
=BusinessRulesTestOrganization/
wt.pdmlink.PDMLinkProduct=BusinessRulesTestProduct
</objectContainerPath>
<key>PART_ATTRIBUTE_RULE</key>
<selector>ATTRIBUTE_RULE</selector>
<name>Test Attribute Rule</name>
<description>Test Attribute Rule</description>
<enabled>true</enabled>
<updateIfExists>true</updateIfExists>
<configs>
<config name="objectType"
value="wt.part.AttributeRulePart"></config>
<config name="weight" value="[0..100]"></config>
</configs>
</BusinessRule>

Business Rule Link that implements the Attribute rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:168919
</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:45347
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:168926
</localId></ObjectReference></rule>
<blockNumber>1</blockNumber>
<updateIfExists>true</updateIfExists>
</BusinessRuleLink>

1306 Customization Guide


Release Target Rule
The “Release Target Rule” ensures that all “Resulting Objects” are at an
appropriate state for release and have an appropriate change management
transition specified that is consistent with the assigned lifecycle transition rules. If
the user selected transition is not defined for the current resulting object transition
the rule should fail. The new “Release Rule” is part of the delivered
"CHANGEABLE_PRE_RELEASE" business rule set.
Any undefined change management transition values in the Change Record
associated with the plan for release is assumed to be the “Change” transition and
its defined state. This approach provides equivalent backward compatibility. If the
“Change” transition is not defined for the resulting object the rule should fail. A
special case exists where the current state of the Changeable object does not have
a defined “Change” transition, but is already at the release target state that is
specified by the “Change” transition. This case should be permitted by exception.
For example, a part has the following lifecycle states "In Work", "Under Review"
and "Released". A "Change" transition is defined on the "Under Review" state to
transition to the "Released" state. The part is currently in the released state and has
been added to the resulting objects table of a change task with some specified
effectivity. The "Change" transition would be assumed even though the "Change"
transition is defined on the "Released State" allowing the change to process. The
part's state should not change but remain in the "Released" state.

Examples
The following XML defines a set of business rule objects which implement the
Release Target rule.

Business Rule Set that implements the Release Target rule:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:45346</localId></ObjectID>
<key>CHANGEABLE_PRE_RELEASE</key>
<name>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_NAME</name>
<description>com.ptc.windchill.enterprise.change2.change2ClientResource:
CHANGE_PRE_RELEASE_RULESET_DESC</description>
<enabled>true</enabled>
<overridable>true</overridable>
</BusinessRuleSet>

Business Rule that Implements the Release Target Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:151031</localId></ObjectID>
<key>RELEASE_TARGET</key>

Business Rules 1307


<selector>RELEASE_TARGET</selector>
<name>com.ptc.windchill.enterprise.change2.change2ClientResource:
RELEASE_TARGET_RULE_NAME</name>
<description>com.ptc.windchill.enterprise.change2.change2ClientResource:
RELEASE_TARGET_RULE_DESC</description>
<enabled>true</enabled>
</BusinessRule>

Business Rule Link that Implements the Release Target Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">\
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:151033</localId></ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:45346
</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:151031
</localId></ObjectReference></rule>
<blockNumber>2</blockNumber>
</BusinessRuleLink>

BOM Release Rule


The BOM Release Rule ensures that all resulting objects are at an appropriate
state and all their first level children are at an appropriate state. This rule is not
used out of the box but can be configured using the selector BOM_RELEASE_
RULE. The configuration options required for this rule are
• targetState – one or more valid states for the resulting objects
• validDependentState – one or more valid states for child objects
• invalidDependentState – one or more invalid states for child objects
• checkPredecessorRevisions – boolean value which represents whether or not
the BOM release rule should execute against previous revisions
• collectionComponentID - the collection component id used to collect the child
objects.
An example config is:
<configs>
<config name="targetState" value="RELEASED"/>
<config name="validDependentState" value="RELEASED"/>
<config name="validDependentState" value="PROTOTYPE"/>
<config name="invalidDependentState" value="OBSOLETE"></config>
<config name="invalidDependentState" value="INWORK"></config>
<config name="collectionComponentID"
value="COLLECT_ITEMS_FOR_BOM_RELEASE_RULE"/>
</configs>

1308 Customization Guide


A default collection component id COLLECT_ITEMS_FOR_BOM_RELEASE_
RULE is provided out of the box. Each collection component id has preferences
that determine which objects are collected. The preferences for COLLECT_
ITEMS_FOR_BOM_RELEASE_RULE are located under Business Rules, ▶ BOM
Maturity Release Collector
If a child object is also a resulting object, then the target state that the object goes
to when it is released through the change notice is used instead of the current state.

Examples
If you need to change an assembly that has many child parts. However, before you
change the assembly, you want to ensure that all of the children are in the
Released state, or are in the Releasedstate as a result of this change. You also want
to ensure that all of the child parts are up-to-date, so you want to ensure that none
of the children parts had become Obsolete at some point in time. To configure
this, you could create the following business rule objects.

Business Rule Set that Implements the BOM Release Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleSet SYSTEM "standardX20.dtd">
<BusinessRuleSet>
<ObjectID><localId>wt.businessRules.BusinessRuleSet:45347</localId>
</ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=
BusinessRulesTestOrganization
/wt.pdmlink.PDMLinkProduct=BusinessRulesTestProduct</objectContainerPath>
<key>CHANGEABLE_PRE_RELEASE</key>
<name>Test_Changeable_ReleaseRuleSet</name>
<description>To test basic Attribute RuleSet Validation</description>
<enabled>true</enabled>
<overridable>true</overridable>
<updateIfExists>true</updateIfExists>
</BusinessRuleSet>

Business Rule that Implements the BOM Release Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRule SYSTEM "standardX20.dtd">
<BusinessRule>
<ObjectID><localId>wt.businessRules.BusinessRule:158927
</localId></ObjectID>
<objectContainerPath>/wt.inf.container.OrgContainer=
BusinessRulesTestOrganization
/wt.pdmlink.PDMLinkProduct=BusinessRulesTestProduct
</objectContainerPath>
<key>BOM_RELEASE_RULE_RELEASED_STATE</key>
<selector>BOM_RELEASE_RULE</selector>
<name>Test BOM release Rule</name>
<description>Test BOM release Rule RELEASED State</description>
<enabled>true</enabled>

Business Rules 1309


<updateIfExists>true</updateIfExists>
<configs>
<config name="targetState" value="RELEASED"></config>
<config name="validDependentState" value="RELEASED"></config>
<config name="invalidDependentState" value="OBSOLETE"></config>
<config name="checkPredecessorRevisions" value="true"></config>
<config name="collectionComponentID"
value="COLLECT_ITEMS_FOR_BOM_RELEASE_RULE"></config>
</configs>
</BusinessRule>

Business Rule Link that Implements the BOM Release Rule


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE BusinessRuleLink SYSTEM "standardX20.dtd">
<BusinessRuleLink>
<ObjectID><localId>wt.businessRules.BusinessRuleLink:168920</localId>
</ObjectID>
<ruleSet><ObjectReference><localId>wt.businessRules.BusinessRuleSet:
45347</localId></ObjectReference></ruleSet>
<rule><ObjectReference><localId>wt.businessRules.BusinessRule:158927
</localId></ObjectReference></rule>
<blockNumber>1</blockNumber>
<updateIfExists>true</updateIfExists>
</BusinessRuleLink>

1310 Customization Guide


29
Customizing Workflow
Administration
Customizing Change Management Workflow Process Templates.............................. 1312
Customizing Promotion Request Workflow Processes.............................................. 1318
Enhanced Promotion Process ................................................................................ 1322
Customizing Workflow Events on an Object............................................................. 1333
Customizing Workflow Task Pages ......................................................................... 1335
Refine and Review Workflow Transitions................................................................. 1359
Adding Custom Workflow Attribute to Workflow Processes ....................................... 1366
Workflow Email Notifications .................................................................................. 1369
Multiple Participant Selection Wizard Customization ................................................ 1374
Customizing Change Activity Workflow Assignments ............................................... 1382
Customizing Change Tables Designed for Workflow................................................. 1392
Locking Annotations In Change Workflows ............................................................. 1398

This chapter describes how to customize workflow.

1311
Customizing Change Management
Workflow Process Templates
Introduction
Synchronization robots are a critical part of the Change Management workflow
process template examples. Originally, these robots were developed as pure
expression robots. However, use of normal expression synchronization robots
causes very heavy Oracle activity, resulting in frequent Oracle redo log turnover.
At Release 5.1, therefore, these robots were updated to use object or class event
synchronization in conjunction with an expression.
These change affect only out-of-the-box example workflow process templates in
loadfiles\ChangeManagement.csv. If you use these templates but have not
customized them, simply delete the existing templates and load the modified ones.
If you have customized the out-of-the-box workflow process templates, you
should manually incorporate the changes, as described in the remainder of this
section, into your customizations to take advantage of the improved performance.
If your own expression synchronization robots are problematic, you should
manually incorporate changes similar to those described in this section.
Following are the Change Management workflow process templates that have
been enhanced to improve system performance:
• Change Issue Process
• Change Request Process 2
• Change Investigation Process
• Change Proposal Process
• Change Analysis Process
• Change Order Process
• Change Activity Process

Change Issue Process


Both of the existing robots in this template have been converted to object event
synchronization robots, and a new robot of that type has also been added:
Template Robot
Change Issue Process Sync on Request Association
Change Issue Process Listen for Request Disassociation
Change Issue Process Sync on Request Complete

1312 Customization Guide


The expression logic of change issue robots is illustrated in the following figure.
The following table explains the details of this figure; the numbers in the table
correspond to numbers in the figure.
1a) This conditional router checks if the change issue is already associated to a
change request. If so, the workflow continues to the conditional at 3a; otherwise,
it proceeds to the sync robot at 1b.
1b) The Sync on Request Association robot waits until the event ISSUE_
FORMALIZED is emitted for the primaryBusinessObject (the change issue),
signaling the change issue has been attached to a change request. The workflow
then continues to the conditional at 2a and the conditional at 3a simultaneously.
2a) This conditional router checks if the 3a) This conditional router checks the
change issue has been immediately state of the associated change request.
disassociated with the change request. If it is in state Completed, the workflow
If so, the workflow cycles back to 1a; continues to 3b (the end of the process).
otherwise, it continues to the sync robot If it is in state Cancelled, the workflow
at 2b. loops back to a point near the beginning
of the process. Otherwise, the workflow
continues to the sync robot at 3b.
2b) The Listen for Request 3b) The Sync on Request Complete
Disassociation sync robot listens for the robot waits until the state of the
event ISSUE_UNFORMALIZED on associated change request changes. If
the primaryBusinessObject, signaling the state is Completed, the workflow
the change issue has been disassociated continues to 3b (the end of the process).
from its change request. This causes the If it is in state Cancelled, the workflow
sync robot at 3b (‡) to terminate, and loops back to a point near the beginning
the workflow to loop back to the of the process. Otherwise, the sync
conditional at 1a. robot continues to wait for one of those
two states.

Sync on Change Request Submit


Each of the following robots has been converted to an object event
synchronization robot as described below:
Template Robot
Change Investigation Process Sync on Request Submit
Change Analysis Process Sync on Request Submit
Change Proposal Process Sync on Request Submit
Change Order Process Sync on Request Submit
Change Activity Process Sync on Request Submit

Customizing Workflow Administration 1313


Before Release 5.1, the expression logic performed the following actions:
1. Determine the parent change request by navigating one or two levels of
associations based on the change object:
• For a change investigation or change proposal, navigate the ResearchedBy
association.
• For a change order, navigate the AddressedBy2 association.
• For an analysis activity, first navigate the DetailedBy association to obtain
a change investigation or change proposal, then navigate the
ResearchedBy association.
• For a change activity, first navigate the IncludedIn2 association to obtain a
change order, then navigate the AddressedBy2 association.
2. Determine the current life cycle state of the change request.
3. Determine the current value stored in the Complexity attribute (for Sync on
Request Submit only).
4. Based on the results of step 2 and step 3, either continue holding or move on
to one of several possible activities that follow in the workflow.
The following changes have been made to this logic:
• A new process variable named parentChangeRequest has been introduced in
each workflow. It holds the parent request and is initialized when the
workflow begins through a transition expression on the process Start
transition.
• The following figure shows the expression synchronization robot as it existed
before Release 5.1.
This robot has been replaced with a conditional router followed by the sync
robot. The new robot, which has been changed to an object event
synchronization robot, is shown in the following figure.
The object is the new change request process variable just described. The
event is STATE CHANGE in each case. The conditional router contains
exactly the same logic as the expression in the object event subscription robot.
The purpose for this conditional router is to immediately check whether the
state has already been reached. This helps avoid the race condition of the state
being achieved prior to the instantiation of the synchronization robot. (In both
figures, the parentChangeRequest variable is assumed to be initialized
already.)
• The expression in the object event synchronization robot and conditional has
been changed to use the workflow variable parentChangeRequest directly,
rather than access the database repeatedly to determine the parent change
request.

1314 Customization Guide


These changes resulted in the following performance improvements:
• Lookup time during each execution of the synchronization expression has
been shortened as a result of saving the change request in a workflow variable.
• The synchronization expression executes only after the state of the change
request has changed. As a result, there is a very good chance the proper state
has been reached each time the expression runs.

Sync on Multiple Object State Change


Each of the following robots has been converted to a class event synchronization
robot as described below.
Template Robot
Change Request Process 2 Sync on Investigation
Change Request Process 2 Sync on Proposal
Change Request Process 2 Sync on Change Orders
Change Investigation Process Sync on Analysis Activities
Change Proposal Process Sync on Activities
Change Order Process Sync on Change Activities

Before Release 5.1, the expression logic performed the following actions:
1. Determine which children objects are applicable to the synchronization. For
example, in the Sync on Change Activities robot, all the change activities
related to the change order are relevant.
2. Determine the life cycles states of all the relevant objects.
3. Based on the result of step 2, either continue holding or move on to one of
several possible activities that follow in the workflow.
Release 5.1 includes the following changes to this logic:
The expression synchronization robot has been replaced with a conditional router
followed by the sync robot. The sync robot has been changed to a new class event
synchronization robot. The class differs depending on the particular
synchronization robot, but the event is always STATE CHANGE. The conditional
router contains exactly the same logic as the expression in the object event
subscription robot. The purpose for this conditional router is to immediately check
whether the state has already been reached. This helps avoid the race condition of
the state being achieved prior to the instantiation of the synchronization robot.
This change resulted in the following improvements:
The synchronization expression is executed only when an object in the proper
class has changed state. As a result, the expression is executed only when there is
a chance that the states of all related objects are in synchronization.

Customizing Workflow Administration 1315


Installation and Upgrade
The file \Windchill\loadfiles\ChangeManagement.csv contains the definition of
the following items:
• ChangeItems Domain
• Example Projects
• Example Workflows
• Example Life Cycle Templates

New Installations
A new Windchill installation will include the new Change Management workflow
process templates. Be sure to load the "Change Management lifecycles and
workflows" during the initial database load.
For further information about loading data, see the Windchill Installation and
Configuration Guide.

Existing Installations
If you are not concerned about overwriting existing demo workflow process or life
cycle templates, you can simply initiate "java wt.load.Demo " and answer "no" to
all questions except "Change Management lifecycles and workflows" (see the
Windchill Installation and Configuration Guide for further information about
loading data). You can ignore errors regarding the "Change Items" Domain and
the example projects. However, to avoid these errors, remove all sections from
ChangeManagement.csv except those for the Change Management workflow
process templates and life cycle templates.
If you do not want to overwrite the existing demo workflow process templates,
PTC recommends that you perform one of the following options before loading
the new workflow and life cycle templates:
• Rename the existing workflow and life cycle templates using the Workflow
Administrator and Life Cycle Administrator.
• Rename the new workflow and life cycle templates by manually editing the
ChangeManagement.csv file.

After loading the Release 5.1 workflow process and life cycle templates, you can
restore them to their original state one at a time by clicking Delete Latest Iteration
from the Workflow Administrator or Life Cycle Administrator page.

1316 Customization Guide


Custom Workflow Process Templates
If you have custom workflow process templates that contain synchronization
robots, PTC suggests that you load the Release 5.1 example workflow process
templates and study how they work, along with this document. This will help you
determine if you would benefit from implementing these techniques in your own
synchronization robots.

Code Impacted
The following code has been impacted by the enhancements:
• The workflow processes in loadfiles\ChangeManagement.csv, including the
changes described in this section.
• wt.change2.process.ProcessHelper – A new, overloaded version of the
checkRequestFinished method has been added, which takes a change request
and checks the state of the passed object.
• wt.change2.StandardChangeService – The methods saveFormalizedBy and
deleteFormalizedBy now emit the events ISSUE_FORMALIZED and ISSUE_
UNFORMALIZED, respectively.
• wt.admin.AdminEventResource – The ISSUE_FORMALIZED and ISSUE_
UNFORMALIZED events were added to this resource bundle (and all of its
language variants).
• wt.workflow.robots.synchEventResource – The ISSUE_FORMALIZED and
ISSUE_UNFORMALIZED events were added to this resource bundle (and all
of its language variants).
• wt.notify.notify.properties – The ISSUE_FORMALIZED and ISSUE_
UNFORMALIZED events were added to this property file.

Customizing Workflow Administration 1317


Customizing Promotion Request
Workflow Processes
The client that is used to Promote objects offers users a choice of two workflow
processes to choose from: promotion request approval and promotion request
review. These workflows can be customized. The out-of-the-box workflows are
shown below:

Promotion Request Approval Process

1318 Customization Guide


Promotion Request Review Process

Key Customization Points


You msut keep the following key points in mind when customizing these
workflows.

Lock/Unlock Promotion Targets


As you notice there are two "Conditional" routers that you see in the above
workflows. They handle important tasks.
One of them does the job of locking targets. The promotion targets could be parts,
CAD documents, docs etc. These promotion targets could be associated with a
lifecycle that has lock transitions. If so, and if there is a need to move the targets
to a desired lock state before reviewing the Promotion Request, and if there is lock
transition that exists with that desired lock state as the end state, then those targets
have to be locked before review tasks can be fired to the promotion review team
members.
The out-of-the-box conditional for locking has an expression similar to the below
code snippet:
wt.maturity.PromotionNotice pn =
(wt.maturity.PromotionNotice)primaryBusinessObject;
try
{
wt.maturity.MaturityServerHelper.service.lockTargets( pn );
result = "Accepted";

Customizing Workflow Administration 1319


}
catch( Exception wte )
{
result = "Rejected"; // send notification to owner
}

The customized workflow should also have a similar locking mechanism before
including the task for review.
The second conditional does the actual promotion of the targets and has code like:
wt.maturity.PromotionNotice pn =
(wt.maturity.PromotionNotice)primaryBusinessObject;
try
{
wt.maturity.MaturityServerHelper.service.promoteTargets (pn);
result="Approved";
}
catch (wt.maturity.MaturityException me)
{
result="Rejected";
}

The promoteTargets API also takes care of the process of unlocking the targets
before promoting them. This kind of an unlocking mechanism should also be
incorporated in the customized workflow.

1320 Customization Guide


Review Promotion Request Activity
The task that should be included in the workflow must be of the type Promotion
Request Task. This special task type will be available as a drop down while
defining the review activity in the workflow.

Owner Role in Promotion Request Team Template


Another important rule that must be strictly followed is to include the "Owner"
role in the team template that would be used for Promotion Request. The owner
role is a participant in many of the activities and robots in the PR workflow.

Customizing Workflow Administration 1321


Enhanced Promotion Process
There is currently no out of the box solution to refresh promotion objects to their
latest iterations or automatically revise the promotion candidates that are being
promoted through a revision series change.

Background
During the Promotion Request review and approval process, it is not uncommon
for the participants to uncover issues associated with the promotion candidates.
Rather than rejecting the Promotion Request, the process can be more efficient
with the introduction of a rework loop. This rework loop allows the creator of the
Promotion Request to review the comments, make appropriate adjustments to the
promotion candidates, and have the workflow automatically refresh the Promotion
Request for another review and approval.
It is also good practice to avoid sending promotion targets for approval when the
result will be a validation error. The rework loop contains this validation based on
the current iterations of promotion targets or the refreshed iterations if Automatic
Refresh is enabled.
For companies that use the Promotion Request as a "Gate Review" for production,
a best practice is to switch the revision labels for objects from a numeric series to
an alphanumeric series. With a proper life cycle design, such a gate state can be
modeled that achieves the desired target state and automatically revises the
promotion candidates to the initial revision label of the new revision series.

Scope/Applicability/Assumptions
These instructions assume a pre-existing knowledge of modifying workflow
processes and how to call Windchill methods within the workflow.

Intended Outcome
The expectation is that you will be able to add the auto-refresh or the automatic
revise functionality to your customized workflows.

Solution
The out-of-the-box promotion request process templates illustrate how to
implement both the auto-refresh and the automatic revise functionality. Also
included in the template is the review validation.

Prerequisite knowledge
To achieve this result, you need to have an understanding of the following:

1322 Customization Guide


• Basic Java development
• Workflow process modification including tally expressions and robot
expressions
• The management of resource bundle file.
• Windchill Preference Management utility

Note
The workflow process templates provided out-of-the-box should not be
modified directly. These process templates should be renamed prior to
modification.

Solution Elements
Element Type Description
wt.maturity. method This method call can be added to a
MaturityServerHelper. workflow expression that will unlock
service.unlockTargets the promotion targets in this case for
(pn) rework. The result of this is the
promotion targets will be at the state
they were at, at the moment the
promotion request was created.
Unlocking the promotion targets may
allow the user assigned to rework to
perform updates on the objects (subject
to access control).
wt.workflow.work. class This class is used to tally votes of a
WfTally workflow task. For example if a task is
assigned to the approval role multiple
users could receive that task and vote
differently. This class provides
methods that define which route to take
based on if ‘all have to vote for that
option” or any have to vote for that
option.
com.ptc.windchill. method This method can be added to a
enterprise.maturity. workflow expression that provides the
PromotionNoticeWork- update handling of promotion objects.
flowHelper.refresh(pn); Internally this method uses a new
preference Latest Iteration Refresh to
control the behavior. Here are the

Customizing Workflow Administration 1323


Element Type Description
values
1. Refresh promotion candidates
(default setting). This value only
refreshes the promotion candidates.
2. Refresh all objects. This value
refreshes all promotion objects: The
promotion candidates and the other
objects in the Maturity baseline.
3. Do nothing. This option will not
refresh any promotion objects.
4. Validate promotion targets. (see
Procedure – Validation of
Promotion Targets in Rework on
page 1332 for more information)

1324 Customization Guide


Element Type Description
wt.maturity. method This method call can be added to a
MaturityServerHelper. workflow expression that will lock the
service.lockTargets (pn); promotion targets. Only promotion
targets that have a lock transition will
be subject to locking.
com.ptc.core.ui. method This method can be added to a
validation. workflow expression to automatically
UIValidationResultSet revise promotion objects. Internally
set= com.ptc.windchill. this method uses two new preferences :
enterprise.maturity. 1. Automatic Revision Mode. There
PromotionNoticeWork- are 3 modes:
flowHelper.
revisePromotables(pn, pn. a. Do nothing.
getCreator(), locale); This mode will not perform any
automatic revisioning.
b. Automatically revise only the
promotion candidates.
This mode will automatically
revise only promotion
candidates
c. Automatically revise only the
promotion candidates with
versioning scheme changed
This mode will only revise
promotion candidates that will
be revising to a state that result
in a versioning scheme change.
2. Automatic Revision States.
This preference is a multi valued
list containing states that are valid
for automatic revisioning. This
preference only takes effect if the
Automatic Revision Mode
preference is something besides
Do-nothing.

Customizing Workflow Administration 1325


Procedure — Adding Automatic Refresh
A customized workflow process template used by promotion requests can be
modified to support automatic refresh. The following example will outline to
procedure used in the latest iteration of the “Promotion Request Approval
Process” provided out-of-the-box.

In this example a rework loop has been added. The loop begins at the Approve
Promotion Request task. Members of the Promotion Approvers receive this task.
An addition route has been added to the Approve Promotion Request task called
Rework.
In this example, a tally expression is defined that determines, based on all the
approvers’ votes, which route to take.
Vector v = new Vector();
v.addElement("Approve");
v.addElement("Reject");
v.addElement("Rework");
Vector vResult = wt.workflow.work.WfTally.any(self, v);
if( vResult.contains("Rework")) {
result = "Rework";
} else if ( vResult.contains("Reject") ) {
result = "Reject";
}else {
vResult = WfTally.all(self,v);
if( !vResult.isEmpty() ) {
result = (String)vResult.get(0);
}
}

1326 Customization Guide


This expression says if any approvers choose Rework then the Rework option is
taken. If no approvers select rework but any select Reject then Reject is taken.
Otherwise the Approve route is taken.
The approver task no longer contains special instructions. However, there exists a
process variable called special_instructions. This field is global to the
process and therefore can be set programmatically. The enhanced workflow uses
the Comment field of the Approve Promotion Request task to assemble a string of
comments that approvers voted Rework. This String is set on the Rework special
instructions. For example, if there are three users in the approvers role: user1,
user2 and user3.
• User1 votes approve with the comment: “Looks good”
• User2 votes rework with the comment: “Modify”
• User3 votes rework with the comment: “Resize”
In this case, the reworker will receive a task with the special instructions:
• [User2]: Modify
• [User3]: Resize
Once the Rework route is chosen the promotion targets are locked for rework and
the promotion creator will receive the Rework Promotion Request task. This task
will provide special instructions supplied by the approver of what promotion items
need rework. This special instructions field is writable for the Approve task and
read only for the Rework task. The creator can then iterate certain promotable
objects for this task. The creator could determine that the promotion in not longer
viable and can choose the reject option. In this case the promotion request is
rejected.
The user performing the rework can only update objects that they have permission
to modify. If the content of the promotion request is not able to be modified, major
reworking of the promotion request will require a rejection followed by a new
promotion request with the reworked items. The rework loop is meant to address
minor issues such as typographical errors, issues with quantity or units, minor
geometry changes rather than significant structural changes.
Once the promotion creator chooses the ‘Submit’ option the promotion request
will execute the Refresh Promotion Objects expression.
wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice)
primaryBusinessObject;
try
{
com.ptc.windchill.enterprise.maturity.PromotionNoticeWorkflowHelper.
refresh(pn);
wt.maturity.MaturityServerHelper.service.lockTargets (pn);
catch( Exception wte )
}
{
wte.printStackTrace();

Customizing Workflow Administration 1327


}
The PromotionNoticeWorkflowHelper.refresh(pn) method will
refresh the promotion objects to their latest iteration following the preference rules
defined in Solution on page 1322. Finally the loop is finished and the approvers
again receive the Approve Promotion Request task. It is important to include the
call to lockTargets() to ensure the promotion targets are not inadvertently
modified before approval if locking is supported.

FIT Table
The following fit table describes how the Latest iteration Refresh preference
affects automatic refresh.
Promotable Is Promotion Latest iteration Eligible to be
Target refresh Refreshed
preference
value
part_1 N/A Do Nothing false
part_2 Y Refresh promotion true
candidates
part_3 Y All true
part_4 N Refresh promotion false
candidates
part_5 Y All true

1328 Customization Guide


Procedure — Adding Automatic Revisioning
The workflow template used by the promotion request can be modified to support
automatic revisioning.
The following example will outline the procedure used in the latest iteration of the
“Promotion Request Approval Process” provided out-of-the-box.

In this example an additional conditional expression is added. It is added after the


conditional that promotes the targets. The Conditional looks like the following:

The Routing Expression expanded:


wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice)

Customizing Workflow Administration 1329


primaryBusinessObject;
try
{
java.util.Locale locale = wt.session.SessionHelper.getLocale();
com.ptc.core.ui.validation.UIValidationResultSet
set= com.ptc.windchill.enterprise.maturity.PromotionNoticeWorkflowHelper.
revisePromotables(pn, pn.getCreator(), locale);

reviseValidationMsg= com.ptc.windchill.enterprise.maturity.validators.
PromotionTargetsReviseValidator.getReviseResultSetMessage(set, locale);
if (!reviseValidationMsg.isEmpty() )
result="Partial";
else
result="Full";

}
catch( Exception wte )
{
wte.printStackTrace();
}
The method revisePromotables(pn, pn.getCreator(), locale);
performs the revision of the promotion objects following the preferences defined
above in Solution on page 1322.
Once the eligible promotion objects have been revised a message is created
containing any promotion targets not eligible for promotion along with the reason
why the promotion object was disqualified. This message is sent to the promotion
creator. Any valid promotion targets will be revised independent of whether there
are any disqualified targets.

Note
If promoting CAD Documents and Parts together, if the revise disqualifies
either the part or CAD document, the objects will not be revised together and
will need to be correctively fixed by the promotion request creator (or another
user) after promote.

Promotion Process as a Gate Review Process


For companies that use the Promotion Request as a "Gate Review" for production,
a best practice is to switch the revision labels for objects from a numeric series to
an alphanumeric series. With a proper life cycle design, such a gate state can be
modeled that achieves the desired target state and automatically revises the
promotion candidates to the initial revision label of the new revision series.
The following FIT table describes how this scenario would work based on various
values of the preferences described in Solution on page 1322.

1330 Customization Guide


Promot- Is Life Prefer- Prefer- Prefer- Prefer- Valid for
able Cycle ence ence ence ence revise
State Value Value
Based
part_1 No Automatic Released Automatic Automati- Yes
Revision Revision cally
States Mode revise all
the
promotion
candidates
part_2 Yes Automatic Released Automatic Automati- Yes
Revision Revision cally
States Mode revise
only the
promotion
candidates
with
versioning
scheme
changed
part_3 No Automatic Released Automatic Automati- No
Revision Revision cally
States Mode revise
only the
promotion
candidates
with
versioning
scheme
changed
part_4 No Automatic In Work Automatic Automati- No
Revision Revision cally
States Mode revise all
the
promotion
candidates
For this example the Maturity State of the promotion request is “Released”. In
addition each part is in its own unique container.

Customizing Workflow Administration 1331


Procedure – Validation of Promotion Targets in Rework
The automatic refresh capability detailed in Procedure — Adding Automatic
Refresh on page 1326 has been extended to check that if there is a later iteration of
the promotion target to be refreshed, that this iteration is valid for promotion. The
following checks are made:
• Promotion Target is not checked out.
• The creator has modify access on the Promotion Target.
• The LifeCycle of the promotion target has not changed since the promotion
was created.
• The State of the promotion target has not changed since the promotion was
created.

Workflow Template
Here is the expanded promotion notice workflow template with validation.

A conditional has been added to perform the above checks. An email is sent to the
creator with a list of promotion targets that cannot be promoted (if any). If some
targets of the Promotion Request cannot be promoted, the Promotion Request is
sent back for rework where the creator can either submit or reject. If all targets are
valid the promotion request is sent for approval.

1332 Customization Guide


Customizing Workflow Events on an
Object
Creating a customized event on an object
The following is an example of how to create a customized workflow event
(wt.workflow.engine.WfCustomEvent) on an object. In this example,
the customized event is MY_EVENT.
1. Add the following entry to <Windchill>/src/wt/workflow/
robots/synchEventResource.java :
@RBEntry("DEFAULT COMPLETED")
public static final String PRIVATE_CONSTANT_39 =
"*/wt.workflow.engine.WfCustomEvent/DEFAULT_COMPLETED";
2. Add the following entries to <Windchill>/src/wt/workflow/
engine/WfCustomEventTypeResource.java :
@RBEntry("MY_EVENT")
public static final String MY_EVENT = "MY_EVENT";
3. Rebuild the resources by running: ant -f bin/tools.xml class
-Dclass.includes=wt/workflow/robots/
synchEventResource.java
4. Rebuild the client JARs (see Rebuilding Client JARs on page 120).
5. Clear the Java Plug-in cache on your client machines.
6. Restart the Method Server.
7. Use the Workflow Process Editor to design a workflow template with a
Synchronization robot, as shown below:
In the Synchronization robot properties window:
a. Select object event
b. Make sure MY_EVENT is listed in Event dropdown list.
c. Choose MY_EVENT
d. Write appropriate expressions in the initial and routing expressions.
For more information on the Workflow Process Editor, see the Windchill
Business Administrator's Guide.

Emitting a customized event


Continuing the above example, the following code is required to emit the
customized event.
java.util.Hashtable valueMap = new java.util.Hashtable();

Customizing Workflow Administration 1333


wt.workflow.engine.WfEngineServerHelper.service.emitCustomObjectEvent ("MY_EVENT",
primaryBusinessObject, valueMap);

Where:
• MY_EVENT is the customized event as created above. Alternatively, any event
selected in the Event dropdown list in the Synchronization robot properties
window would be substituted in its place.
• PrimaryBusinessObject is the object on which we want to emit an
event. In other words, the object on which the Synchronization robot is
listening for MY_EVENT (the customized event).

Note
A customized event can be emitted from any customized code or from an
expression robot.

In handling an emitted event, there is no way to retrieve the valueMap


Hashtable from the event, since the synchronization expression syntax does not
provide a way to get the event object for an object-based event.

1334 Customization Guide


Customizing Workflow Task Pages
The following information details how to customize workflow task pages.
• Configuring Workflow Task Detail Pages on page 1336
• Implementing Customized Task Page JSP on page 1350
• Rendering Custom Workflow Activity Variables on page 1351
• Rendering PBO UI Components on page 1353
• Auto Create Change Notice Customization on page 1357
• Use of Customized Tag Library and/or 3rd Party Tag Library on page 1358

Customizing Workflow Administration 1335


Configuring Workflow Task Detail Pages
This section details the steps required to configure the workflow task details page
using the “Configure in Wizard” option in the Task Form Template UI. For more
information, see the “Creating a Task Form Template” topic in the Windchill Help
Center. This functionality was added in the Windchill 10.2 M030 release.
The following customizations are supported in task info page:
• Rendering of customized or OOTB tables associated with PBO
• Rendering of PBO attribute group
• Multiple tabs

Process Overview
Configuring the workflow task page consists of the following steps::
1. Identify the PBO object type that you want to customization. For more
information, see Identify PBO on page 1337.
2. Identify the Workflow task type that you want to customize. For more
information, see Identify Workflow Task Type on page 1337.
3. Identify the tables which should be rendered in the workflow task and their
sequence. For more information, see ftask form templateIdentify Tables to
Render and Configure on page 1337.
4. Identify the PBO actions that need to be rendered in the task info page and
their sequence. For more information, see Identify PBO Actions on page 1341.
5. Identify the PBO attributes that must be rendered. For more information, see
PBO Attribute Rendering on page 1342.
6. Identify the tabs to be on the workflow task page and where the tables and
actions must be rendered. For more information, see Multiple Tabs Support on
page 1345.
7. Create the load file for the task form template object in the proper format and
load the file. For more information, see Load File Format on page 1345 and
Overriding an out-of-the-box Task JSP on page 1358.
8. Configure the workflow task to use the loaded task form template. For more
information, see Workflow Template Configuration on page 1347.

1336 Customization Guide


Identify PBO
Identify the PBO object type that you want to customize. Any
lifecyclemanaged object can be used as a PBO. Hard types and soft types
are supported (WTPart, WtDocument, Agenda, Meeting, EPMDocument, etc).
You need to identify the full class name of the PBO.

Identify Workflow Task Type


Determine the workflow task type for which you want to create a task page.
You can configure a task for a combination of PBO and workflow task types. This
gives you the flexibility to have different configurations for two different
workflow task types (for example; Review and Promote).
For more information about task types, see the Activity Tab topic in the Windchill
Help Center.

Identify Tables to Render and Configure


The steps below will explain how to add the Affected Objects Table and Maturity
History Table
1. Identify the PBO-related tables which should be rendered on task details page.
It could be OOTB or your own customized tables.
• Identify table component id along with its type-based information.
○ To identify the component id and componentConfigBuilder
used by the component, refer to the debugging section of Customizing
Information Page Components on page 972.
○ Refer to the JavaDoc for the builder of the component to check if the
builder is defined with TypeBased annotation or not. Consider that
the component id for the component is
‘changemanagement.affecteddatatable’ and the builder is
configured to be a TypeBased.
For more information on TypeBased, seeTypeBased on page 265.

Customizing Workflow Administration 1337


2. Configure the identified tables above into a workitem task action model.
Define a new action in a custom actions file for the component (e.g. Affected
Data table) to display in the configurable workflow pages. The component
name needs to be "workflowTask.pbo", the component id needs to be
passed as pboCompId in the urlParams and the useTypeBased needs
to have the value based on the finding in previous step.
For example:
<action name="TestAffectedData"
resourceBundle="wt.workflow.worklist.worklistResource" >
<component name="workflowTask.pbo"
urlParams="pboCompId=changemanagement.
affecteddatatable&amp;useTypeBased=true"/>
<includeFilter name="configurableTypeBaseFilter"/>
</action>

• The includeFilter tag provides the filtering mechanism. The filter


framework is applicable for table components/actions where
includeFilter tag is used.
• In the TaskFormTemplate UI, table actions display based on the PBO
class selected for task form template.
• In the code soft types are already supported. However, if you have applied
filter for hard types (supported as true) and through UI if any soft type
instance is provided as its owns type, but it does not exist it checks for its
super class.
• In the Customized tab on the Workitem Info page, actions displayed in the
Customized menu is filtered based on the work items PBO type.
3. Create an action validator for the new action (TestAffectedData) created
in the previous step. OOTB an abstract validator
(WorkFlowTaskPBOComponentValidator class) and an override

1338 Customization Guide


method (isComponentValidFor) is provided by the framework that
filters the component based on PBO object type. The action validator for the
new action need to override isComponentValidFor that defines whether
PBO object type is valid or not for the given component.
package com.ptc.windchill.enterprise. workitem.validators;

import com.ptc.core.ui.validation.DefaultUIComponentValidator;
import com.ptc.core.ui.validation.UIValidationCriteria;
import com.ptc.core.ui.validation.UIValidationKey;
import com.ptc.core.ui.validation.UIValidationResult;
import com.ptc.core.ui.validation.UIValidationResultSet;
import com.ptc.core.ui.validation.UIValidationStatus;
import com.ptc.netmarkets.util.beans.NmCommandBean;
import com.ptc.core.meta.common.TypeIdentifier;
import com.ptc.windchill.enterprise.history.validators.
LifecycleHistoryNavValidator;

public class TestAffectedDataValidator extends


WorkFlowTaskPBOComponentValidator {

@Override
protected boolean isComponentValidFor(UIValidationKey validationKey,
UIValidationCriteria validationCriteria, WTReference pboRef) {

if (pboRef != null && pboRef.getObject() instanceof


LifeCycleManaged))
return true;

return false;
}

}
4. Configure the validators in the appropriate .properties files. The following
code sample continues the example about PboMaturityHistory. Add
these actions in the Workitem-service-properties.xconf file.
...
<Option cardinality="singleton" requestor="java.lang.Object"
serviceClass="com.ptc.windchill.enterprise.workitem.validators.
WorkflowTaskPboMaturityHistoryValidator"
selector="PboMaturityHistory"/> [Option cardinality="singleton"
requestor="java.lang.Object" serviceClass="com.ptc.windchill.enterprise.workitem.
validators.TestAffectedDataValidator" selector="TestAffectedData"/>

• All these actions should be part of model “workitem third nav


configurable” which is added to the Netmarkets-
actionmodels.xml file.

...

Customizing Workflow Administration 1339


<model name="workitem third nav">
<action name="attributes" type="workitem"/>
<action name="routingStatus" type="workitem"/>
<action name="notebook" type="workitem"/>
<action name="discussions" type="workitem"/>
<action name="setupParticipant" type="workitem"/>
<action name="adhocActivities" type="workitem"/>
<action name="workflowTaskPboAttributes" type="object"/>
<action name="saveComplete" type="workitem"/>
<action name="workflowTaskPboAction" type="workitem"/>
<action name="PboMaturityHistory" type="history"/>
<action name="TestAffectedData" type="change"/>
</model>
• All the above actions are validated in super set defined in the configuration
file (ConfigurableWorkflowTask-
typeBasedActionFiler.properties.xconf).
Actions which are displayed on task details page should be present in the
super set. If they do not exist then the task form template won’t be loaded
and it will not be configurable from the TaskForm template UI.
In the configuration file you must make entries in following pattern:
<Property name=
"actionType.actionName.configurablePbo.supported
Types/ nonSupportedTypes” overridable="true"
default="object Type<comma separated fully qualified
class names will be acceptable>"/>
Filtering is not applied for workitem actions. It should be applicable for
the PBO type which is associated with workitem.

1340 Customization Guide


Identify PBO Actions
1. Identify the PBO actions such as checkin, check out, edit, or view info page.
2. Add identified actions in “ConfigurableTask.<Fully Qualified
ClassName>” model (Netmarkets-actionmodels.xml). If it is not
specified, then the OOTB action model for the PBO type is used.
...
<model name="TaskFormTemplateWizardButtons" resourceBundle=
"com.ptc.netmarkets.workflow.taskformtemplates.taskformtemplatesResource">
<action name="editButton" type="taskformtemplates"/>
<action name="checkinButton" type="taskformtemplates"/>
<action name="cancelButton" type="object"/>
</model>

<model name="ConfigurableTask.wt.part.WTPart">
<submodel name="more part actions"/>
</model>

<model name="ConfigurableTask.wt.change2.WTChangeIssue">
<action name="view" type="object"/>
<action name="edit" type="problemReport"/>
<action name="editModifyContentOnly type="problemReport"/>
</model>

</actionmodels>

Customizing Workflow Administration 1341


PBO Attribute Rendering
This functionality supports rendering the PBO attribute defined in a specific
layout. Configuration of the layout is as follows
• The workflowTaskPboAttributes action is associated with new screen
definition created for lifecycle managed object in which you are able to render
PBO attributes on task page. This action is created in the EnterpriseUI_
actions.xml file and configured under “workitem third nav
configurable”.
...
<!-- MULTI OBJECT EDIT ACTIONS -->
<action name="editMultiObjects" id="editMultiObjects" multiselect="true"
selectRequired="true" resourceBundle="com.ptc.core.ui.tableRB">
<command class="com.ptc.windchill.enterprise.object.forms.
EditMultiObjectsFormProcessor"
method="execute" windowType="popup"
url="netmarkets/jsp/object/editMultiObjects.jsp"/>
<includeFilter name="disableForAdminLocked"/>
</action>

<action name="workflowTaskPboAttributes"
resourceBundle="wt.workflow.worklist.worklistResource">
<component name="workflowTask.pbo"
urlParams="pboCompId=workflow.pbo.attributes" />
<includeFilter name="configurableTypeBaseFilter"/>
</action>

</objecttype>
<!-- MULTI OBJECT EDIT ACTIONS END-->

1342 Customization Guide


To view this action you must create the layout by selecting “Information Page –
Workflow Task attribute” and “workflowTaskPboAttributes“ to render this layout
on the task details page.

Customizing Workflow Administration 1343


It renders the information within the work item info page.

1344 Customization Guide


Multiple Tabs Support

Load File Format


1. Create the Task Form template of a configurable type.
This is the loader format for creating a task form template.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE LoadTaskFormTemplate SYSTEM "standardX24.dtd">
<LoadTaskFormTemplate>
<TaskFormTemplate>
<name>test</name>
<filePath></filePath>
<taskType>WfTask</taskType>
<pboClass>wt.part.WTPart</pboClass>
<typeFormat>configurableWorkflow</typeFormat>
<description>Out Of The Box configurable workflow Template</description>
<WorkflowTaskTab>

<tabName>TestTab1</tabName>
<tabSetKey>infopage</tabSetKey> <components>
{"name":"workflowTaskPboAction",
"type":"workitem"},{"name":"attributes","type":"workitem"},
{"name":"routingStatus",
"type":"workitem"},{"name":"notebook","type":"workitem"},
{"name":"discussions",
"type":"workitem"},{"name":"setupParticipant","type":"workitem"},
{"name":"adhocActivities","type":"workitem"},
{"name":"pboMaturityHistory","type":"history"}]</components>
<pboAction><{"name":"checkout","type":"wip"},
{"name":"REVISEITEMS","type":"pdmObject"}]</pboAction>
<sequence>1</sequence>

</WorkflowTaskTab>

<WorkflowTaskTab>

<tabName>TestTab2</tabName>
<tabSetKey>infopage</tabSetKey> <components><
{"name":"workflowTaskPboAction",
"type":"workitem"},{"name":"attributes","type":"workitem"},
{"name":"routingStatus","type":"workitem"}]</components>
<pboAction>{"name":"checkin","type":"wip"}</pboAction>
<sequence>2</sequence>

</WorkflowTaskTab>

</TaskFormTemplate>
</LoadTaskFormTemplate>

Customizing Workflow Administration 1345


• <WorkflowTaskTab> is used to create the tab which has following tags
• <tabName> specifies the tab name
• <tabSetKey> is always infopage because the tabs are displayed on
the Workitem info page
• <components> is the Json of the tables/actions displayed on task details
page
• <pboAction> is the Json of the actions performed on the primary
business object which is associated with workitem displayed on task
details page
• <sequence> is the order in which the tabs display
2. Load into Windchill system and verify.
For more information, see the “Creating a Task Form Template” topic in the
Windchill Help Center.

1346 Customization Guide


Workflow Template Configuration
The newly created task form template needs to be referenced in the workflow
template as an activity template to be picked up for rendering.
1. Initiate a workflow and go to the activity you want to configure.

2. To use the task form tempalte to generate the task detail page, a preference
must be set.
Navigate to Utilities ▶ Preference Management ▶ Workflow ▶ Use task form
template to generate the task details page.

Customizing Workflow Administration 1347


3. Verify that the tabs are available.

1348 Customization Guide


Customizing Workflow Administration 1349
Implementing Customized Task Page JSP
The customer may create their own Tag file, to define their own custom task page
for one of their organizations.
They would have the choice of writing it from scratch, or using the provided
testPage template. This template would provide a starting point for development.
A "testPage" JSP, that contains all possible out-of-the-box attributes and
components, are available to the customer as an example page for customization.
This JSP lists each out-of-the-box attribute and component using HTML
constructs, similar to the out-of-the-box task pages. This "testPage" will also
include the alternate rendering options for tables and actions (for example, display
as a link and as an embedded table).

1350 Customization Guide


Rendering Custom Workflow Activity Variables
There exists a tag file (workItemInfo.tag) that must be included within each
task page JSP, before the actual rendering of the components. This tag describes
and gets the model of GUI Components for the given task page. For any custom
workflow activity variables, you need to specify either a comma-delimited list of
the activity variable names (which have been defined in the Workflow Definer)
and/or specify the reserved keyword of "all_activity_variables". Height
and/or width for each listed custom variable may also be specified using CSS style
syntax. ". (Note: height and width can only be applied to java.lang.String activity
variables, and width (only) can be applied for java.net.URL,
java.util.Date, and wt.workflow.engine.WfDueDate custom
activity variable types). A default height (1 character) and width (50 characters)
are used, when none is specified. For example, a list of variable names can be
specified as follows:
"variable_name1{height:1;width:2},variable_name2{height:1},variabl
e_name3{width:2},variable_name4".

Specifying "all_activity_variables" displays all visible activity


variables except for those named "special_instructions", "instructions", or
"primaryBusinessObject". The customizer is required to explicitly list these three
activity variable names (if defined in the Workflow definer as such), in addition to
the "all_activity_variables".
For the Windchill R9.0 out-of-the-box templates, the default renders all_activity_
variables. In addition, the Change Management template includes the specification
of the special_instructions activity variables.
Describe Examples:
<tags:workItemInfo
custom_variables="variable_name1,variable_name2{height:1}"/>
<tags:workItemInfo custom_variables="all_activity_variables"/>
<tags:workItemInfo
custom_variables="all_activity_variables,special_instructions{widt
h:50;height:5}"/

If you specify to render a particular custom activity variable (other than special_
instructions, instructions, or primaryBusinessObject) with the all_activity_
variables, the specified custom activity variable gets rendered twice.
Once the customizer has described and retrieved the property model (via the
workItemInfo.tag), they need to specify where on the page to render the
particular workflow activity variable's GUI component. This is done by including
the taskPanelValue tag, along with the new property model and the list of
variables to display at the desired location of the JSP. (Note: the list of variable
names must match the names listed for tags:workItemInfo. That is, if "all_
activity_variables" was specified, then this same name must be used to render the
GUI Components for "all_activity_variables.)

Customizing Workflow Administration 1351


Render Examples:
<tags:taskPanelValue propertyModel="${propertyModel}"
attrs="variable_name"/>
<tags:taskPanelValue propertyModel="${propertyModel}"
attrs="special_instructions"/
<tags:taskPanelValue propertyModel="${propertyModel}"
attrs="all_activity_variables"/>

1352 Customization Guide


Rendering PBO UI Components
You can customize the task form template (that is, the customized JSP) to only
display individual components of the PBO. For example, you might want to
include just the affected end items or attachments.
Use the tablePageLink tag to display one or more tables that are defined
together in one custom JSP:
• The parameter path is the JSP that is included.
• The tablePageLink tag can only be used once on a page to render one JSP
file.
For example:
<tags:tablePageLink
path="/netmarkets/jsp/change/affectedEndItemsTable.jsp"/

The following table lists the paths that can be used with tablePageLink:
PBO Path Available Function
Component
Affected End /netmarkets/jsp/change/ • Change Request-
Items affectedEndItemsTable.jsp WTChangeRequest 2
• Change Issue or Variance-
ChangeIssue
Affected and /netmarkets/jsp/changeTask/af • Change Task-
Resulting Items fectedAndResultingItems.jsp WTChangeActivity2
Attributes and /netmarkets/jsp/object/ • Change Request-
Attachments attribute s.jsp (no attachments WTChangeRequest 2
for CA) • Change Notice-
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice
Baselines /netmarkets/jsp/object/ • Change Request-
relatedBaselines.jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Task-
WTChangeActivity2

Customizing Workflow Administration 1353


PBO Path Available Function
Component
Contexts /netmarkets/jsp/object/ • Change Request-
relatedContexts.jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice
Discussion /netmarkets/jsp/forum/discuss. • Change Request-
jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice
Maturity History /netmarkets/jsp/history/ • Change Request-
maturit yHistory.jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice

1354 Customization Guide


PBO Path Available Function
Component
Routing/Process /netmarkets/jsp/workflow/ • Change Request-
processHistory.jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice
Subscriptions /netmarkets/jsp/subscription/ • Change Request-
objectSubscriptions.jsp WTChangeRequest 2
• Change Notice-
WTChangeOrder2
• Change Task-
WTChangeActivity2
• Change Issue or Variance-
ChangeIssue
• Promotion Notice-
PromotionNotice
The following table lists the tag files that can be used to include tables. If there is
a tablePageLink these tags must precede it.
PBO Syntax for including on JSP
Component
Promotion If the PBO is a PromotionNotice, the customizer may include
Notice Table the promotion objects table as follows:
<workItem:setPrimaryBusinessObject/>
<workItem:promotionObjects/
Notebook Table <workItem:notebook displayType="Table"/
Discussion Table <workItem:discussions displayType="Table"/>
Routing History To display routing history for all activities:
Table <tags:routingStatus dispProcess="All"/>

To display routing history for just the current activity:


<tags:routingStatus/>

Customizing Workflow Administration 1355


PBO Syntax for including on JSP
Component

Note
The display of the routing history table currently includes
the reassignment table as well. An SPR exists to allow the
routing history table to be displayed independent of the
reassignment history table.
Reassignment To display the reassignment history table as embedded and
Table expanded in the JSP:
<tags:reassignHistory showRH="Table"/>

To display the reassignment history table as a link:


<tags:reassignHistory showRH="Link"/>
Setup <tags:workItemActions/>
Participants `

Bold Font Issues


You may see that are no bold fonts if “Use task form template to generate the task
details page” is set to “Yes” while there are bold fonts if “Use task form template
to generate the task details page” is set to “No.” To correct this issue, do the
following:
1. Navigate to <Windchill>\codebase\netmarkets\jsp\
customtemplates
2. Edit the Site5_wt.fc.WTObject_WfTask_default.jsp file. This is
the template view jsp page for corresponding data type.

Note
To get the Site5_wt.fc.WTObject_WfTask_default.jsp file
we have “template view” preference must be set.

3. Modify the “table border” tag as follows.


• Existing code: <table border="0" cellpadding="1" width=
100%>
• Change to: <table border="0" cellpadding="1" width=100%
class="x-reset-font-wf">
4. At the end of the jsp add the following tag:
<STYLE TYPE="text/css"> .x-reset-font-wf strong{ font-weight: bolder; } </STYLE>

1356 Customization Guide


Auto Create Change Notice Customization
The customizer may also reimplement the handler for auto-creating the default
change notice and corresponding change task
(DefaultAutomateCreateChangeNoticeHandler.java), and override the following
method:
public abstract void
createChangeNoticeFromChangeRequest(WTChangeRequest2
changeRequest,
NmCommandBean cb) throws WTException;

To register the new handler within the configuration file ChangeManagement-


service-properties.xconf:
<Service context="default"
name="com.ptc.windchill.enterprise.change2.handler.AutomateCreateC
hangeNoticeHandler">

<Option
serviceClass="com.ptc.windchill.enterprise.change2.handler.Defa
ultAutomateCreateChangeNoticeHadler"
selector="DefaultHandler" requestor="null"
cardinality="duplicate"/

</Service>

Customizing Workflow Administration 1357


Use of Customized Tag Library and/or 3rd Party Tag
Library
The customizer might also choose to use a third-party tag library, or one of their
own custom tag libraries, for use in the custom task page. They would need to
include a "taglib" directive at the top of their page to specify the location of the
custom tag library. If they were to specify a custom tag library, they might choose
to use the same location as Windchill tags (WEB-INF/tags). However, it is
recommended that they use a unique prefix of their own (we use "tags" as a
prefix). Otherwise, they would have to make sure that they have unique tag
names.

Overriding an out-of-the-box Task JSP


Once a custom task page is created, the "Create Task Form Template" page is used
to upload the custom page, and register it with the given change item, task type,
and container.
Customer authors a JSP template and uses the following UI to upload it to
Windchill for a given combination of task type and PBO Class.
Clicking Create Template opens up the following page using which the JSP file
can be uploaded
Once the new template is uploaded, a new JSP file gets created in the codebase/
netmarkets/jsp/customtemplates folder. The name of the new JSP is generated
based off a mapping mechanism, using the Container, PBO class, Activity Type,
and JSP template name. (See Project 14216460 Workflow Task Forms).
The JSP name is generated using the mapping mechanism as follows:
<ContainerName>_<PBOType>_<ActivityType>_<Template Name>.jsp

Note
It is assumed that at least the out-of-the-box templates are present in the
system. If no template is found due to deletion of templates, then an exception
is raised.

1358 Customization Guide


Refine and Review Workflow Transitions
Sometimes you need to set all the Resulting Items into a new state that cannot be
checked out or modified so everyone has a consistent view of the Resulting data.

Prerequisite knowledge
To apply this knowledge, you need to have an understanding of the following:
• Knowledge of creating and modifying a workflow.
• Familiarity with change management concepts such as resulting data.
• Access to a system where the Refine and Review workflow transitions are
supported.
• That you have administrator access to the workflow and life cycle back end on
the Windchill application.

Adding the Transitions


1. Navigate to Site ▶ UtilitiesWorkflow Process Administration
2. Edit the Change Notice Workflow
3. Upon editing the Change Notice workflow, add a new Expression Robot.
a. Select the icon.
b. Click the workflow to add the transition.

4. Next you must link the expression with the workflow so it is executed.

a. You can modify or add new arrows using the Action tool ( ).
b. Holding CTRL and drag arrows between states. In this example it is added
before the Change Notice is submitted.

Customizing Workflow Administration 1359


5. Now that it is part of the Change Notice’s workflow execution, you must make
it a Refine or Review transition. You can do this by adding some code to the
expression. Double click the new Expression and then select the Expression
tab.
a. To add a Refine transition add the following expression code to the
transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTargets
(primaryBusinessObject,wt.lifecycle.Transition.toTransition(“REWORK"),false);

b. To add a Review transition add the following expression code to the


transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTargets
(primaryBusinessObject,wt.life cycle.Transition.toTransition("REVIEW"),false);

In this example a Review Transition has been added.

1360 Customization Guide


6. Select Check Syntax.

Note
If you copy and paste the transition code out of Word and directly into
Windchill, Word will copy invalid quotes which are not valid for the java
compiler. To get around this, when adding your expression code, paste it
into a Notepad first, copy it from Notepad, then paste into the Windchill
Expression box.

7. Save your changes and then Exit the Change Notice Workflow window. Now
you have a working copy of the new workflow with a Review Transition.
You can use the same process to add Refine transitions.

Understanding the Transitions


After the default Change Notice life cycle has been modified to contain the Refine
and Review transitions, you might have a workflow that looks something like this:

Customizing Workflow Administration 1361


Understanding the execution of Refine and Review above
If an Auditor is reviewing changes made to several Resulting Objects on a Change
Notice. When the Auditor reviews them, the changes do not appear to be
complete, so the changes are disapproved. The Refine and Review transitions will
help to complete the changes and get to the Auditor so that he or she can review
the complete changes.
1. During the Audit Change Notice, the changes are disapproved.
2. Refine Transition will be executed internally, changing the state of the
Resulting objects back to something modifiable.
3. The workflow will create a task for the Change Admin I to make the proper
updates. This is the Rework Task.
4. The Change Admin I makes the proper updates, and completes the Rework
Task.
5. Next, the workflow will execute the Review Transition. Once this Review
Transition is executed, the workflow will internally set the Resulting objects to
a state in which they can no longer be modified. Once the Review Transition is
executed, the Auditor who originally disapproved the changes would be able
to review the new complete changes.

Changing the Life Cycle of Part to Handle Refine and


Review Transitions
In this scenario, the part is using the Two Phase Development Life cycle instead of
the default one.
1. Navigate to the Site/Utilities level of Windchill
2. Find the Life Cycle Administrator and navigate to it
3. Edit the Two Phase Development Life Cycle, you will have to check it out
4. Configure what the new state will be when the Review transition is executed.
Suppose the business needs require to set the state of the Resulting objects to
Under Review if the Review transition is executed. To configure this, make
the following change in the life cycle:

1362 Customization Guide


5. Configure what you want the state to do if it is under the Refine transition.
Keep in mind this would likely be useful to use just after the Review has
occurred. Because of this, when the Change Notice is in Under Review state,
you will want to use the Refine transition to change the object back into
something editable. To do this, change the state to Production Change:

Customizing Workflow Administration 1363


6. Once the changes are made, click Save
7. Click Ok.
8. Back in the Life Cycle Administrator, check in the changes to the Two Phase
Life cycle

Executing the Use Case


Verify the changes with the UI.
1. Create a few new Parts (this will ensure they are all in the design state)
2. Copy the new Parts to the clipboard
3. Launch Create Change Notice wizard
4. On the implementation table of the Change Notice wizard, find the Default
Change Task, edit it.

1364 Customization Guide


5. Go to the Affected and Resulting step of the Change Task
6. Paste the parts into the Resulting Objects table.
7. Finish the Change Task wizard.
8. Finish the Change Notice, and select submit now.
9. Modify the Resulting Object, and complete the workflow tasks for the Change
Task
10. Upon Auditing the Change Notice, disapprove the changes made. The Change
Notice will now enter Refine Transition > Rework Task > Review Transition
as depicted above.
At this point, the workflow will execute the Refine Transition. This takes the
Change Notice and places it into a state in which the Resulting objects can be
modified.
11. As the Change Administrator you can go back and modify the Resulting
Object again. This time, modify it correctly so that the changes will be
approved by the Auditor.
12. Complete the Rework Task.
At this point, the Rework Task is completed, and the workflow will internally
run the Review Transition. This results in placing the Resulted objects back
into a state which cannot be modified. This ensures that the proper changes
will be reviewed by the Auditor the next time around.

Customizing Workflow Administration 1365


Adding Custom Workflow Attribute to
Workflow Processes
There are times when you might want to view variables from a workflow process
on the primary business object’s info page as an attribute. This section details how
to add customized workflow process attributes to the info page of an object. This
is accomplished by adding WFVariables of the WFProcess object to the
primary business object’s information page.

Scope/Applicability/Assumptions
This documentation assumes familiarity with:
• type attribute layouts
• creating new xconf entries
• using xconfmanager
• resource bundles
• defining variables in a workflow process

Adding the Custom Workflow Attribute to the


Workflow Process
This section contains an example of adding a work flow item attribute to the info
page of a Problem Report object.
You will add a new workflow item variable to a task by using Workflow Process
Management utility. In this example, add a variable with the name
testNewAttribute to the WFProcess.
The supported data types for the data utility are String, Date, Boolean, and
Number.

1366 Customization Guide


Adding the New Attribute to the Type Attribute Layout
Next, you must add a new attribute to the type attribute layout of the Primary
Business Object. In this case, you will add this entry to the info page attribute
layout for the loadFiles/type/WTChangeIssue.xml. The csvname is
important. The csvname must be the string “WFVAR_” followed by the variable
name chosen above for the WfProcess’s new variable. In this case, the full text
of the csvname is “WFVAR_testNewAttribute”.
<csvBeginAttributeDefView handler="com.ptc.core.lwc.server.
TypeDefinitionLoader.beginProcessAttributeDefinition">
<csvname>WFVAR_testNewAttribute</csvname>
<csvattDefClass>com.ptc.core.lwc.server.LWCNonPersistedAttDefinition
</csvattDefClass>
<csvdatatype>java.lang.String</csvdatatype>
<csvIBA/>
<csvQoM/>
<csvviewStyle/>
<csveditStyle/>
<csvdefaults/>
</csvBeginAttributeDefView>

Customizing Workflow Administration 1367


Registering the new attribute with xconfmanager
You will have to add this new attribute to be registered against the
WorkItemAttributeDataUtility. This can be done by adding the following to an
xconf entry to WorkItem-
components.dataUtilities.properties, and propagating xconf
properties (xconfmanager -pF)
<Option cardinality="duplicate"
requestor="null"
selector="WFVAR_testNewAttribute"
serviceClass="com.ptc.windchill.enterprise.
workitem.dataUtilities.WorkItemAttributeDataUtility"
/>

Changing the name of the attribute in the UI


By default, the name of the attribute would use the name of the key. At this point,
the information page would display a new attribute with the name
testNewAttribute. If you want to customize this value to a localized
attribute, you can add a new entry within the WorkItem/src/com/ptc/
windchill/enterprise/workitem/
workItemAttributeResource.java resource.
The name of the rbinfo key should match the variable name:

After you have done this, the attribute will now show up with the value defined by
the RBEntry annotation:

Verifying the Customization


Your customized attribute will be displayed on the information page of the
primary business object.

1368 Customization Guide


Workflow Email Notifications
This section provides you with details on customizing Windchill workflow email
notifications.
The following types of notifications are detailed :
• Workflow Task Notifications
• Workflow Process Notifications
• Workflow Notification Robot Notifications
• Calendar Delegate Notifications

Customizable Templates
To customize these notifications, you need to edit the html templates. Which
notification template needs to be edited for each notification type is listed below.

Workflow Task Notifications


General Template : <Windchill>\codebase\templates\
workNotification\General_<Locale>.html

Note
If you are using a separate template for “Subject” then edit the following
template: <Windchill>\codebase\templates\
workNotification\GeneralSubject_<Locale>.html

Workflow Process notifications :


There are various types of Workflow Process notifications that you can customize.
• Approaching Deadline Notifications
<Windchill>\codebase\templates\workflow\
ApproachingDeadlineNotification_<Locale>.html
• Overdue Notifications
<Windchill>\codebase\templates\workflow\
OverdueNotification_<Locale>.html
• Past Deadline Notifications
<Windchill>\codebase\templates\workflow\
PastDeadlineNotification_<Locale>.html

Customizing Workflow Administration 1369


Note
If you are using a separate template for “Subject” then edit the following
template: <Windchill>\codebase\templates\workflow\
DeadlineNotificationSubject_<Locale>.html

Workflow Notification Robot notifications :


• General Template: <Windchill>\codebase\templates\
workNotification\NotificationRobot_<Locale>.html

Note
If you are using a separate template for “Subject” then edit the following
template: <Windchill>\codebase\templates\
workNotification\NotificationRobotSubject_
<Locale>.html

Calendar Delegate Notifications:


• General Template : <Windchill>\codebase\templates\
calendar\DelegateNotification.htm

Note
If you are using a separate template for “Subject” then edit the following
template: <Windchill>\codebase\templates\calendar\
DelegateNotificationSubject_<Locale>.html

1370 Customization Guide


How to Customize Notification Templates
In an email notification template, the block between the Windchill script
beginSubject and endSubject are used to generate the email subject text.
This block can be added anywhere within the <html> tag in the template.
Windchill script calls made from beginSubject and endSubject tag will
customize the subject of the email where as Windchill script calls made from
<body> tag will customize the body of the email.
For example:
<html>
<SCRIPT LANGUAGE=Windchill> <!-- beginSubject --> </SCRIPT>
<SCRIPT LANGUAGE=Windchill> <!-- getSubject --> </SCRIPT>
<SCRIPT LANGUAGE=Windchill> <!-- endSubject --> </SCRIPT>
</html>

In the above example, an email generated for notification will have of subject
consisting of the methods defined in the “Subject” template mentioned above.
Alternatively, individual methods within Windchill tags can be added within the
beginSubject and endSubject tags.
<SCRIPT LANGUAGE=Windchill>
<!-- beginSubject -->
</SCRIPT>
<SCRIPT LANGUAGE=Windchill>
<!-- getProcessName -->
</SCRIPT>
<SCRIPT LANGUAGE=Windchill>
<!-- getPrimaryBusinessObjectName -->
</SCRIPT>
<SCRIPT LANGUAGE=Windchill>
<!-- endSubject -->
</SCRIPT>
There are standard methods written for these notification types. These are listed
below.

Common Methods
• addText text="<value>"
• getActivityName
• getActivityVariable varName="<Variable Name>" (not
applicable for Notification Robot)
• getInitSubject
• getPrimaryBusinessObjectName
• getProcessName
• getProcessVariable varName="< Variable Name >"

Customizing Workflow Administration 1371


Methods for Workflow Task Notification
• activityAttributes (This method shall be used in body only)
• activityNotificationUrl (This method shall be used in body only)
• getDeadline

Methods for Calendar Delegate Notification


• getDelegatedBy
• getDelegationDate
• getDelegationPeriod

Methods for Workflow Process Notification


• getDeadline
• getDeadLineLabel
• getOverdueTaskRow
• getOwnerRole
• getParentProcess
• getProcessManagerURL
• getState (This method shall only be used only be used for abort
notification.
• projectLinkAttributes (This method shall only be used for
projectlink notification body)

Methods for Workflow Notification Robot Notification


• activityDescription
• activityDescriptionPlain
• activityName
• getProcessManagerURL
• getProcessManagerURLPlain
• getProcessOverviewURL
• getProcessOverviewURLPlain
• messageText
• messageTextPlain
• primaryBusinessObjectLink
• primaryBusinessObjectLinkPlain
• processDescription

1372 Customization Guide


• processDescriptionPlain
• processName
• projectLinkAttributes (This method shall only be used for
projectlink notification body)

Customizing Workflow Administration 1373


Multiple Participant Selection Wizard
Customization
When implementing Windchill you can customize so that you have finer grain
control of what can be displayed in the participant selection table for a change
tasks or for promotion requests. The following information details the supported
customizations for the participant selection component in the change task and
promotion request wizards.

Solution
Extend the default participant configuration delegate to override the default
display of the participant picker in the change task or promotion request wizard.

Prerequisite Knowledge
To perform this customization you need to have an understanding of the
following:
• Basic development involving JAVA and properties.

Solution Elements
Element Package Type Description
ParticipantConfi- com.ptc.windchill. Interface The interface for
guration enterprise. the delegates
wizardParticipant. which control the
configuration display of the
wizard participant
selection table with
different
configurations.
DefaultParticipant- com.ptc.windchill. Class The default
Configuration enterprise. delegate for
wizardParticipant. displaying the
configuration wizard participant
selection table with
different
configurations.
PromotionPartici- com.ptc.windchill. Class The configuration
pantConfiguration enterprise.maturity. delegate for
configuration displaying the
promotion wizard
participant
selection table.

1374 Customization Guide


Element Package Type Description
typedservice. xconf Participant
properties.xconf configuration
delegates are
registered in the
typed service
properties.
ParticipantsForm- com.ptc.windchill. Class Form delegate for
Delegate enterprise. processing the
wizardParticipant. selection of
forms workflow team
participants.
PromotionPartici- com.ptc.windchill. Class Stores the selection
pantsFormDele- enterprise.maturity. process and the
gate forms.delegates selection of
workflow
participants for the
selected processes.

Customization Points
Override Display
To override the display of the participant selection picker in the change task or
promotion request wizard the DefaultParticipantConfiguration
delegate can be extended to provide the desired behavior. The promotion request
overrides some of the default display behavior which is implemented by the
PromotionParticipantConfiguration. To make use of the customized
participant configuration delegate it must be first registered in the
typedservice.properties for the type of object that the delegate is to be
used for. The typedservice.properties should not be directly updated
instead a custom typedservice.properties.xonf should be created to
register the delegate. Currently the supported types are promotion request, change
task and any sub types. The following is the example of a delegate registered for
the Promotion Request object.
<Service context="default"
name= "com.ptc.windchill.enterprise.wizardParticipant.
configuration.ParticipantConfiguration" >
<Option requestor="wt.maturity.PromotionNotice"
selector="wizardParticipantConfiguration"
serviceClass= "com.ptc.windchill.enterprise.maturity.configuration.
PromotionParticipantConfiguration" />
</Service>

Customizing Workflow Administration 1375


The following table describes specific display configurations which can be
overridden:
API Description Default Overridden
Behavior Behavior for
(Change Task) Promotion
Request
getWorkFlowTem- The work flow Looks up the life
plate process template cycle template
which is used to work flow process
define the template from the
displayed work selected object
flow roles for type in the wizard.
selection and the
resource pools
used to display the
list of participants.
getWorkflowRe- The resource pools The resource pools
sourcePools used to display the used to display the
list of participants list of participants
available for available for
selection. The map selection. Uses the
will contain the work flow process
work flow role as template returned
the key and value from
as a set of Context getWorkFlowTem-
Team, Team plate
Template, Team or (FormDataHolder)
Group. and the context
team from the
container found in
the form data.
getFixedRoleSe- The mapping of No roles are If the role is
lection initially selected marked as fixed. mapped to another
participant roles to role via promotion
work flow process "Fixed Roles For
roles to be Promote"
selected. These preference, then
roles can be we get the initially
unselected by the selected
user. participants from
the mapped role.
Otherwise the

1376 Customization Guide


API Description Default Overridden
Behavior Behavior for
(Change Task) Promotion
Request
initially selected
participants is
derived from the
given role.
getInitialRoleSe- The mapping of Uses the roles on No initial
lections fixed initially the object team selections.
selected participant template defined in
roles to work flow the object
process roles to be initialization rules.
selected. These
roles cannot be
unselected by the
user.
isSelectUser- When true users Enable selecting If the "Group
sInGroups can be selected users within Members Display"
within groups. groups. promotion
preference is set to
Yes the users can
be selected within
groups.

Customizing Workflow Administration 1377


API Description Default Overridden
Behavior Behavior for
(Change Task) Promotion
Request
excludedWork- Used to filter work No roles excluded. Excludes the
flowRoles flow roles. OWNER role.
excludedWork- Used to filter No roles excluded. The default is that
flowRolesForDis- workflow role no roles are
play columns from excluded. When
displaying in the the workflow
participant table. template variable
Any system "hideFixedRoles"
selected is set to true all
participants for the fixed roles are
hidden roles would hidden. The
still be saved. workflow template
variable
"overrideFixedRo-
leDisplay" is used
as an override to
filter out hiding the
fixed roles when
"hideFixedRoles"
is set to true. To
override more than
one role use the "|"
to separate the
roles.

Validate Participant Selections


Currently there is no validation of selections based on the configured resource
configurations. To validate the selections prior to processing the selections the
preProcess API on the ParticipantsFormDelegate or the
PromotionParticipantsFormDelegate can be overridden. The
getParticipantsToProcess API in the
ParticipantsFormDelegate can be leveraged to get the map of workflow
roles and the selection participants for the workflow role.
The getParticipantConfiguration API can then be used to get the
correct instance of the ParticipantConfiguration delegate in order to
evaluate the participant selections.

1378 Customization Guide


Exclude Workflow Roles for Display in the Promotion Request
The promotion request process workflow templates can be updated to exclude the
system fixed roles from being displayed on the promotion request participant
table. For example the Promotion Request Approval Process has two workflow
roles the Approver and Reviewer. There is a requirement that the Reviewers are
always predetermined and that the promotion request author should not be able to
set additional Reviewers.
In order for the fixed selected roles to be hidden in the table update the Promotion
Request Approval Process workflow template properties to include a new Boolean
variable called “hideFixedRoles” with a default value of “true”.

Since both Approver and Reviewer roles are configured as fixed system selected
roles they are both hidden in the participants table.

Customizing Workflow Administration 1379


In order to display the Approver role even though it is configured as a fixed
system selected role update the Promotion Request Approval Process workflow
template properties to also include a new String variable called
“overrideFixedRoleDisplay“ with the internal name of the role i.e.
“APPROVER”. Note that additional roles can be added using “|” to separate the
internal role names.

1380 Customization Guide


The Approver role column now displays in the participants table. Note that even
though the Review role column is not displayed, any preselected fixed system
participant role selections will still be processed when completing the promotion
request wizard.

Limitations
Custom display configurations are limited to the supported APIs in the
ParticipantConfiguration delegate.

Customizing Workflow Administration 1381


Customizing Change Activity Workflow
Assignments
You can customize the change activity workflow template so that rework activities
are assigned to the users that actually completed the original activities, rather than
simply being reassigned to the whole team.
The Windchill out-of-the-box (OOTB) change activity workflow template assigns
rework activities to all users specified in the “Assignee” role, regardless of which
users actually completed the original assignment. While this is appropriate for a
general OOTB workflow template, it may not serve the needs of customers who
assign groups of people to change activities and allow anyone in the group to
complete the task. In this case, you can assign rework activity to the person who
actually did the original task so they can quickly correct the work, rather than
assign it to the whole group where someone unfamiliar with the original work
may pick it up. In addition, you may want to use a different team role for rework
activities, such as a “Rework Assignee”.

Note
This process assumes familiarity with workflow processes for change objects
and workflow customization. The techniques described in this document are
limited to change object workflow templates.

Intended Outcome
Assume a case where a change task is created with three assigned participants
using the OOTB Change Activity Workflow template. When the change task is
first created its process page shows the following.

1382 Customization Guide


If User 2 actually takes on the task and completes it, then the Tasks for Change
Process table is updated to show the completed work task and a review task.

Customizing Workflow Administration 1383


If a problem is found during review, and the task is sent for rework, then a new
rework task is created for each of the original assignees. Any one of them may
now accept the rework task.

Creating rework tasks for all original team members may run contrary to a
company’s standard change process. For example, a change process may dictate
that only User 2, who originally performed the work, should be assigned to a
special “rework” role. And further, User 2 should be the only person assigned to a
rework task. The desired process page should show the following. This is only
possible by manually editing the process when using the OOTB Change Activity
Workflow template. A customized template is needed to automatically follow this
change process.

1384 Customization Guide


Solution
Customize the Change Activity Workflow template to automatically determine
who completed a work task and assign only that person (or persons) to the rework
role.

Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:

Customizing Workflow Administration 1385


• Workflow Processes for Change Objects
• Workflow Template Administration and Customization
• Life Cycle Template Administration and Customization
• Object Initialization Rules Administration and Customization
• Enumerated Type Customization
• Basic Java programming

Customization Points
Create Custom Rework Role
Use the enumCustomize tool to add a new rework role to
wt.project.RoleRB.rbInfo. See The Enumerated Type Customization
Utility on page 1981 for more information on using this tool.
The custom role “Rework Assignee” is used in this process. This step can be
skipped if a new role is not needed.

Customize Change Activity Workflow Template


1. Select Workflow Template Administration from Utilities page of a Site,
Organization, Product or Library context.
2. Select the “Save As” action for “Change Activity Workflow” template to
create a copy for customization. Select suitable name for the customized
workflow (for example, “Custom Change Activity Workflow”) is used in this
document. Always copy a workflow template before changing it; always avoid
customizing an OOTB workflow template.
3. Select the “Edit” action for “Custom Change Activity Workflow” template and
the change activity workflow graph is displayed in the Workflow Template
Editor. The area of interest for this customization is the rework loop, located in
the upper-right portion.

1386 Customization Guide


4. Double-click the “Rework Change Notice Task” to open the editor and select
the “Participants” tab. Add the “Rework Assignee” role and remove the
“Assignee” role. This step can be skipped if a new role is not needed.

5. Create a new expression step in the workflow between the “Set State
Implementation” and “Rework Change Notice Task” steps, and name it
something meaningful, such as “Set Rework Assignee”.

6. Add Java code to the “Set Rework Assignee” step to automatically obtain the
users that completed the prior work task and assign them to the change item
team for the rework task. See Java Helper Methods on page 1389 for a
description of helper methods that can be called here.
Example:
wt.project.Role reworkRole = wt.project.Role.toRole("REWORK_ASSIGNEE");
wt.project.Role participantsRole = reworkRole;

java.util.Map<wt.project.Role, wt.fc.collections.WTSet> roleToParticipantMap;


// Try to get participants from the rework activity.
roleToParticipantMap = com.ptc.windchill.pdmlink.change.server.
impl.WorkflowProcessHelper.getActivityParticipants(
(wt.change2.VersionableChangeItem) primaryBusinessObject,
"Rework Change Notice Task");

Customizing Workflow Administration 1387


// If the map is null then the rework activity has not executed yet.
if (roleToParticipantMap == null) {
participantsRole = wt.project.Role.toRole("ASSIGNEE");

// Try to get participants from the original activity.


roleToParticipantMap = com.ptc.windchill.pdmlink.change.server.impl.
WorkflowProcessHelper.getActivityParticipants(
(wt.change2.VersionableChangeItem) primaryBusinessObject,
"Complete Change Notice Task");
}

// Assign participants from original or rework activity to the


rework role on the change team.
// By doing so only those participants will get the next
rework tasks.
wt.fc.collections.WTSet participants = roleToParticipantMap.
get(participantsRole);
com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.
setChangeItemParticipants(
(wt.change2.VersionableChangeItem) primaryBusinessObject,
reworkRole, participants);

7. When the Java code is complete select the “Check Syntax” button to check for
errors. Be sure to correct all errors before using the custom workflow
template.
8. Save the changes made to the “Custom Change Activity Workflow” template
and check it in.

Customize Change Activity Life Cycle


Create a custom “Change Activity Life Cycle” template using the Life Cycle
Template Administration utility. Specify the custom workflow template created in
the previous section:

1388 Customization Guide


Customize Change Activity Object Initialization Rule
Create a custom “Change Activity” object initialization rule (OIR) using the
template using the Object Initialization Rules Administration utility. Specify the
custom life cycle template created in the previous section:

Java Helper Methods


Several Java helper methods are provided to simplify the code for automatically
making rework assignments. These methods are located in class:
com.ptc.windchill.pdmlink.change.server.impl.Workflow
ProcessHelper

Helper Method getActivityParticipants


/**

Customizing Workflow Administration 1389


* Get participants of a completed work activity for a change item.
* If the work activity was executed multiple times
* (e.g., a rework activity was run several times), then only
* the participants from the latest completed execution are returned.
*
* Supported API: true
*
* @param changeItem Work flow primary business object.
* @param activityName Work flow activity name.
*
* @return Map of activity roles to the participants for that role,
* or null if an activity with the specified name has not been
* executed for the change item.
*
* @throws WTException
*/
public static Map<Role, WTSet>
getActivityParticipants(VersionableChangeItem changeItem,
String activityName) throws WTException

Helper Method getChangeItemParticipants


/**
* Get all participants of a change item team.
*
* Supported API: true
*
* @param changeItem Change item object.
*
* @return Map of change item roles to the
* participants for that role.
*
* @throws WTException
*/

public static Map<Role,WTSet> getChangeItemParticipants


(VersionableChangeItem changeItem)
throws WTException {

Helper Method setChangeItemParticipants


/**
* Set the participants for a role of a change item team.
* The old participants of the role, if any, will be
* replaced with the new participants.
*
* Supported API: true
*
* @param changeItem Work flow primary business object.
* @param role Change item team role to be set.
*
* @param participants Collection of new participants for the role.

1390 Customization Guide


* Pass an empty set to remove all participants
* from the role. Pass null to remove the
* entire role.

* @throws WTException
*/

public static void setChangeItemParticipants(VersionableChangeItem changeItem,


Role role,
WTCollection participants) throws WTException {

Customizing Workflow Administration 1391


Customizing Change Tables Designed for
Workflow
There are customization and configuration options available for the configurable
task page layouts designed for the Change Management process. You can
configure the resulting or change summary table to have different views, actions,
and so on, that are specific to a workflow task.

Scope
Supported tables for configuration are
• Resulting Objects table
• Change Notice summary table

Intended Outcome
This document describes on how to create a new component which is a variant of
resulting or change summary table.

Prerequisite Knowledge
To perform these customizations, you must have an understanding of the
following:
• Java programming language
• Creation of new actions, and action models. For more information, see Adding
Actions and Hooking Them Up in the UI on page 511.
• The management of RBINFO files customizations. For more information, see
Resource Info (.rbInfo) Files on page 2071.
• Adding xconf entries and running xconfmanager. For more information, see
Using the xconfmanager Utility on page 164.

Solution
This section contains an example of adding a variant of Resulting Objects or
Change Summary table. This process includes the following steps:
• Define a new table component on page 1393
• Define a Workflow Action for the New Component on page 1394
• Adding New Resource Bundle Entries on page 1397
• Add new action to Workflow Task Components List on page 1397
• Build and Test on page 1397

1392 Customization Guide


Define a new table component
This process consists of the following steps:
• Define a new table id for new table component
• Register a table view class for the new table
• Define action models for the new table component

Define a New Table ID for New Table Component


The table ID for new component is customTask.resultingItems.

Register a Table View Class for the New Table


The table views listed below are the default table views defined for change tables
designed to be rendered in workflow pages.
Table View Class
Resulting Object com.ptc.windchill.enterprise.change2.
tableViews.
WorkflowTaskResultingItemsTable-
Views
Change Notice Summary com.ptc.windchill.enterprise.change2.
tableViews.
WorkflowTaskChangeSummaryTable-
Views
Register the appropriate table view to the new table by creating a new entry in the
custom service.properties.xconf file. Refer to Adding New Resource
Bundle Entries on page 1397 for details on how to add xconf entries for
registering a table view. You can extend the listed table view classes in case you
need to change the behavior of the view.
<Service context="default"
name="com.ptc.core.htmlcomp.tableview.ConfigurableTable">
<Option serviceClass=
"com.ptc.windchill.enterprise.change2.tableViews.
WorkflowTaskResultingItemsTableViews" selector="customTask.resultingItems"
requestor="java.lang.Object"/>
</Service>
Please refer to the “Adding a Custom Service Provider Property File” section of
Best Practices for Adding New Packages and Files on page 129 for more details
on creating custom xconf entries.

Customizing Workflow Administration 1393


Define Action Models for the New Table Component
The action model that defines the list of actions for tool bar actions and row object
actions needs to be defined in custom-actionmodels.xml. The expected
action model name for the table tool bar and row object actions should follow the
convention described in the following table.
Component Action Model Name Example
Tool Bar table id + “.table.view" "customTask.
resultingItems.table.view"
Row Object table id + “.row.actions. "customTask.
view" resultingItems.row.
actions.view"

Note
If the action model for the row object actions is not defined, the default action
model for the row object type is used.

Define a Workflow Action for the New Component


Define an action as a component to be added in Workflow layouts. An action
needs to be defined for the new table component to be shown in workflow task
pages. Note that the resource bundle entries for all custom actions should be
defined in the com.ptc.windchill.enterprise.object.CustomRB
file. For more information on how to create a new resource bundle file, see
Adding New Resource Bundle Entries on page 1397.
<objecttype name="object" class=""
resourceBundle="com.ptc.windchill.enterprise.object.CustomRB">
<action name="customTask_ResultingDataTable">
<description>Resulting data table for a new workflow
task</description>
<component name="workflowTask.pbo"
urlParams="pboCompId=changeTask.resultingItemsTable&amp;
useTypeBased=true&amp;changeableTableId=customTask.resultingItems&amp;
changeableLabel= com.ptc.windchill.enterprise.object.CustomRB.
CUSTOM_TASK_RESULTING_ITEMS_TABLE&amp;enableAddToWorkspace=true"/>
<includeFilter name="configurableTypeBaseFilter"/>
</action>
Tag Elements Description
action name - name for the new action for
workflow pages.
component name - Should be "workflowTask.pbo"
which denotes it is a subject(pbo)

1394 Customization Guide


Tag Elements Description
component on workflow pages.

Customizing Workflow Administration 1395


Tag Elements Description
urlParams Parameters to build the new table
component.
• pboCompId – the id of the
component of subject(pbo). The
below table refers to the
pboCompId for resulting objects
and summary table.
Component pboCompId
Resulting Object
“changeTask.
resultingItemsTa-
ble”
Change Summary changeNotice.
changeSummary

• useTypeBased is true as both


resulting object and summary table
component are defiend as
TypeBased. For more information
see, Configuring Workflow Task
Detail Pages
on page 1336.
• changeableTableId – The table id
for the new component. Example
for table id is ”customTask.
resultingItems”.
• changeableLabel= the resource
bundle entry of title for the new
table component. You need to add
an entry in CustomRB
• enableAddToWorkspace = flag that
needs to be passed for enabling add
to workspace action on change
tables.
includeFilter • name - configurableTypeBaseFilter;
You need to add entries to type
based action filter properties if the
component needs to be filtered by
type. For more information see,
Configuring Workflow Task Detail
Pages
on page 1336

1396 Customization Guide


Tag Elements Description
• Adding Actions and Hooking Them
Up in the UI on page 511

Adding New Resource Bundle Entries


A new file needs to be created under <Windchill>/wtCustom/<custom-
subdirectories>, (for instance CustomRB.java must be added under
<Windchill>/wtCustom/com/ptc/windchill/enterprise/
object folder), if a resource bundle does not exist for custom resource bundle
entries.
Expected resource bundle entries for actions are:
@RBEntry("Custom Resulting Objects")
@RBComment("Used as the label for the action")
public static final String CUSTOM_RESULTING_DESC =
"changeTask.customTask_ResultingDataTable.description";

@RBEntry("Custom resulting objects")


@RBComment("Used as the tooltip for the action")
public static final String CUSTOM_RESULTING_TOOLTIP =
"changeTask.customTask_ResultingDataTable.tooltip";

@RBEntry("Custom Resulting Objects")


@RBComment("The table title for the custom resulting
objects table on a custom workflow task.")
public static final String CUSTOM_TASK_RESULTING_ITEMS_TABLE
= "CUSTOM_TASK_RESULTING_ITEMS_TABLE";

For more information on creating custom xconf entries, see Compiling Custom
Classes on page 132.

Add new action to Workflow Task Components List


Add the new action/component to respective action models as detailed in
Configuring Workflow Task Detail Pages on page 1336 to make the component an
available component to be rendered in workflow task pages.
Adding Actions and Hooking Them Up in the UI on page 511

Build and Test


Once you compiled the new classes and propagated the xconf entries, restart the
method server. You should be able to configure the new component via the
workflow task form templates, so that the component is rendered in the specified
workflow task pages.

Customizing Workflow Administration 1397


Locking Annotations In Change
Workflows
You can have annotations associated to the change be locked and/or unlocked at
various points in the workflow. This section how to add annotation locking and
unlocking to Workflow Templates.

Prerequisite Knowledge
To achieve the intended result you need to have an understanding of the following:
• Modifying and/or creating Workflow Templates.
• Working with expressions in workflow nodes using the Java Language

1398 Customization Guide


Define a Workflow Robot to Lock Annotations
To lock annotations on a Change Notice after the Change Notice is resolved, insert
a new robot in between the “Set Change Notice Resolution Date” node and the
“Or” node:
1. Select the new Execute Expression robot from the toolbar.
2. Insert the expression in between the “Set Change Notice Resolution” and the
“Or” as indicated below

3. Add a description and name.


4. Enter the following Java into the Expression tab to lock the annotations:
wt.fc.collections.WTSet changeObjects =
wt.fc.collections.CollectionsHelper.singletonWTSet(primaryBusinessObject);
wt.change2.ChangeLockHelper.service.
lockRelatedMaterials(revisedChangeObjects,
wt.change2.ChangeApplicationLock.
LOCK_SUPPORTINGMATERIAL);

Customizing Workflow Administration 1399


Define a Workflow Robot to Unlock Annotations
To unlock annotations when a Change Notice is revised, insert a new robot in
between the “Reassign to Original Author” node and the “Or” node:
1. Select the new Execute Expression robot from the toolbar as above and insert
the new expression.

2. Add a description and name.


3. Enter the following Java into the Expression tab to unlock the annotations:
wt.fc.collections.WTSet revisedChangeObjects =
wt.fc.collections.CollectionsHelper.singletonWTSet(primaryBusinessObject);
wt.change2.ChangeLockHelper.service.
unlockRelatedMaterials(revisedChangeObjects,
wt.change2.ChangeApplicationLock.LOCK_SUPPORTINGMATERIAL);

1400 Customization Guide


30
Customizing Life Cycle
Administration
Customizing the Display of Life Cycle Information .................................................... 1402
Defining Custom Life Cycle Transitions ................................................................... 1404
Setting Up a Customized State-Based Versioning Scheme....................................... 1407

This section describes how to customize life cycle administration.

1401
Customizing the Display of Life Cycle
Information
The way life cycle state information is displayed, particularly in life cycle-
managed object properties pages, can be customized by setting configurable
components in the wt.lifecycle.lifecycleResource*.java files. You can set values
for the following entries:
STATES_SEPARATOR
When displaying a string of states, this value is the separator between each of
the states listed. Default is " - ".
CURRENT_STATE_BEGIN
When displaying a string of states, this value is the notation that a particular
state is the current state. Default is "<B>".
CURRENT_STATE_END
When displaying a string of states, this value is the notation that a particular
state is the current state. Default is "</B>".
DROPPED_STATE_BEGIN
This entry notes that the current state (usually dropped) is not found in the list
of current states. Default is " [".
DROPPED_STATE_END
This entry notes that the current state (usually dropped) is not found in the list
of current states. Default is "] ".
IS_AT_GATE
This value is used to indicate that Awaiting Promotion = true. Default is "Yes".
IS_NOT_AT_GATE
This value is used to indicate that Awaiting Promotion = false. Default is
"No".
LABEL_BEGIN
This value is used when displaying any of the StateProcessor labels. Default is
"<B>".
LABEL_END
This value is used when displaying any of the StateProcessor labels. Default is
": </B>".
STATE_LIST_BEGIN
When the list of states is provided along with other information, this entry
differentiates the State list from other information in the display. Default is "(".
STATE_LIST_END
When the list of states is provided along with other information, this entry
differentiates the State list from other information in the display. Default is ")".

1402 Customization Guide


HISTORY_LABEL
This entry is used when displaying a link to the Life Cycle History page.
Default is "History".
HISTORY_NOTATION_BEGIN
When the history link is provided along with other information, this entry
differentiates the History link from other information in the display. Default is
" (".
HISTORY_NOTATION_END
When the history link is provided along with other information, this entry
differentiates the History link from other information in the display. Default is
") ".

Customizing Life Cycle Administration 1403


Defining Custom Life Cycle Transitions
You can create custom life cycle transitions that you can then define between life
cycle states using the Life Cycle Administration utility.
There are two methods to accomplish this:
• Use the Enumerated Type Customization Utility
• Create a custom TransitionRB.rbInfo file

Note
If you want to use the new transition as part of a change process, you must
perform additional steps. For more information, see “Custom Change Process
Transitions” in the Windchill Help Center.

Use the enumcustomize Utility


1. From a Windchill shell, run the following command:
enumcustomize
2. The Enumerated Type Customization Utility window opens.
3. Click Browse and navigate to the following file:
codebase\wt\lifecycle\TransitionRB.RB.ser

1404 Customization Guide


4. Click New to create a new transition:

5. Select the Selectable checkbox.


6. Click Save and Exit.
7. From the Windchill shell, execute the following command:
ant -f codebase\makejar.xml

Modify TransitionRB.rbInfo
The follow example creates a new transition called “Reject”:
1. Locate the following file (or create it if it does not exist):

Customizing Life Cycle Administration 1405


<Windchill>/wtCustom/wt/lifecycle/
TransitionRB.rbInfo
2. Add the following entry:
USER_REJECT.value=Reject
USER_REJECT.shortDescription=Reject transition

3. Build the runtime resource bundles for the customized packages by entering
the following command from a Windchill shell:
ResourceBuild wt.lifecycle.TransitionRB

Results
As a result:
• The new transition is added to the transitions that are available when you
create or update life cycles using the Life Cycle Administration utility.
• The new transition can be accessed programmatically.
• You can invoke the navigate() method to find the valid transitions
between states using that new transition:
WTKeyedMap rejectMap=new WTKeyedHashMap();
Set rejectSet = new HashSet();
State rejectState=State.toState("DESIGN");
rejectSet.add(rejectState);
rejectMap.put(<life_cycle_managed>, rejectSet);
WTKeyedHashMap returnMap =
(WTKeyedHashMap) LifeCycleHelper.service.navigate
(rejectMap,
Transition.toTransition("USER_REJECT"),
true);

The above call to navigate() returns the successor states to the DESIGN
state on a life cycle managed object (<life_cycle_managed>), following
valid USER_REJECT transitions.

1406 Customization Guide


Setting Up a Customized State-Based
Versioning Scheme
Setting up a customized state-based versioning scheme consists of the following:
• Adding The Series To StateBasedVersioning.xml And Loading The File on
page 1407
• Making The Newly Added Version Schemes Available In The Lifecycle
Administrator on page 1408
• Creating A Lifecycle Template Which Uses The New Version Series on page
1410
• Setting Up The Object Initialization Rules on page 1410
• How The Revision Scheme Can Be Used on page 1412

Adding The Series To StateBasedVersioning.xml


And Loading The File
1. Make a backup copy of the StateBasedVersioning.xml file, located
under <Windchill>\loadFiles\pdmlink.
2. Append your versioning schemes to the existing file using a text editor so that
it matches your requirements.
The stated based series makes use of <seed name> elements within the xml
file to define the Version Series and the example below contains an additional
2 series’ ‘PROTOTYPE’ which will define versions ‘proto_1’ to ‘proto_
10’ and ‘RELEASED’, which runs from ‘rel_A’ to ‘rel_F’. These series’
have been added as extra “seeds” to the original NUMERIC and MILSTD, and

Customizing Life Cycle Administration 1407


will be available as options in the Lifecycle Administrator “Version Series”
dropdown:

3. Load the file into Windchill using the following command:


C:\ptc\Windchill>java.wt.series.LoadFileBasedSeries C:\ptc
\Windchill>loadFiles\pdmlink\StateBasedVersioning.xml -load

4. You will be prompted to log in as a member of the Administrators group.


Observe the warning that THIS WILL OVERWRITE THE EXISTING
SERIES.
Once the file has been loaded, you will receive a message: “Successfully
saved FileBasedSeries”.

Making The Newly Added Version Schemes


Available In The Lifecycle Administrator
Customize the Lifecycle Administrator, adding the two seeds as options to the
‘Version Series’ drop-down.
This is done using the enumCustomize utility found in <Windchill>\bin,
and the file to modify is the Resource Bundle
wt.series.SeriesRangeSelectorRB.

1408 Customization Guide


Ensure that the key that you add matches the name of the seed you have defined in
the StateBasedSeries.xml. Below is an example of how to add the
PROTOTYPE seed, which we added as a seed and loaded in Step 1.

Rebuild the resource:

Customizing Life Cycle Administration 1409


Finally, rebuild the jars in a Windchill shell with the following command:
<Windchill>\ant\bin\ant -f <Windchill>\codebase\makejar.xml

Note that the extra series’ were added using the ‘Default’ locale in the
enumCustomize utility. This means that they will only be visible if the browser
language is set to English (US).

Creating A Lifecycle Template Which Uses The New


Version Series
Now that the “Version Series” dropdown contains the appropriate options, we can
proceed to create a Lifecycle Template which will use them.
In this instance, a lifecycle called prototype_released was created which
uses the PROTOTYPE version series in the Prototype phase, and the RELEASED
version series in the Released phase.

Setting Up The Object Initialization Rules


Set up the Object Initialization Rules so that the Object is associated with the
newly created Lifecycle, and takes the StateBased versioning scheme where the
seeds are defined.
The example below shows a modified initialization rule for a WTPart.
<AttributeValues objType="wt.part.WTPart">
<!-- set the folder -->
<AttrValue id="folder.id"

1410 Customization Guide


algorithm="com.ptc.core.foundation.folder.server.impl.
FolderPathAttributeAlgorithm">
<Arg>/Default</Arg>
</AttrValue>

<!-- set the lifecycle -->


<AttrValue id="lifeCycle.id"
algorithm="com.ptc.core.foundation.lifecycle.server.impl.LifeCycleTemplate
Attribute
Algorithm">

<Arg>
<!-- Translation of the word "Basic" must be the same as
the translation done in commonLifeCycles.xml -->
<?loc-begin key="BASIC_LIFECYCLE_NAME"
maxlen="30"?>Basic<?loc-end?>
</Arg>

</AttrValue>

<!-- set the team template -->


<AttrValue id="teamTemplate.id"
algorithm="com.ptc.core.foundation.team.server.impl.TeamTemplateAttributeAl
gorithm"
>
<Arg>Default</Arg>
</AttrValue>

<!-- set the number to a generated number -->


<AttrValue id="number"
algorithm="com.ptc.windchill.enterprise.revisionControlled.server.impl.Number
Genera
tor">
<!-- add a V prefix for variant parts -->
<Value algorithm="wt.rule.algorithm.BooleanBranch">
<Value algorithm="wt.rule.algorithm.EqualsTest">
<Attr id="genericType"/>
<Arg>variant</Arg>
</Value>
<Arg>V</Arg>
<Arg></Arg>
</Value>

<!-- the sequence -->


<Arg>{GEN:wt.enterprise.SequenceGenerator:WTPARTID_seq:10:0}</Arg>
</AttrValue>

Customizing Life Cycle Administration 1411


<!-- set the version info to a generated version info -->
<AttrValue id="MBA|versionInfo"
algorithm="com.ptc.core.foundation.vc.server.impl.VersionInfoGenerator">
<Arg>wt.series.HarvardSeries</Arg>
</AttrValue>
</AttributeValues>

Note
If this rule is defined at Site or Organization level, object initialization rules
defined at context level may need to be disabled.

Automatic Part Numbering - Upgrade Considerations


On any system upgraded to Windchill release 9.x or any new installation where
part Object Initialization Rules are customized, the following must be considered.
Variant Part Creation fails when Part automatic numbering is turned off; Part
Object Initialization Rules are customized to turn off automatic numbering. This
results in the failure of VariantPart creation (Request Deliverables action on
VariantSpecifications).
Variants are auto generated by the system and automatic numbering cannot be
turned off for the variant parts. If you need to turn off automatic numbering for
parts other than variants, the following code sample shows how to modify the Part
Object Initialization Rules xml file for the "number" attribute.
<AttrValue id="number"
algorithm="wt.rule.algorithm.BooleanBranch">
<Value algorithm="wt.rule.algorithm.EqualsTest">
<Attr id="genericType"/>

How The Revision Scheme Can Be Used


The screenshots below show examples of a WTPart created and associated to the
above Lifecycle. The part initially started as version proto_1 and was revised to
proto_2.
The part was then promoted to the “Released” phase, then revised again.

1412 Customization Guide


Note
The version now shows rel_A, as defined in the StateBasedVersioning.xml file
in the beginning.

Customizing Life Cycle Administration 1413


Caution
This procedure should be performed immediately after installation, and before
any objects are created in the Windchill system. If objects have already been
created using a different versioning scheme, then the behavior when these
objects are revised will be unpredictable.

1414 Customization Guide


31
Customizations in Type and
Attribute Management
Using a BusinessAlgorithm in a Calculated Attribute ................................................ 1416

This section contains information on customizations within the Type and Attribute
Management utility.

1415
Using a BusinessAlgorithm in a
Calculated Attribute
You want to easily create an attribute whose value is the result of a complicated
computation.

Background
You want to define complex calculated attributes that cannot be expressed with the
simple OOTB operations available for combining attribute values from a given
object. In some cases, the algorithms may be more complex than the basic
operations. In some cases the calculation may need to traverse relationships to
other objects, often recursively, to accumulate information from a structure. In
some navigation, config spec processing may be involved. In some cases, data
from an external system may be required. You want a simple API for defining and
implementing these custom algorithms, and want to assign the values of those
calculations to an attribute in the Type and Attribute Management utility.
You can implement a BusinessAlgorithm class and easily execute it with a
calculated attribute to see the results of your complex calculations in Windchill
UIs.

Scope/Applicability/Assumptions
BusinessAlgorithm is only for use with calculated attributes.

1416 Customization Guide


Solution
Implement a custom BusinessAlgorithm and execute it with a calculated
attribute.

Prerequisite Knowledge
To achieve this result, you need to have an understanding of the following:
• Calculated Attributes — Attribute Customization on page 658

Solution Elements
Element Type Description
BusinessObject Java Interface This class provides the
public APIs to create,
retrieve, and modify an
instance of business
object.
• Descriptor
information should be
retrieved from the
BusinessField.
BusinessObjectHelper Java Class This class provides the
public APIs to create,
retrieve and modify
business objects in bulk.
• This supports working
with heterogeneous
types of business
objects.
BusinessAlgorithmCon- Java Interface This class provides the
text public API for accessing
BusinessObjects that are
stored in the
MethodContext and is
used to pass them and the
Locale into the
calculation engine. It
provides a cache that
custom
BusinessAlgorithms can
use to store state between
executions, and it
provides an index into the

Customizations in Type and Attribute Management 1417


Element Type Description
list of BusinessObjects to
indicate which is
currently being evaluated
against.
BusinessAlgorithm Java Interface This interface is
implemented by
application developers
and customers who want
to define new calculated
attribute operations.
These operations may
involve complex or
expensive business logic.
Classes Implementing
this interface must be
public and must provide a
public no argument
constructor.
execute() Calculated Attribute The new function for use
Function in calculated attributes
which create an instance
of a BusinessAlgorithm,
invoke its execute
function, pass the
arguments specified in the
Type and Attribute
Management utility, and
return its results to the
calculated attribute layer
to be used by further
formula processing.

1418 Customization Guide


Procedure – Using a BusinessAlgorithm in a
Calculated Attribute
Implement the BusinessAlgorithm Class
BusinessAlgorithm is an interface that defines two methods: execute and
getSampleValue.
public Object execute(BusinessAlgorithmContext context, Object[] args);
public Object getSampleValue();

To use your complex computations in a calculated attribute you need to start by


creating a new class that implements this interface. The execute method should
return the final result that you want to see in a Windchill UI or use in further
calculation within the calculated attribute formula. The getSampleValue API
is used when formulas are created and validated in the Type and Attribute
Management utility. It should return a realistic example value for the result of
execute. This is so that it is not necessary to do the real, presumably expensive,
computations in execute in order to validate the return type of your
BusinessAlgorithm.
Here’s a very simple example of a BusinessAlgorithm
/**
* Hello World example BusinessAlgorithm
*/
final public class HelloWorldBusinessAlgorithm implements BusinessAlgorithm {

@Override
public Object execute(BusinessAlgorithmContext context, Object[] args) {
// Your complex calculations should go here
return “Hello World: “ + args[0];
}

@Override
public Object getSampleValue() {
// A realistic example value of the same type as the result of execute
// should be returned here. For this case a string.
return “A Sample Value”;
}

Create the calculated attribute


To use the output of your calculations in a calculated attribute you use the new
execute function.
Here are the steps to invoke the HelloWorldBusinessAlgorithm

Customizations in Type and Attribute Management 1419


1. In the Windchill Type and Attribute Management utility create a string
calculated attribute.
2. On the set properties step define the formula that calls the execute function
like so:
execute(“com.mycompany.HelloWorldBusinessAlgorithm”,
“My Function Works”)
3. This formula evaluates to the string “Hello World: My Function Works” and
that is what is displayed in the UI.
In this case the result of the execute function on the BusinessAlgorithm is a
string. So we created a string calculated attribute. The result of the function could
be any of the datatypes available for calculated attributes. When creating your
calculated attribute, be sure the datatype matches the expected return type of your
BusinessAlgorithm class.

Additional Formula Examples


When creating your formula on your calculated attribute you can combine the
execute function with any of the other functions and operands available for
formulas. However, one of the following conditions must be met:
• The data type returned from your formula is supported by the function or
operand you are trying to use,
• The datatype returned from the other function or operand is supported by your
BusinessAlgorithm.
You can pass attribute values or function results to the execute function as
arguments, and you can pass as many arguments as you need. For Example:
execute(“com.mycompany.MyComplexBusinessAlgorithm”,
<atttributeName1>, round(<attributeName2>),
100*<attributeName3>)
You can also pass the result of the execute function to other functions in the
formula. For Example:
round(execute(“com.mycompany.MyComplexBusinessAlgor
ithm”, <atttributeName1>, 100*<attributeName3>))

1420 Customization Guide


Performance Considerations
Be aware that your business algorithm will be evaluated wherever your calculated
attribute appears in the Windchill UI. For example, if a table has been customized
to display your calculated attribute, the business algorithm needs to be run for
each row in the table. If the algorithm involves database queries or complex
computations it could potentially cause significant performance issues. Therefore
it is highly recommended that your business algorithm be as performant as
possible. Some ideas could include batched database queries, caching results and/
or partial static computations, etc.
You may refer to the sample “sum” algorithm
(AbstractCarambolaAttributeSumBusinessAlgorithm) discussed
below, for an example on a reasonably performant algorithm for summing the
values of an attribute over an entire Part structure. Also, you could refer to the
CarambolaAttributeSumBusinessAlgorithmTestIntegration
test for an example of performance testing this sample business algorithm.

Note
Rendering business algorithms in the PSB tree may take some additional time
to complete. Therefore, it is recommended that your BusinessAlgorithm
be as performant as possible.

Sample Code
Packaged Samples
AbstractCarambolaAttributeSumBusinessAlgorithm
This is an example business algorithm that calculates and return the numerical
"sum" of the specified attribute on all of the parts in a part structure. This
algorithm is intended to be used in a "Formula" property on a numeric attribute.
The internal name of the attribute to sum is passed in as the first argument to the
algorithm.
Because the technique to add a list of numbers varies based on the data type,
subclasses of this abstract class will actually handle the summing of values of
different data types. We provide 3 subclasses that handle these data-type specific
details:
• IntCarambolaAttributeSumBusinessAlgorithm
• FloatCarambolaAttributeSumBusinessAlgorithm
• FloatWithUnitCarambolaAttributeSumBusinessAlgorithm

Customizations in Type and Attribute Management 1421


These subclasses must override 2 data-type specific methods: one is to provide a
typical sample value of that data type that is used for formula validation
(getSampleValue()), and one is to add up a list of values of this data type
(calculateSumValue()).
So to use this algorithm on a floating point attribute, enter something like the
following expression in the formula property of a calculated attribute in the Type
and Attribute Management utility:
execute("com.ptc.carambola.customization.examples.busi
nessfield.FloatCarambolaAttributeSumBusinessAlgorithm",
"<name of a floating point attribute>")
This example code can be viewed in this location: <Windchill>/
DevModules/Carambola/src/com/ptc/carambola/
customization/examples/businessfield/

Files Used in This Example


• <Windchill>\DevModules\Carambola\src\com\ptc\
carambola\customization\examples\businessfield
\AbstractCarambolaAttributeSumBusinessAlgorithm.java
• <Windchill>\DevModules\Carambola\src\com\ptc\
carambola\customization\examples\businessfield
\IntCarambolaAttributeSumBusinessAlgorithm.java
• <Windchill>\DevModules\Carambola\src\com\ptc\
carambola\customization\examples\businessfield
\FloatCarambolaAttributeSumBusinessAlgorithm.java
• <Windchill>\DevModules\Carambola\src\com\ptc\
carambola\customization\examples\businessfield
\FloatWithUnitCarambolaAttributeSumBusinessAlgor
ithm.java

Explanation of example code


The execute() method first gets the name of the attribute to sum, and the
current business object (a WTPart). Next it calls a
getAllPartStructure(final BusinessObject
curBusinessObject) helper method to walk down the part structure tree of
the current business object, returning a WTCollection of the parts in that
structure. (This is done using the wt.navigation.PartRequest and
wt.navigation.DependencyHelper classes.)
After getting the collection of parts in the structure, execute() next calls a
getBusinessField( final String fieldName, final
TypeIdentifier contextType ) helper to return the BusinessField
object that should be summed over the structure.

1422 Customization Guide


Then execute() calls the getPartStructureValues(final
WTCollection partCollection, final BusinessField
fieldToSum ) helper to get a list of values of the desired business field on all
of the parts in the structure. This helper first uses the
com.ptc.core.businessfield.server.businessObject.Busi
nessObjectHelper class to create and load all of the business objects at once
(if they aren’t already loaded). Then it loops over the business objects and grabs
the value(s) in the fieldToSum business field and adds them to a list. Finally
the list of values is returned.
Next, execute() calls the subclass-overridden
calculateSumValue(List<Number> allValuesForAttribute)
method to actually sum all of the values into a total. (If you take a look at the
different subclasses you see that summing long values is simple, but adding
floating point values needs to take into account the units & precision.)
Finally, execute() returns the total, which is then returned as the value of the
“execute()” formula function. (If the Formula only contains the execute()
function, then this is also the value of the entire formula and the attribute.)

Related Information
Related Customization Documentation
• Calculated Attributes — Attribute Customization on page 658

Related Package/Class Javadoc


• BusinessObject
• BusinessObjectHelper
• BusinessAlgorithmContext
• BusinessAlgorithm

Customizations in Type and Attribute Management 1423


32
Options and Variants
Customizing Options and Variants .......................................................................... 1426

This section describes the customization points in the Windchill Options and
Variants capabilities.

1425
Customizing Options and Variants
Architecture Overview
Options and Variants have an OptionSet object that holds the information
about a set of option choices. This option set is used to assign option choices to
the ChoiceMappable object. ChoiceMappble are objects, when associated
with choices, that can participate in Options and Variant capabilities. option set
assignment is a way to define the selection of an option set for an object. WTPart
andWTPartUsageLink are examples of ChoiceMappable objects. See the
Windchill Java Documentation for more information about the
ChoiceMappable object.
Windchill Options and Variants provide a Delegate Framework to get the option
set to be used by various functions that require an OptionSet. The default
implementation uses the RegisterOptionsetLink association. This
association assigns an option set to an object. You can override this by
implementing a custom delegate.

Windchill Option Set Delegate Framework


Customizations
This section describes how you write custom delegate and use the delegate
framework.
You can modify the capability provided in Windchill Options and Variants for
assignment of option set. Specifically, you can:
• Restrict Windchill object to assign option set
• Extend option set delegate

Restrict Windchill Object to Assign Option Set


In your Windchill system based on your business requirements you may be a need
to restrict specific type of object from being assigned with an option set.
In a product structure assembly there is a type of part, where due to the business
rules, the system should not allow the assignment of an option set and does not
allow capability to assign choices on specific type of part. You can restrict this for
a business object or a subtype of a business object.

1426 Customization Guide


Procedure
In order to restrict a specific object type for assigning option set object, Windchill
provides the
com.ptc.windchill.option.delegate.impl.NullOptionSet
FetcherDelegate delegate. You can specify this delegate for an object type
you want restrict. This can be defined using a service property in Windchill.
These Windchill properties are defined using the Windchill XCONF feature. See
the Windchill Business Administrator's Guide for details on XCONF files and how
to create them.

Example: Restrict the Option Set Assignment


Suppose that you wish to restrict the option set assignment to say subtype of part
viz.com.myorg.OrgPart:
1. Create an XCONF file that contains the appropriate new value for the property
com.ptc.windchill.option.delegate.OptionSetFetcherDe
legate.
2. Use the XCONF Manager to update Windchill services properties.
The following XML document is an XCONF command to restrict a object to
assign option set:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">

<Configuration targetFile="codebase/service.properties">
<!-- OptionSet Fetcher Delegates -->
<Service context="default" name="com.ptc.windchill.
option.delegate.OptionSetFetcherDelegate">
<Option cardinality="duplicate" requestor="null"
selector="WCTYPE|wt.part.WTPart| com.myorg.OrgPart"
serviceClass="com.ptc.windchill.option.delegate.impl.
NullOptionSetFetcherDelegate"/>
</Service>

</Configuration>

3. The following command saves the changes in the file to Windchill services
properties:
xconfmanager -i codebase/com/ptc/windchill/options/
customization/example1.properties.xconf -p
This command causes Windchill to restrict all object of this type for assigning
an option set.

Options and Variants 1427


Note
The code above is an example. You must have appropriate type of object
defined in system and XCONF file created at appropriate location.

Extend Option Set Delegate


Option set assignment is a default way to define the selection of option set for an
object. This option set determined by delegate is used for following purposes by
the system:
1. Determine set of option choices to be assigned to an object.
2. Override the option set by new or old version based on the need.
3. Determine option choices to filter the structure.
In your Windchill system, based on a business requirement you may need to
customize the logic that determines the option set based on context/selected
object. Customization allows the following scenarios:
• Extend existing logic for new set of object.
• Modify implementation to consider out-of-the-box logic with some additional
business rules.
• Implement custom logic to determine option set.

Option Set Assignment Delegate framework


The option set Assignment Delegate framework provides set of classes with some
methods. These classes can be extended and methods can be implemented for
customization as required. This delegate will return the option set to be used by
the Windchill system. When option set is overridden with a specific version of
option set delegate, it will return the overridden version of option set to the
Windchill system.
Following are some of the important classes of this framework for customization.

RegisteredOptionSetLink
Out-of-the box association class that associates an OptionSet to an
OptionSetAssignable object. With this by default option set gets assigned
to an OptionSetAssignable object.

1428 Customization Guide


AbstractOptionSetFetcherDelegate
This is an abstract delegate class defined to provide customization capability to UI
and processing. This class has following methods which can be implemented to
customize logic:
• getAssignedOptionSet : This is a abstract method that can be
implemented to determine option set for specified object.
• isAssignOptionSetAllowed : This is a method that tells the system if
custom logic needs the capability of assigning option set to object in user
interface. When this is allowed you can use the UI to create
RegisteredOptionSetLink association with an object.

RegisteredOptionSetFetcherDelegate
This is the default delegate used Windchill to determine option set for an option
set assignable object. This delegate implements getAssignedOptionSet
defined by AbstractOptionSetFetcherDelegate. While determining
option set this delegate use RegisteredOptionSetLink association to find
assigned option set for an object. If no option set for an object is found and if an
object is contained, the object will check if option set is available in its container
hierarchy. It only considers container for an object that are instance of
OptionSetAssignable.
Delegate Framework Classes
com.ptc.windchill.option.delegate.AbstractOptionSetFetcherDelegate
com.ptc.windchill.option.delegate.impl.RegisteredOptionSetFetcherDelegate
com.ptc.windchill.option.delegate.impl.NullOptionSetFetcherDelegate

Please refer to the Windchill Java Documentation for more information about
method signature and expected input and output parameters.

Writing custom Delegate


When you are interested in developing your own logic to determine option set you
can write new delegate that extends
com.ptc.windchill.option.delegate.AbstractOptionSet
FetcherDelegate and implement method getAssignedOptionSet. This
custom delegate can be registered in system for a specific type of object. With this
it is possible to write custom logic for determining option set for out-of-the-box
objects or for custom objects.

Extend default registered option set delegate


In order to customize the out-of-the-box logic of the OptionSetDelegate that
determines option set for an object in Windchill, you can extend
com.ptc.windchill.option.delegate.impl.

Options and Variants 1429


RegisteredOptionSetFetcherDelegate and override the method
getAssignedOptionSet for custom logic. With the extension of this class
you can take advantage of both the OOTB delegate and your own business logic.

Procedure
Procedures for extending classes using the Windchill Information Modeler are
defined in the Windchill Customization Guide. For simple extensions of the
default interface implementation use this process:
1. Define the java source file using the editor or Integrated Development
Environment (IDE) of your choice.

Note
Do not modify or replace any classes that were provided when Windchill
was installed. These files may be replaced by future software releases.

2. Compile the java source file into the Windchill codebase.


3. Create an XCONF file that contains the appropriate new value for the property
to register your delegate in Windchill system.
4. Use the XCONF Manager to update Windchill services properties.
These Windchill properties are defined using the Windchill XCONF feature. See
the Windchill Specialized Administration Guide for details about the XCONF files
and how to create them.

Example
You have defined a new custom type of part with its own set of business rules.
The requirement for this type or its structure is such that it determines the option
set with some custom logic. This custom logic does not require any direct
association with the part type. Instead it uses some information on a part to
determine option set. It also requires that there is no option set determined. Then
based on information on the part it expects to use out-of-the box behavior to
determine the option set.

1430 Customization Guide


33
Customizing Security Labels
Customizing Security Labels .................................................................................. 1432

This chapter contains details on customizing security labels to providing the set of
security label values for a given custom security label and for determining
authorized participants for each security label value on either a standard or custom
security label.

1431
Customizing Security Labels
There are two types of security labels available in Windchill: custom security
labels and standard security labels. For both standard and custom security labels, a
security label always has a null, or unrestricted, label value and can have one or
more additional label values. These non-null label values can be defined to allow
access only to users who are cleared for that label value. Cleared users are called
authorized participants. Security label values that clear all users can be used as
purely informative markings.
Standard security labels have a pre-defined set of a null and one or more non-null
values established when the standard security label is configured. When applying
a standard security label to an object, a user selects the null or one of these pre-
defined non-null values from a drop-down list. Each object can have only one
value applied for each standard security label configured.
Custom security labels do not have a pre-defined set of values. When applying a
custom security label to an object, a user enters a value for the custom security
label into a text field or leaves the text field blank to specify the null value. The
set of custom values may be too numerous or complex to pre-define, or may
originate outside of Windchill. You can customize how the custom security label
values are translated between the external display value in the text field and the
internal value stored in Windchill. In addition, you can customize how the
authorized participants are determined for each security label value on either a
custom or standard security label, and how the participants that are allowed to
modify each security label value are determined.
The use of these customizations allows you to link your Windchill system to
another system that may contain user data to determine if a participant is cleared
for a security label value. For example, your company may collaborate with other
companies using a separate non-disclosure agreement (NDA) for each company
interaction. After a user agrees to the NDA, the user is automatically added to a
corresponding Windchill group that represents participants in that NDA. Since
some of the interactions are between multiple companies, a user needs to be a
member of every NDA group involved to have full access to all Windchill data in
the collaborative product.
To set up this scenario to work well with security labels, a custom security label
can be implemented that allows values that can represent multiple NDA groups
rather than the configured list of values offered with standard security labels. You
can also use a custom evaluator to determine if a participant is a member of every
group required to access an object. For example, a collaborative product has been
set up between your company and two others: Company A and Company B. A
user must be a member of both the NDA group for Company A and the NDA
group for Company B to be able to access an object in the collaborative product.
The object in the product has a custom security label applied called Third Party
Proprietary with the value of CompanyA,CompanyB. Custom security label

1432 Customization Guide


values are entered as text strings in a text box provided in the user interface by
users who are able to modify the security label value. Custom security labels can
also be set using object initialization rules.

Note
The security label could have been defined as a standard label with pre-
defined values CompanyA, CompanyB, and CompanyA-CompanyB. However
if your company works with many companies and the list of companies
changes, it may not be practical to pre-define all of the companies and
combinations of NDAs that could apply to a particular object.

The authorized participants for the Third Party Proprietary custom security label
are determined using a custom evaluator class. When a user tries to access an
object with the Third Party Proprietary label applied, the custom evaluator class
searches to find out if the user is a member of the appropriate groups associated
with the security label value applied and then returns either a true or false value to
specify if the user is cleared for the security label and can subsequently access the
object.
The custom evaluator class can also be used to determine which participants are
able to modify the security label values applied to an object. There may be a case
where a user is not familiar with the contract between your company and
Company A, so you do not want that user to modify the Third Party Proprietary
security label settings on an object. You may want to prevent users from changing
the security label value of an object based on the life cycle state of the object. For
example, you could create a custom evaluator that restricts value modification for
objects in the Released state. Using the custom evaluator class on either a custom
or standard security label, you can specify which participants are able to modify a
particular security label’s values.
The following customizations can change how security labels work:
• Including a custom security label in the
securityLabelsConfiguration.xml file.
• Converting between the external and internal custom security label values
using a custom translator class.
• Specifying the participants authorized for the security label value and those
who can modify the security label value using a custom evaluator class.

Note
The custom evaluator class can be used for both standard and custom
security labels.

Customizing Security Labels 1433


Best Practice
When implementing custom evaluator and translator classes, performance may
be impacted as methods in the custom classes will be called frequently by
Windchill. If you are setting up a call to an outside system, for example, you
may consider caching the returned values to improve performance on
subsequent method calls.

Information about security labels is available from the Windchill Installation and
Configuration Guide or from the following topics in the Windchill Help Center:
• Specialized Administration ▶ Ensuring Data Security ▶ Security Labels and
Agreements ▶ Security Labels
• Installation and Upgrade ▶ Windchill Installation and Configuration ▶
Configuring Security Labels

1434 Customization Guide


Setting Up Custom Security Labels
The following sections should be used in conjunction with the Security Labels
Configuration Steps, found in the Windchill Installation and Configuration Guide
or the Windchill Help Center. One or all of these customization can be completed.

Best Practice
If you are using custom security labels, PTC recommends adding validation to
the user interface if users are able to enter values manually, such as by using
the text field provided by default when custom security labels are configured.
A custom translator class is recommended to validate the values to prevent
unexpected values from being stored in the database, either if the user enters
an invalid value in the user interface or if an invalid value is specified in an
import file.

Enabling Custom Security Labels


To enable custom security labels, you must complete the following steps. See the
Security Labels Configuration Steps, found in the Windchill Installation and
Configuration Guide or the Windchill Help Center, for more information about
each of these steps.
1. Define Security Labels - Required
Add the following lines to the <Windchill>/wtcustom/wt/access/
accessModelRB.rbinfo file, making sure not to include any spaces
except in the <DISPLAY_NAME> or the <LONG_DESCRIPTION>:
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>.value=<DISPLAY_NAME>
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>.dataType=java.lang.String
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>.serverFunction=
com.ptc.core.foundation.security.server.impl.SACFSecurityLabel
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>.serverFunction.arg1=
PID{<SECURITY_LABEL>}
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>.longDescription=
<LONG_DESCRIPTION>

where:
• <SECURITY_LABEL> is the custom security label name. This value
should use only alphanumeric characters and the underscore character. The
string
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_
LABEL> is the value that will be specified for the

Customizing Security Labels 1435


SecurityLabelResourceKey element for the custom security label
later in this configuration. While there is no requirement for the
<SECURITY_LABEL> value to match the name attribute specified for
the CustomSecurityLabel element in the security labels
configuration file, that is the convention used in this guide.

Note
A security label name is stored as a server-calculated attribute (SCA).
Each SCA must have a unique name. The Logical Attributes Report
provides a list of all current SCAs. You can access this report from
<Windchill>/netmarkets/jsp/lwcType/
logicalAttributesReport.jsp.

• <DISPLAY_NAME> is the name of the custom security label as it will


display in the user interface.
• <LONG_DESCRIPTION> is the long description of the custom security
label. The long description is displayed in the automatically generated
description for the custom security label, accessed by clicking the view
security label information icon from the Security Labels table.

Tip
Because custom security label values are not pre-defined, there is no
long description available to display on the information page for the
custom security label. Any information about the custom security label
values can be included in the long description for the custom security
label.

For example, add the following lines to the end of the file for configuring the
example custom security label:
WCTYPE|wt.access.SecurityLabeled~SCA|THIRD_PARTY_PROPRIETARY.value=
Third Party Proprietary
WCTYPE|wt.access.SecurityLabeled~SCA|THIRD_PARTY_PROPRIETARY.dataType=
java.lang.String
WCTYPE|wt.access.SecurityLabeled~SCA|THIRD_PARTY_PROPRIETARY.serverFunction=
com.ptc.core.foundation.security.server.impl.SACFSecurityLabel
WCTYPE|wt.access.SecurityLabeled~SCA|
THIRD_PARTY_PROPRIETARY.serverFunction.arg1=
PID{THIRD_PARTY_PROPRIETARY}
WCTYPE|wt.access.SecurityLabeled~SCA|THIRD_PARTY_PROPRIETARY.longDescription=
The "Third Party Proprietary" label indicates the business object's
level of third party corporate sensitivity.

1436 Customization Guide


Note
Do not delete or alter the existing lines that begin with:
• WCTYPE|wt.access.SecurityLabeled~SCA|ALL_SECURITY_LABELS
• WCTYPE|wt.access.SecurityLabeled~SCA|ALL_STANDARD_
SECURITY_LABELS
• WCTYPE|wt.access.SecurityLabeled~SCA|ALL_CUSTOM_SECURITY_
LABELS

2. Create a Custom Java Evaluator Class - Optional


For more information about this step, see Create a Custom Java Evaluator
Class on page 1438.
3. Create a Custom Java Translator Class - Optional
For more information about this step, see Create a Custom Java Translator
Class on page 1442.
4. Edit the Security Labels Configuration File - Required
For more information about this step, see Edit the Security Labels
Configuration File for Custom Security Labels on page 1443.
5. Edit LogicalAttributesSite.xml - Required
For more information about this step, see the Step 7. Edit
LogicalAttributesSite.xml - Required section in the Windchill
Installation and Configuration Guide.
6. Specify Attribute Handler for Label Attribute - Required
From within a windchill shell, run the following command for each custom
security label:
xconfmanager -s wt.services/svc/default/com.ptc.core.command.
server.delegate.io.AbstractAttributeHandler/
<CUSTOM_SECURITY_LABEL>/wt.access.SecurityLabeled/
0=com.ptc.core.command.server.delegate.io.
SecurityLabelAttributeHandler/
singleton -t codebase/com/ptc/core/foundation/
FoundationAttributeHandler.properties -p

where <CUSTOM_SECURITY_LABEL> is the custom security label name as


specified in the securityLabelsConfiguration.xml file.
For example, the following command would be run for the example custom
security label:

Customizing Security Labels 1437


xconfmanager -s wt.services/svc/default/
com.ptc.core.command.
server.delegate.io.AbstractAttributeHandler/THIRD_
PARTY_PROPRIETARY /wt.access.SecurityLabeled/0=
com.ptc.core.command.server.delegate
.io.SecurityLabelAttributeHandler/singleton -t
codebase/com/ ptc/core/foundation/
FoundationAttributeHandler.properties -p
7. Restart Windchill method servers.

Note
Additional configuration is required to enable object initialization rules,
agreements, auditing, and subscriptions for custom security labels, but the
steps are the same for standard and custom security labels.
For information about enabling these additional capabilities, see the Security
Labels Configuration Steps in the Windchill Installation and Configuration
Guide or the Windchill Help Center.

Create a Custom Java Evaluator Class

Note
If custom evaluation is needed when determining if a participant is restricted
by a security label value, or when determining if a participant is able to
modify a security label value, then a custom Java evaluator class is required.

A custom Java evaluator class can be used to determine if a participant is


restricted by the security label value specified and to determine if the participant is
able to modify the security label value. To do this, the class must extend the
wt.access.UnrestrictedPrincipalEvaluator class.
The wt.access.UnrestrictedPrincipalEvaluator class contains
four methods. Any of these methods can be overridden, depending on whether the
default behavior is sufficient:
• boolean isRestrictedBySecurityLabelValue(WTPrincipal
principal, String label_name, String label_value) -
Determines if a participant is restricted by the security label value by
evaluating the participant, the security label, and the security label value.

1438 Customization Guide


If this method is not overridden, its default behavior evaluates the UFID
provided in the security labels configuration file to determine if the participant
is the user specified by the UFID or a member of the group or organization
specified by the UFID. To get the default answer in your overridden method,
include a call to
super.isRestrictedBySecurityLabelValue(principal,
label_name, label_value) in your class.
• boolean isRestrictedBySecurityLabelValue(WTPrincipal
principal, SecurityLabeled object, String label_name,
String label_value) - Determines if a participant is restricted by the
security label value by evaluating the participant, the object, the security label,
and the security label value. The object could be an
AccessControlSurrogate. The AccessControlSurrogate acts as
a stand-in for a persistable object, and contains all the attributes Windchill
needs to determine access rights without having the full persistable object. For
more information about an AccessControlSurrogate, seeHandling an
AccessControlSurrogate on page 1440.
If this method is not overridden, its default behavior is to call the boolean
isRestrictedBySecurityLabelValue(WTPrincipal
principal, String label_name, String label_value) method.
• boolean
isAllowedToModifySecurityLabelValue(WTPrincipal
principal, SecurityLabeled object, String label_name,
String label_value) - Determines if a participant is allowed to modify
the security label value by evaluating the participant, the security label, the
security label value, and the object.
If this method is not overridden, its default behavior evaluates the UFID
provided in the security labels configuration file to determine if the participant
is the user specified by the UFID or a member of the group or organization
specified by the UFID. To get the default answer in your overridden method,
include a call to
super.isAllowedToModifySecurityLabelValue(principal,
object, label_name, label_value) in your class.
• WTKeyedHashMap
isAllowedToModifySecurityLabelValues(WTPrincipal
principal, WTKeyedMap objects_to_security_labels_map)
- Determines if a participant is allowed to modify specified security label /
value pairs on a collection of objects. A separate Boolean result is returned for
each specified combination of label, value, and object.

Customizing Security Labels 1439


If this method is not overridden, its default behavior is to call the single-value
evaluator, isAllowedToModifySecurityLabelValue, for each of the
label/value pairs, for each of the objects. This may cause performance issues
if, for example, the evaluation requires separately querying an external system
for each evaluation. The custom evaluator may therefore override this method
with a more efficient implementation- for example, combining calls to the
external system, or caching results to avoid repetitive evaluations.
An example custom Java evaluator class can be found in the <Windchill>/
prog_examples/access directory. For more information about the use case
and setting up Windchill to use the example, refer to the Javadoc for the custom
Java evaluator class for each of the implemented methods.
For more information about working with class files, see Managing
Customizations.

Handling an AccessControlSurrogate
When Windchill access control service methods are called to evaluate a user's
access rights to information, the methods may be given a persistable object or a
wt.access.AccessControlSurrogate. The
AccessControlSurrogate acts as a stand-in for a persistable object, to
evaluate access rights for the information returned when a database query is
performed requesting specific attributes of an object rather than a full persistable.
The surrogate contains attributes from the class it is representing and includes all
possible attributes necessary for making the access control decision.
The boolean isRestrictedBySecurityLabelValue(WTPrincipal
principal, SecurityLabeled object, String label_name,
String label_value) method defined by the
wt.access.UnrestrictedPrincipalEvaluator class could be given
an AccessControlSurrogate object. If you override this method in a
custom Java evaluator class, your custom code should check if the object is an
instance of AccessControlSurrogate before trying to check various
attributes.
The wt.fc.ObjectIdentifier method getId() can be used to get the
unique identifier of the represented persistable object. The class name in the
ObjectIdentifier is wt.access.AccessControlSurrogate. The
surrogate has a getTargetClassName method which can be used to get the
class name of the represented persistable object. For example:
Class targetClass = Object.class;
if (object instanceof AccessControlSurrogate) {
try {
targetClass = Class.forName(((AccessControlSurrogate)
object).getTargetClassName());
}
catch (ClassNotFoundException cnfe) {
...

1440 Customization Guide


}
long id = PersistenceHelper.getObjectIdentifier(object).getId();
}
The attributes that are available on the AccessControlSurrogate depend
on the type of the represented persistable object and whether Agreements are
enabled on your system.
The following attributes are available and have supported APIs to access them.:
• If the wt.admin.DomainAdministered interface is a superinterface of
the target class, the wt.admin.DomainAdministeredHelper method
getAdminDomainRef(DomainAdministered obj) can be used to
get the object's domain reference.
• If the wt.lifecycle.LifeCycleManaged interface is a superinterface
of the target class, its getState() method can be used to get the object's
life cycle state.
• If the wt.access.SecurityLabeled interface is a superinterface of the
target class, the wt.access.AccessControlManager method
getSecurityLabels(SecurityLabeled object) can be used to
get a map of the object's security labels and their values.
If Agreements are enabled on your system in addition to the
SecurityLabeled interface being a superinterface of the target class:
• If the wt.inf.container.WTContained interface is a superinterface of
the target class, the wt.inf.container.WTContainerHelper method
getContainer(WTContained contained) can be used to get the
context of the object
• If the wt.vc.Iterated interface is a superinterface of the target class, its
getMasterReference() method can be used to get the
ObjectReference of the iteration's master. Also, the
wt.vc.VersionControlHelper method
getBranchIdentifier(Iterated iteration) can be used to get
the iteration's branch id
• If the wt.vc.wip.Workable interface is a superinterface of the target
class, the wt.vc.wip.WorkInProgressHelper method getState
(Workable object) can be used to get the work-in-progress state of the object
and its APIs such as isCheckedOut(Workable object),
isReservedWorkingCopy(Workable object) and
isPrivateWorkingCopy(Workable object) can be used to evaluate
the state

Customizing Security Labels 1441


Create a Custom Java Translator Class
For custom security labels a custom Java translator class can be used to convert
the internal form of the security label value into the external form of the security
label value or back again. To do this, the class must extend the
wt.access.CustomSecurityLabelValueTranslator class. The
internal form is used by Windchill during access evaluations and is stored in the
database. The external form is what is displayed in the Windchill interface and
what users will enter when specifying a security label value. If no translator class
is defined, the external form is the same as the internal form and is what is stored
in the database.
There are certain restrictions on what can be included in the internal form. The
equals (=) and comma (,) characters cannot be stored in the database. If your user-
entered security label values will use either of these characters, you must use a
translator class to remove them from the internal name. Similarly, the string NULL
cannot be stored in the database. Using a custom Java translator class also allows
you to have longer security label value names. The security label attribute is
limited to 4000 characters in the database, so having lengthy security label values
can cause a storage issue. By specifying a custom translator class, you can have
descriptive label values in the Windchill user interface using an external form and
less user-friendly values stored in the database using an internal form. A custom
translator class can also be used to validate custom security label values,
particularly in cases where there is no user interface to validate the user-specified
label values.
The wt.access.CustomSecurityLabelValueTranslator class
contains two methods:
• getExternalValue - Returns the external value associated with a given
internal value.
• getInternalValue - Returns the internal value associated with a given
external value.
The following simple example removes the restricted comma character (,) and
replaces it with an unrestricted plus character (+). This example assumes that the
external value never contains a plus character (+).
public class CustomTranslator implements CustomSecurityLabelValueTranslator {
public String getExternalValue(String label_name, String internal_value)
throws WTException {
return internal_value.replace("+", ",");
}
public String getInternalValue(String label_name, String external_value)
throws WTException {
return external_value.replace(",", "+");
}
}

1442 Customization Guide


Each method must always return the same answer when given the same input. If
you anticipate the internal value changing over time, consider putting a version
number in the string. For example, if a custom security label represents third party
companies with whom you work, you may need to add the countries in which
each third party has offices at some point in the future. Initially, one external value
could be “Company A”, with the internal value of “1:A”. In the future, when
office locations of Company A need to be represented, the external value could
change to “Company A (US)” and “Company A (UK)”. The corresponding
internal values could change to “2:A-US” and “2:A-UK”. The version number can
be used to let the custom translator class know how to translate each version
individually since the database might have both versions stored.
For more information about working with class files, see Managing
Customizations.

Edit the Security Labels Configuration File for Custom Security Labels
This information relates to the Edit the Security Labels Configuration File -
Required step of the Security Labels Configuration Steps, found in the Windchill
Installation and Configuration Guide or the Windchill Help Center.

Note
An example illustrating the use of a custom security label can be found in the
<Windchill>/conf/securityLabelsConfiguration_
sample.xml file. While the sample configuration file includes sample data
similar to the example configuration used in this document, actual values from
your system are required to successfully configure custom security labels.
A description of the sample configuration is available in the Security Labels
Example Configuration section, found in the Windchill Installation and
Configuration Guide or the Windchill Help Center.

To enable custom security labels, add a CustomSecurityLabel element and


its subelements for each custom security label. When you are finished, save and
close the file.

CustomSecurityLabel element
The CustomSecurityLabel element contains the data for defining a custom
security label, the authorized participant for the custom security label values (if
not all users), the agreement type (if any) associated with the custom security label
values, and various mappings used by applications and services to process custom
security labels. There should be one CustomSecurityLabel element for each
custom security label you configure. For example:
<CustomSecurityLabel name="THIRD_PARTY_PROPRIETARY" enabled="true">

Customizing Security Labels 1443


<SecurityLabelResourceKey>WCTYPE|wt.access.SecurityLabeled~SCA|
THIRD_PARTY_PROPRIETARY</SecurityLabelResourceKey>
<CustomSecurityLabelValues>
<UnrestrictedPrincipal>
<ufid>cn=Employees,cn=Public,ou=people,cn=AdministrativeLdap,
cn=Windchill_10.1,o=ptc|Ldap.ptcnet.ptc.com|
Ldap.ptcnet.ptc.com</ufid>
<evaluatorClass>
com.ourcompany.CustomEvaluator
</evaluatorClass>
</UnrestrictedPrincipal>
<TranslatorClass>
com.ourcompany.CustomTranslator
</TranslatorClass>
</CustomSecurityLabelValues>
<SecurityLabelParameter>THIRD_PARTY_PROPRIETARY
</SecurityLabelParameter>
</CustomSecurityLabel>
The name attribute of the CustomSecurityLabel element is the string that is
stored in the database for this security label, in this case, THIRD_PARTY_
PROPRIETARY. For this custom security label to be available in your Windchill
solution, the enabled attribute must be set to true. This name value does not
generally show in the user interface; the display name for this security label was
defined in the <Windchill>/wtcustom/wt/access/
accessModelRB.rbinfo file previously.

Best Practice
Keep the name attribute of the CustomSecurityLabel element and the
internal custom label values as short as possible. You can use the
TranslatorClass element to reduce the size of the internal values stored
in the database. For more information, see Create a Custom Java Translator
Class on page 1442.

The SecurityLabelResourceKey element represents the resource key for


the label, and is specified in the following format:
WCTYPE|wt.access.SecurityLabeled~SCA|<SECURITY_LABEL>

where <SECURITY_LABEL> is the value of the name attribute on the


CustomSecurityLabel element. This resource key must be present in the
accessModelRB.rbinfo resource file edited previously.

1444 Customization Guide


Note
Even if security labels are globally disabled, the security label resource keys
specified in the configuration file must exist in the
accessModelRB.rbinfo for the method server to start.
For more information on disabling security labels, see Disabling Security
Labels and Values in the Windchill Help Center or the Windchill Specialized
Administration Guide.

The CustomSecurityLabelValues element can have a single


UnrestrictedPrincipal subelement, which specifies the authorized
participant for the security label values. If the UnrestrictedPrincipal
subelement is omitted, all users are cleared for access to objects with the custom
label values.
The UnrestrictedPrincipal element can have a ufid subelement. The
UFID, or Unique Federation Identifier, specifies a participant, which can be a
user, user-defined group, or organization. The UnrestrictedPrincipal
element can also have an evaluatorClass subelement, which specifies the
evaluator class created in Create a Custom Java Evaluator Class on page 1438.
The ufid subelement and the evaluatorClass subelement can either be used
together or individually under the UnrestrictedPrincipal element. For
more information about the differences between using a ufid subelement, an
evaluatorClass subelement, or both, see Specifying Authorized Participants
for Custom Security Labels on page 1447.
The UnrestrictedPrincipal element can optionally have an
AgreementType subelement. An agreement can be used to grant temporary
clearance to users who are not authorized participants for the security label values.
The content for the AgreementType element is specified in the following
format:
<logicalTypeId><AGREEMENT_NAME></logicalTypeId>
where <AGREEMENT_NAME> is the internal name of the agreement type or
subtype.
The optional TranslatorClass element specifies the class created in Create a
Custom Java Translator Class on page 1442. The TranslatorClass element
converts the internal name of the security label values into the external names,
which appear throughout Windchill, and back again. If the TranslatorClass
element is not specified, the internal and external values for the custom security
label values are the same.

Customizing Security Labels 1445


The optional SecurityLabelParameter element contains the parameter
name used by various authoring applications as a file attribute to map to this
custom security label. SecurityLabelParameter is always the last element
within the CustomSecurityLabel element. The parameter name must follow
any restrictions for parameter names that exist for the authoring applications.

1446 Customization Guide


Specifying Authorized Participants for Custom
Security Labels
A custom security label can have multiple label values. For custom security labels,
authorized participants can be configured for all non-null security label values, not
for individual security label values. For both standard and custom security labels,
there are multiple ways to specify the authorized participants:
• Unspecified
If neither a UFID nor an EvaluatorClass is specified, the label value does
not limit access to the objects with the label value applied and it becomes an
informative marking.
• UFID Only
If an authorized participant is specified using a UFID, whether the participant
(user, user-defined group, or organization) is cleared for access to the objects
with the label value applied is indicated by the UFID value.
• EvaluatorClass Only
If an evaluator class is specified, its boolean
isRestrictedBySecurityLabelValue (WTPrincipal
principal, SecurityLabeled object, String label_name,
String label_value) method is called when the access rights of a
participant are evaluated to determine whether the participant is cleared for
access to objects with the label value applied.
• Both UFID and EvaluatorClass
If both a UFID and an evaluator class are specified, the UFID is only used if
the super.isRestrictedBySecurityLabelValue(principal,
label_name, label_value) method is called and the result is used (i.e.,
the isRestrictedBySecurityLabelValue methods are not
overridden in the evaluator class or an overridden method calls
super.isRestrictedBySecurityLabelValue and makes use of the
result).

Note
Although authorized participants cannot be configured for individual custom
security label values, the users that are authorized for each value can still be
different when an evaluator class is configured. The evaluator class can return
a different answer for each value applied to the object.

Customizing Security Labels 1447


Using a UFID to Specify the Authorized Participants
When using only a UFID for the authorized participant, specifying a user-defined
group to identify the authorized participants provides the most flexibility, as
membership in the group can be modified as needed using the Participant
Administration utility, the Organizations ▶ Groups page, or a third party LDAP
tool to manage groups within an LDAP directory service. If a group is used as the
authorized participant for a custom security label, the membership of the group
can include other groups. Users who are not authorized participants for any value
of the custom security label are denied access to objects with that label value
applied, unless they are specifically granted temporary clearance to the value by
being in the authorized participants set for an agreement. Being authorized for one
security label does not automatically authorize a user for any other security label.
Users must be cleared for all security labels that are set on an object to be able to
access the object.
For example, a site might have a system outside of Windchill that tracks whether a
user has completed ITAR training. The ITAR Clearance security label value on the
Export Control standard security label value is configured with a custom
evaluator. The custom evaluator queries the external system to determine if the
user has completed the training. The evaluator method returns false for a user who
has completed the training (when Yes is returned by the external system) and the
user is cleared for the security label value.

Using a Custom Evaluator to Specify the Authorized


Participants
When using a custom evaluator class to determine if a user is an authorized
participant for a custom security label or standard security label value, the boolean
isRestrictedBySecurityLabelValue (WTPrincipal principal,
SecurityLabeled object, String label_name, String label_
value) method is called. Windchilluses the boolean answer to determine if a
user is an authorized participant for the security label value applied to the object.
For example, a site might have a system outside of Windchill that tracks whether a
user has completed ITAR training. The ITAR Clearance security label value on the
Export Control standard security label value is configured with a custom
evaluator. The custom evaluator queries the external system to determine if the
user has completed the training. The evaluator method returns false for a user who
has completed the training (when Yes is returned by the external system) and the
user is cleared for the security label value.

1448 Customization Guide


Using a Custom Evaluator and UFID to Specify the
Authorized Participants
When using a custom evaluator class to determine if a user is an authorized
participant for a security label value, the boolean
isRestrictedBySecurityLabelValue(WTPrincipal principal,
SecurityLabeled object, String label_name, String label_
value) method is called, but this method can call the
super.isRestrictedBySecurityLabelValue(principal,
label_name, label_value) method to also incorporate the UFID specified
in the security labels configuration file. If the
super.isRestrictedBySecurityLabelValue method is called, then it
is up to the evaluator to use the answer from
super.isRestrictedBySecurityLabelValue in whatever way is
desired.
For example, a site may have a system outside of Windchill that tracks whether a
user has completed ITAR training. The ITAR Clearance-US security label value
on the Export Control standard security label is configured with a custom
evaluator. The custom evaluator queries the external system to determine if the
user has completed the training. If the user has completed the training, the external
system returns a value of Yes to the custom evaluator method. Then, the
super.isRestrictedBySecurityLabelValue method is called and the
user is evaluated to determine if they are a member of the US Persons group. If
that is true, the user is cleared for the security label value and the method returns
false. If the user has not completed the training, the external system returns a
value of No to the custom evaluator method and the
super.isRestrictedBySecurityLabelValue method is not called, the
method returns true and the user is not cleared for the security label.

Customizing Security Labels 1449


1450 Customization Guide
Additional Considerations for Custom Security
Labels
The following sections contain information that is helpful when you have
implemented custom security labels.

Custom Security Labels and Watermarks


When a custom security label is selected from one of the property groups and
included in a watermark, the external value displays.

Removing Custom Security Label Values


Although custom security label values are not defined in the security labels
configuration file, you might want to discontinue use of a value. To remove uses
of a custom security label value, change all uses of that label value to the null
(blank) value for the security label, or to a label value that will remain in use.

Customizing Security Labels 1451


34
Customizing Windchill
Visualization Services
Custom Publishing ................................................................................................ 1454
Customizing Publishing Queues ............................................................................. 1473
Interference Detection ........................................................................................... 1479
Modifying the Default Behavior of Dynamic Part Generation ..................................... 1487

This chapter describes how to customize Windchill Visualization Services.

1453
Custom Publishing
Objective
You want to initiate publishing from another product area or from custom code.
You may also want to define alternative inputs to the creation of a representation
such as naming, descriptions, or configuration specifications to an OOTB
publishing mechanism (i.e. check-in driven and scheduled publishing).

Background
Out-of-the-box Windchill Visualization Services can create representations three
ways. They are by manual creation from the Windchill UI, the check-in of a
Representable (an object that can have Representations; i.e. EPMDocument,
WTPart, WTDocument), and by a schedule job. This document will help explain
how to initiate publishing in other ways such as custom code for workflows, from
a custom UI, etc.
This topic also explains how to customize the creation of representations from
such existing mechanisms like the check-in of a Representable or by a schedule
job. Unlike manual creation, there is no out-of-the-box way to specify special
configuration specifications for publishing, or provide business specific
information you may want to capture in the name or description of the
Representation.

Scope/Applicability/Assumptions
Custom publishing should be used when there is a requirement to initiate
publishing in Windchill from a non-standard way (something other than check-in,
manual or schedule), or if you need to modify the input information for a
Representation. Publishing can only be performed on
wt.representation.Representable objects (i.e. EPMDocuments,
WTPart, WTDocuments; including soft and hard typed children).

Intended Outcome
Using the information in this topic will allow end users to perform publishing in a
manner in-line with their business requirement whenever the out-of-the-box
publishing mechanisms are not sufficient.

Solution
Customize publishing by implementing public WVS APIs in custom code and
making WVS aware of this custom code via appropriate WVS property changes.

1454 Customization Guide


Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Java Development
• Standard WVS publishing setup and configuration
• WVS concepts such as Representable and Representation
• Basic understanding of publishable business objects such as EPMDocuments,
WTParts and WTDocuments and their relationships/structure
• The use of configuration specifications (ConfigSpecs)

Note
The use of configuration specifications (ConfigSpecs) Additional Resources
on page 1471 includes references to many or all of these subjects.

Solution Elements
Element Type Description
Publisher.class Class file Contains api for doPublish needed for invoking
publishing from code.
Runtime Location: <Windchill>\codebase\com\ptc
\wvs\common\ui
PublisherAction. Class file Used to create the optional actionString to be
class passed to the doPublish method in Publisher. See
JavaDoc for details.
Runtime Location: <Windchill>\codebase\com\ptc
\wvs\common\ui
Visualization Class file Contains helper api’s such as findRepresentable
Helper.class and getRepresentation often needed in custom
code.
Runtime Location: <Windchill>\ codebase\com\ptc
\wvs\common\ui
ScheduleJobs Class file Contains getCurrentContainer method needed
.class when writing custom schedule jobs.
Runtime Location: <Windchill>\codebase\com\ptc
\wvs\server\schedule
wvs.properties Proper- Contains specific properties used with the
ties file Windchill Visualization Service.
Runtime Location: <Windchill>\codebase

Customizing Windchill Visualization Services 1455


Procedure – Invoking Publishing from Custom Code/
Workflow
This section details how to use the following supported APIs and classes:
• doPublish from Publisher class – see Simple Publish on page 1456
• PublisherAction class for advanced use of doPublish – see Advanced Publish
on page 1458
To invoke publishing from custom code or from an Expression Robot in a
Workflow the key method to understand and use is the supported doPublish
method in the com.ptc.wvs.common.ui.Publisher class.
public boolean doPublish (boolean viewableLink,
boolean forceRepublish,
String objectReference,
ConfigSpec configSpec,
ConfigSpec partConfigSpec,
boolean defaultRep,
String repName,
String repDescription,
int structureType,
String actionString,
int jobSource)

For more details on this method and it’s parameters, see the JavaDoc in
<Windchill>\codebase\wt\clients\library\api\index.html.

Simple Publish
You have an EPMDocument instance with publishable data and you want to create
a default Representation.
String objRef =
ObjectReference.newObjectReference(myepmdoc).toString();
Publisher pub = new Publisher();
boolean result = pub.doPublish(false, true, objRef,
(ConfigSpec)null,
(ConfigSpec)null, true, null, null,
Publisher.EPM, null, 0);

This simple example will simply add a publish job to the publishing queue for
myepmdoc. The resulting default representation named “default” will be published
using the As-Stored or Latest ConfigSpec as defined in wvs.properties (publish.
configspec.default.useasstoredifavailable). Since the forceRepublish parameter
was true, an existing representation with the same name would be replaced.

1456 Customization Guide


If you wanted to programmatically provide a name for the representation, or insert
useful business information into the description modify the parameters. For
example:
Publisher pub = new Publisher();
boolean result = pub.doPublish(false, true, objRef,
(ConfigSpec)null,
(ConfigSpec)null, true, “MyRep”,
(ConfigSpec)null, true, “MyRep”,
“My Description”, Publisher.EPM, null,
0);

The only difference between this and the previous example is that the resulting
default representation will have the name “MyRep” and have the description “My
Description”.
If you wish to retrieve a reference to an existing Representation, set the
viewableLink parameter to true and the forceRepublish parameter to false. If there
is an existing Representation with the repName you provided associated to the
Representable, you can call getViewableObjRef() following a call to doPublish.
This will provide a String object reference if the Representation was found.
Otherwise null will be returned.
String repObjRef = null;
Publisher pub = new Publisher();
if (pub.doPublish(true, false, objRef, (ConfigSpec)null,
(ConfigSpec)null,
true, “MyRep”, “My Description”, Publisher.EPM,
null, 0)) {
repObjRef = pub.getViewableObjRef();
}

In addition to getting the object reference of an existing Representation, you can


also get an HTML fragment to use for launching Creo View to view the
representation by using the getViewableLink() api following a call to doPublish.
Again, viewableLink must be true, forceRepublish must be false, and a
Representation with the name passed in for repName must exist on the
Representable supplied by the objRef parameter.
String repLink = null;
Publisher pub = new Publisher();
if (pub.doPublish(true, false, objRef, (ConfigSpec)null,
(ConfigSpec)null,
true, “MyRep”, “My Description”, Publisher.EPM,
null, 0)) {
repLink = pub.getViewableLink();
}

Customizing Windchill Visualization Services 1457


Advanced Publish
You have an EPMDocument instance with publishable data and you want to create
a default Representation with your own configuration specification and have the
publish job processed on the high priority publishing queue.
The more advanced features of publishing require using the use of the
PublisherAction class. See the JavaDoc for full details; a couple examples are
shown below.
String objRef =
ObjectReference.newObjectReference(myepmdoc).toString();
PublisherAction pa = new
PublisherAction(PublisherAction.QUEUEPRIORITY, “H”);
ConfigSpec configSpec = <MyHelper.getBaselineConfigSpec()>;
Publisher pub = new Publisher();
boolean result = pub.doPublish(true, true, objRef, configSpec,
null, true,
null, null, Publisher.EPM,
pa.toString(), 0);

You have a WTDocument with several pieces of content. For example, doc1.doc,
doc2.doc and doc3.doc are all content of your WTDocument and you only wish to
publish doc3.doc (by default all docs would be published).
String objRef = ObjectReference.newObjectRefer-
ence(mydoc).toString();
PublisherAction pa =
new PublisherAction(PublisherAction.DOCUMENTFILE, “doc3.doc”);
Publisher pub = new Publisher();
boolean result = pub.doPublish(true, true, objRef, (Config-
Spec)null,
(ConfigSpec)null, null, null,
Publisher.NONE, pa.toString(), 0);

Note
For WTDocuments, a ConfigSpec is not used and the structureType is
Publisher.NONE.

This sort of processing could be useful if you established a business practice of


naming certain content files in a particular way if you wanted them to be
published.

1458 Customization Guide


Procedure – Getting Representables and Representations
This section details how to use the following supported APIs and classes:
• findReprentable from VisualizationHelper class – see findRepresentable on
page 1459
• getRepresentation and getRepresentations from VisualizationHelper class –
see getRepresentation on page 1459
The association of Representables to Representations is one to many. The key
concept when finding these relationships is to understand that when you have an
EPMDocument (i.e. Representable) its Representations aren’t necessarily directly
associated. In the case where an EPMDocument has an actively associated
WTPart (i.e. option of creating associated parts in the workgroup manager was
used when checking-in the EPMDocument), the Representations are linked to the
WTPart. In all other cases the Representations are directly associated with the
Representable (i.e. non-actively associated EPMDocuments, DynamicDocuments,
WTParts, WTDocuments and MPMLink Representables).

findRepresentable
To simplify the concept discussed above, there is a method called
findRepresentable on page 1459 in com.ptc.wvs.common.ui.VisualizationHelper.
This method allows you to pass in a Representable and always get back the right
Representable in the case where actively associated parts are involved. In the case
where there are no actively associated parts, it simply returns the object you
passed in. The method signature is shown below:public Representable
findRepresentable(Persistable d)
public Representable findRepresentable(Persistable d)

If you have custom code that is dealing with Representables, it is a good practice
to use this method so you can be sure to have the right Representable that is
associated to the Representations. Also, note that if you pass in a Persistable that
is not a Representable, the method will return null. You must have an instance of
VisualizationHelper to use this method. For example:
VisualizationHelper vizHelper = new VisualizationHelper();
Representable repable = vizHelper.findRepresentable(d);

getRepresentation
In the com.ptc.wvs.common.ui.VisualizationHelper there are also some
convenience methods for getting Representations from a Representable.
public Representation getRepresentation(Persistable d)

Customizing Windchill Visualization Services 1459


As noted previously, the relationship of Representables to Representations is one
to many. However, one of the Representations may be noted as the “default”
Representation. There will be 0 or 1 defaults. The above method will return the
default Representation if one exists. Otherwise, null will be returned.public
Representation getRepresentation(Persistable d, String repName)
public Representation getRepresentation (Persistable d,
String repName)

The method above will return the Representation associated to the Persistable with
the name passed in to the repName argument. If there are no Representations or
one can’t be found with the supplied name, null will be returned.
public QueryResult getRepresentations(Persistable d)

This method will return all of the Representations associated to the Persistable
passed in. If there are no Representations, null will be returned.
All three methods in this subsection require that you have an instance of
VisualizationHelper:
VisualizationHelper vizHelper = new VisualizationHelper();
Representation rep = vizHelper.getRepresentation(d);

Note
All three of the above methods make use of the findRepresentable method, so
you do not need to worry about actively associated parts when calling it.
Additionally, if the Persistable passed in is not a Representable, null will be
returned.

Procedure – Creating Custom Schedule Jobs


This section details how to use the following supported APIs and classes:
• Creating a custom schedule job step-by-step and using supported api
getCurrentContainer from ScheduleJobs class – see Custom Schedule Job
Fundamentals on page 1461
• Incorporating the use of doPublish from the Publisher class in your custom
schedule job – see An Advanced Technique for Custom Schedule Jobs on page
1463

1460 Customization Guide


Custom Schedule Job Fundamentals
In addition to the out-of-the-box Schedule Jobs, you can also create your own
custom jobs. To do this, start by creating or adding to a custom class in the
Windchill codebase; for example ext.wvs.CustomJobs. In this class create a
method with the following signature:
public static WTList <nameOfMethod>() or public static QuerySpec
<nameOfMethod>() or public static QueryResult <nameOfMethod>()

You can use whatever method name you want, but it is important that the method
be public, static, return a WTList and accept no arguments.
Then add the following to your wvs.properties.xconf file (edit as needed):
<Property default="MyCustomJob" name="myJob.description"/>
<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>
<Property default="myCustomJob" name=" myJob.method"/>
<Property default="true" name=" myJob.enableOnContainers"/>
<Property default="myJob" name="schedulejobs<N>"/>

• Line 1 (<Property default="MyCustomJob" name="myJob.description"/>) is


what you see in the Scheduler UI to identify your custom job.
• Line 2 (<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>) is
the fully qualified class where your custom method resides.
• Line 3 (<Property default="myCustomJob" name=" myJob.method"/>) is the
name of your custom method.
• Line 4 (<Property default="true" name=" myJob.enableOnContainers"/>)
defines whether or not the job code will have access to the container that the
schedule job was initiated from. For example, the out-of-the-box schedule jobs
only handle objects found in the container the schedule job was initiated from
(i.e. Project, Product, Library, or Organization) because this value is set to
true. If the value is set to false it would be the same as executing the job from
the context of the Exchange container, no matter what container the schedule
job was initiated from.
• Line 5 (<Property default="myJob" name="schedulejobs<N>”/>) is to display
your custom job in the Publish Scheduler Administrator. In the name string
you must replace the <N> with the integer that follows that last schedulejobsN
that is already defined.
Below is an example of a publish job:
public static WTlist myCustomJob() {
WTList wtl = new WTArrayList();
try {
QuerySpec qs = new QuerySpec(WTDocument.class);
WTContainerRef cr = ScheduleJobs.getCurrentContainer();
if (cr != null) {

Customizing Windchill Visualization Services 1461


ContainerSpec cs = new ContainerSpec();
cs.addSearchContainer(cr);
qs.setAdvancedQueryEnabled(true);
qs.appendWhere(
WTContainerHelper.getWhereContainerIn(cs, ,new Class[]
{WTDocument.class}),
new int[]{0});
}
if (cr != null) qs.appendAnd();
qs.appendWhere(new SearchCondition(WTDocument.class,
Iterated.LATEST_ITERATION,
SearchCondition.IS_TRUE),
new int[]{0});

Representable doc = null;


int offset = 0;
BasicPageableQuerySpec bpqs = new BasicPageableQuerySpec();
bpqs.setPrimaryStatement(qs);
bpqs.setOffset(offset);
bpqs.setRange(1000);
PagingQueryResult qr =
(PagingQueryResult)PersistenceHelper.manager.find(bpqs);
long sessionId = qr.getSessionId();
int total = qr.getTotalSize();

while (true) {
while (qr.hasMoreElements()) {
doc = (Representable)((Object[])qr.nextElement())[0];
wtl.add(doc);
}

offset += qr.size();
if (offset >= total) break;

PageableQuerySpec pqs = new PagingSessionSpec(sessionId);


pqs.setOffset(offset);
pqs.setRange(1000);
qr = (PagingQueryResult)PersistenceHelper.manager.find(pqs);
}
if (sessionId > 0) PagingSessionHelper.closePagingSession(sessionId);
} catch(Exception e) {e.printStackTrace(); wtl = new WTArrayList ();}

return wtl;
}

1462 Customization Guide


Note
This example contains the use of a BasicPageableQuerySpec and
PagingSessions to avoid out of memory errors. See JavaDoc in the wt.query
and wt.fc packages for details.

This example would effectively ask for all latest iterations of any WTDocuments
found in the current container to be published.
In line six of the example the following method is used from
com.ptc.wvs.server.schedule.ScheduleJobs:
public static WTContainerRef getCurrentContainer()

The result of this method will be null if the schedule job was initiated from the
Exchange container (Site) or if the enableOnContainers value is false in the job
definition (see line four of properties shown prior to the example above). If the
value of enableOnContainers is true, then a WTContainerRef of the container the
schedule job was initiated from will be returned. In the example code, this is used
to filter the scope of the query to the Organization or the Product/Project/Library
container the schedule job was initiated from.

Note
You can have multiple custom schedule jobs. Just use another method name in
the same class, or use a new class altogether. For example:

public static WTList anotherCustomJob();


Then add the following to your wvs.properties.xconf file (edit as needed):
<Property default="AnotherCustomJob"
name="anotherJob.description"/>
<Property default="ext.wvs.CustomJobs" name=" anotherJob.class"/>
<Property default="anotherCustomJob" name=" anotherJob.method"/>
<Property default="true" name=" anotherJob.enableOnContainers"/>
<Property default="anotherJob" name="schedulejobs<N>"/>

An Advanced Technique for Custom Schedule Jobs


Using the technique in the Custom Schedule Job Fundamentals on page 1461 does
not allow you to provide input to creating the Publish Job and specify the name of
the Representation, description of the Representation, etc. Combining the concepts
in theProcedure – Invoking Publishing from Custom Code/Workflow on page
1456 with the Custom Schedule Job Fundamentals on page 1461 can open up a lot
of flexibility for schedule jobs.

Customizing Windchill Visualization Services 1463


The technique simply requires you to insert the use of the doPublish method from
the Publisher class into your myCustomJob method. Since myCustomJob must
return a QueryResult, simply return an empty QueryResult as the doPublish
method will now cause Publish Jobs to be queued up for execution.
public static WTList myCustomJob() {
WTList wt = new WTArrayList();

try {
QuerySpec qs = new QuerySpec(WTDocument.class);
WTContainerRef cr = ScheduleJobs.getCurrentContainer();
if (cr != null) {
ContainerSpec cs = new ContainerSpec();
cs.addSearchContainer(cr);
qs.setAdvancedQueryEnabled(true);
qs.appendWhere(
WTContainerHelper.getWhereContainerIn(cs, WTDocument.class),
new int[]{0});
}
if (cr != null) qs.appendAnd();
qs.appendWhere(new SearchCondition(WTDocument.class,
Iterated.LATEST_ITERATION,
SearchCondition.IS_TRUE),
new int[]{0});

Representable doc = null;


String objRef;
int offset = 0;
BasicPageableQuerySpec bpqs = new BasicPageableQuerySpec();
bpqs.setPrimaryStatement(qs);
bpqs.setOffset(offset);
bpqs.setRange(1000);
PagingQueryResult qr =
(PagingQueryResult)PersistenceHelper.manager.find(bpqs);
long sessionId = qr.getSessionId();
int total = qr.getTotalSize();

while (true) {
while (qr.hasMoreElements()) {
doc = (Representable)((Object[])qr.nextElement())[0];
objRef =
ObjectReference.newObjectReference(doc).toString();
Publisher pub = new Publisher();
pub.doPublish(false, true, objRef, (ConfigSpec)null,
(ConfigSpec)null, true, "My Rep",
"My Description", Publisher.NONE, null, 0);
}

1464 Customization Guide


offset += qr.size();
if (offset >= total) break;

PageableQuerySpec pqs = new PagingSessionSpec(sessionId);


pqs.setOffset(offset);
pqs.setRange(1000);
qr =
(PagingQueryResult)PersistenceHelper.manager.find(pqs);
}
if (sessionId > 0)
PagingSessionHelper.closePagingSession(sessionId);
} catch(Exception e) {e.printStackTrace();}

return new wtl;


}

This is the same example used in Custom Schedule Job Fundamentals on page
1461, but notice the use of the doPublish method shown in bold. This custom job
will now create Representations with the name “My Rep” and a description of
“My Description”. Also, note that the returned WTList from the method is empty.
Refer to Procedure – Invoking Publishing from Custom Code/Workflow on page
1456 for see other useful ways to use the doPublish method.

Procedure – Customizing Check-in Based Publishing


This section details how to use the following property-driven custom hooks:
• publish.service.filterepmdocumentpublishmethod – see Filter Publishing for
EPMDocument Check-in on page 1465
• publish.service.filterdocumentpublishmethod – see Filter Publishing for
WTDocument Check-in or Upload on page 1466
• Incorporating the use of doPublish from the Publisher class in your custom
hook code – see An Advanced Technique for General Publishing on page 1470

Filter Publishing for EPMDocument Check-in


Once publishing is configured for an Authoring Application (i.e. Creo Parametric)
publishing will occur out-out-of-the box for all EPMDocuments of that Authoring
Application that are checked-in. Sometimes there are business reasons for filtering
out some EPMDocuments from publishing based on some criteria. For example a
certain lifecycle state, EPMDocumentType, EPMDocSubType, etc. Windchill
Visualization Services has a code hook available where you can plug in code to
filter on such criteria.
In a custom class you can define a method with the following signature:
public static Boolean epmFilterMethod(EPMDocument epmdoc)

Customizing Windchill Visualization Services 1465


You can use whatever name you want in place of epmFilterMethod. Make sure the
class that contains your custom method is accessible in the Windchill codebase (i.
e. ext.wvs.MyFilterMethods).
The next step is to add the class and method to wvs.properties.xconf. The
following property is empty out-of-the-box. Update it to include your class and
filter method in the format “class/method”.
<Property default="ext.wvs.MyFilterMethods/epmFilterMethod"
name="publish.service.filterepmdocumentpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to
wvs.properties.
Every time a check-in occurs where publishing of an EPMDocument would
normally occur, this method will now be invoked. If the method returns Boolean.
TRUE publishing will be attempted for the specific EPMDocument. If the method
returns Boolean.FALSE, publishing will not be attempted.
The following is a simple example of how to filter out a specific
EPMDocumentType:
public static Boolean epmFilterMethod(EPMDocument epmdoc) {
if (epmdoc.getDocType().equals(

EPMDocumentType.toEPMDocumentType("MANIKIN_POSTURE"))) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}

This is another example where you can filter out the publishing of
EPMDocuments that are in the LifeCycle state of InWork.
public static Boolean epmFilterMethod(EPMDocument epmdoc) {
if (epmdoc.getLifeCycleState() != State.INWORK) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}

Filter Publishing for WTDocument Check-in or Upload


Very similar to filtering publishing for EPMDocuments, there is a means for
filtering for WTDocument publishing as well. For example, you may want to filter
based on specific filenames, lifecycle state, container, etc. If the system has a
worker configured for publishing specific WTDocument content, a custom filter
method can be used to keep certain content from being published.
In a custom class you can define a method with the following signature:
public static Boolean docFilterMethod(WTDocument doc, ContentItem ci)

1466 Customization Guide


You can use whatever name you want in place of docFilterMethod. Make sure the
class that contains your custom method is accessible in the Windchill codebase (i.
e. ext.wvs.MyFilterMethods). Notice that this method differs from the
EPMDocument filter method signature by including ContentItem as a parameter.
This method is called for each ContentItem associated to the WTDocument on
check-in. It is also called for uploads. For example if you had a WTDocument
with .doc file as primary content and a .xls file as secondary content, this method
would be called twice; once with each content item (pending a worker was
associated to both types of content).
The next step is to add the class and method to wvs.properties.xconf. The
following property is empty out-of-the-box. Update it to include your class and
filter method in the format “class/method”.
<Property default="ext.wvs.MyFilterMethods/docFilterMethod"
name="publish.service.filterdocumentpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to
wvs.properties.
Every time a check-in or upload occurs where publishing of WTDocument
content would normally occur, this method will now be invoked. If the method
returns Boolean.TRUE publishing will be attempted for the specific WTDocument
ContentItem. If the method returns Boolean.FALSE, publishing will not be
attempted.
The following example shows how to filter if the WTDocument’s description is
“Do Not Publish”, or if the filename of the content starts with “donotpublish”.
public static Boolean docFilterMethod(WTDocument doc, ContentItem ci) {

if (doc.getDescription().equals("Do Not Publish")) {


return Boolean.FALSE;
}
if (ci instanceof ApplicationData) {
String filename = ((ApplicationData)ci).getFileName();
if (filename.startsWith("donotpublish") {
return Boolean.FALSE;
}
}
return Boolean.TRUE;
}

An Advanced Technique for Custom Check-in Based Publishing


Using the techniques in Filter Publishing for EPMDocument Check-in on page
1465 and Filter Publishing for WTDocument Check-in or Upload on page 1466 do
not allow you to provide input for creating Publish Jobs to specify the name of the
Representation, description of the Representation, etc. Combining the concepts in
Procedure – Invoking Publishing from Custom Code/Workflow on page 1456 with

Customizing Windchill Visualization Services 1467


the concepts in Filter Publishing for EPMDocument Check-in on page 1465 and
Filter Publishing for WTDocument Check-in or Upload on page 1466 can open up
a lot of flexibility for check-in based publishing.
The technique simply requires you to insert the use of the doPublish method from
the Publisher class into the epmFilterMethod or the docFilterMethod shown in the
previous subsections. Since the two filter methods must return a Boolean, simply
return Boolean.FALSE and use the doPublish method to cause Publish Jobs to be
queued up for execution.
public static Boolean epmFilterMethod(EPMDocument epmdoc) {

if (epmdoc.getDocType().equals(
EPMDocumentType.toEPMDocumentType("MANIKIN_POSTURE"))) {
return Boolean.FALSE;
}
String objRef = ObjectReference.newObjectReference(epmdoc).toString();
Publisher pub = new Publisher();
pub.doPublish(false, true, objRef, (ConfigSpec)null,
(ConfigSpec)null,
"My Rep", "My Description", Publisher.EPM, null, 0);
return Boolean.FALSE;
}

This is the same example used in Filter Publishing for EPMDocument Check-in
on page 1465 , but notice the use of the doPublish method shown in bold. This
custom job will now create Representations with the name “My Rep” and a
description of “My Description”. Also, note that the returned Boolean from the
method is Boolean.FALSE.
Refer back to Procedure – Invoking Publishing from Custom Code/Workflow on
page 1456 for see other useful ways to use the doPublish method.

Procedure – Customizing General Publishing


This section details how to:
• Use the property-driven hook: publish.service.filterpublishmethod – see
Filtering All Publishing on page 1468
• Incorporate the use of doPublish from the Publisher class in your custom hook
– see An Advanced Technique for General Publishing on page 1470

Filtering All Publishing


In addition to the filters specifically for EPMDocuments and WTDocuments
described in Procedure – Customizing Check-in Based Publishing on page 1465,
Windchill Visualization Services has a more general hook that is called for

1468 Customization Guide


anything that can be published (including EPM and WTDocuments). In addition
to supporting the filtering of all Representables, this hook also includes publishing
of pre-converted data.
In a custom class you can define a method with the following signature:
public static Boolean filterMethod(Persistable p, Boolean
publishFromDB)

You can use whatever name you want in place of filterMethod. Make sure the
class that contains your custom method is accessible in the Windchill codebase (i.
e. ext.wvs.MyFilterMethods). This method includes a publishFromDB parameter.
This Boolean will come in as Boolean.TRUE if the publish is being invoked for
data stored in Windchill, i.e. content of an EPMDocument or WTDocument
object. The value will come in as Boolean.FALSE if the publish is for data not
stored in Windchill, i.e. local data converted from the file system or data from the
clipboard. You can use the value of publishFromDB to have your custom code
handle the two cases specifically if you wish.
The next step is to add the class and method to wvs.properties.xconf. The
following property is empty out-of-the-box. Update it to include your class and
filter method in the format “class/method”.
<Property default="ext.wvs.MyFilterMethods/filterMethod"
name="publish.service.filterpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to
wvs.properties.
Every time publishing would normally occur, this method will now be invoked. If
the method returns Boolean.TRUE publishing will be attempted for the
Persistable. If the method returns Boolean.FALSE, publishing will not be
attempted.
The following is a simple example of how to filter out publishing of the content if
the Persistable is LifeCycleManaged and in its final phase of its LifeCyle:
public static Boolean filterMethod(Persistable p, Boolean publishFromDB) {
if (!publishFromDB) return Boolean.TRUE;
if (!(p instanceof LifeCycleManaged)) return Boolean.TRUE;
try {
if (LifeCycleHelper.service.isInFinalPhase((LifeCycleManaged)p)) {
return Boolean.FALSE;
}
} catch (WTException wte) {
wte.printStackTrace();
}
return Boolean.TRUE;
}

Customizing Windchill Visualization Services 1469


Note
In the above example the second line states that if the data requested for
publishing is not from the Windchill DB, then just return true. For example if
someone is publishing data on a WTPart that was uploaded from their local
disk, we are saying we don't wish to filter this out and to simply return
Boolean.TRUE.

An Advanced Technique for General Publishing


Combining the concepts in Procedure – Invoking Publishing from Custom Code/
Workflow on page 1456 with Filtering All Publishing on page 1468 you can open
up additional flexibility for general publishing. The technique simply requires you
to insert the use of the doPublish method from the Publisher class into the
filterMethod shown in the previous subsection. Since the filter method must return
a Boolean, simply return Boolean.FALSE and use the doPublish method to cause
Publish Jobs to be queued up for execution.
For example you want to provide specific naming information for publishes that
were not made from Windchill stored data.
public static Boolean filterMethod(Persistable p, Boolean publishFromDB) {
if (publishFromDB) return Boolean.TRUE;
try {
String objRef = ObjectReference.newObjectReference(p).toString();
Publisher pub = new Publisher();
pub.doPublish(false, true, objRef, (ConfigSpec)null,
(ConfigSpec)null, true, “Not From Windchill Data”,
“”, Publisher.NONE, null, 0);
} catch (WTException wte) {
wte.printStackTrace();
}
return Boolean.FALSE;
}

Note
In the example above that the second line states that if we have publishing
requested for data from Windchill stored data, just return Boolean.TRUE. For
example if the request was to publish the primary content of a WTDocument
we just want to return Boolean.TRUE.

1470 Customization Guide


Limitations

Customization Boundaries
PTC does not support the customizations of the out-of-the-box CadConvert
classes (a.k.a. Publishers), the Worker Agent, or the WVS Loader. These
components of WVS were not intended for customization and there is no
guarantee that future releases would not break customizations attempted with
these components.

Custom Schedule Job Performance


Though schedule jobs are run in the background using queues, it is possible to
create very resource intensive queries to return in your custom code. The
examples in theProcedure – Creating Custom Schedule Jobs on page 1460 section
showed one technique of using paging to help avoid problems caused by dealing
with large result sets. Be sure your custom schedule jobs are tested on production-
like datasets. What works for cases where the result is 100 does not always work
as well when you have 10’s or 100’s of thousands of results.

Custom Check-in Filtering Performance


Keep in mind with using the check-in filter techniques shown in Procedure –
Customizing Check-in Based Publishing on page 1465 that your method will be
ran for every Representable that is a candidate for publishing. You method should
be efficient and try to do as little as possible to determine cases where the true or
false result can be returned. If some intense logic needs to occur in the filter
method, do all you can to rule out the need before executing it.

Additional Resources
• Java Development: http://java.sun.com
• The "Visualization Services" chapter in the Windchill Business Administrator's
Guide
• wvs.properties.xconf file in your <Windchill>\codebase directory.

Related Package/Class Javadoc


• com.ptc.wvs.common.ui
• com.ptc.wvs.server.schedule

Customizing Windchill Visualization Services 1471


Other Related Windchill Documentation
• Windchill Business Administrator's Guide
• Creo® View MCAD Adapters 2.0 Installation and Configuration Guide
• Creo® View ECAD Adapters 2.0 Installation and Configuration Guide

1472 Customization Guide


Customizing Publishing Queues
This section contains information and sample code for the filter classes used for
publish.publishqueue.priorities.filtermethod and
wvs.property
publish.publishqueue.usesetworkers.filtermethod.

publish.publishqueue.priorities.filtermethod
This method is called when a publish job is being submitted and allows the
priority, queue set and representation name and description to be set.
• [0] = priority H, M L
• [1] = queue set name which should have been configured by
publish.publishqueue.setnames.
• [2] = new name for representation
• [3] = new description for representation
Any of the return strings can be null, in which case the existing value is
unchanged. Controlled by the property
publish.publishqueue.priorities.filtermethod=
com.ptc.wvs.server.publish.PTCWVSPublishFilters/
publishqueueFiltermethod.

publish.publishqueue.usesetworkers.filtermethod
This method will be called when a conversion job is being submitted to the
CADAgent. The representation name and description to be set to return the
worker queue set, and the CADAgent it should use (if this job will be able to use a
worker that has the queueset property that includes the return value). This does
not have to be the same as the actual publishing queue set that is being used. For
example, you could have dedicated worker for assemblies and parts from the same
set.
Controlled by the property
publish.publishqueue.usesetworkers.filtermethod=
com.ptc.wvs.server.publish.MyPublishFilters/
publishUsesetworkersFiltermethod.

Use Case
If there are no workers configured as dedicated workers, the system will pick any
workers which are currently free and job will get published via that worker. The
worker is not a dedicated worker, because no
usesetworkers.filtermethod has been configured.
If you have only dedicated workers and if usesetworkers.filtermethod
has not been defined, the result will be the error: “Error, did not find available
worker of type PROE”.

Customizing Windchill Visualization Services 1473


If you want to send jobs via dedicated workers then you must write a
UsesetworkersFiltermethod method. After that has been defined, the job
will submit to the dedicated workers.
To do this:
1. xconfmanager -s
publish.publishqueue.priorities.filtermethod=
com.ptc.wvs.server.publish.PTCWVSPublishFilters/
publishqueueFiltermethod -t codebase/WEB-INF/conf/
wvs.properties -p
2. To compile the java file, run the following command in a windchill shell
a. set CLASSPATH = %CLASSPATH%; %WT_HOME%\srclib\tool\
Annotations.jar
b. cd codebase\com\ptc\wvs\server\publish
c. javac PTCWVSPublishFilters.java
3. Restart Windchill.

Sample Code
package com.ptc.wvs.server.publish;

import wt.epm.EPMDocument;
import wt.fc.Persistable;
import wt.fc.QueryResult;
import wt.representation.Representation;

import java.io.File;
import java.util.Properties;

/**
* Example methods for the Dedicated Publisher Queue Set and Worker
* enhancement
*/
public class PTCWVSPublishFilters
{

/**
* publish.publishqueue.priorities.filtermethod
*
* This method is called when a publish job is being submitted and
* allows the priority, queue set and
* representation name and descrition to be set
* return [0] = priority H, M L
* [1] = queue set name which should have been confgured by
* "publish.publishqueue.setnames"
* [2] = new name for representation
* [3] = new description for representation
* Any of the return strings can be null, in which case the

1474 Customization Guide


* existing value is unchanged.
* Controlled by property
* publish.publishqueue.priorities.filtermethod=
* com.ptc.wvs.server.publish.
* PTCWVSPublishFilters/publishqueueFiltermethod
*
**/
public static String[] publishqueueFiltermethod(Persistable p,
Integer requestType, Integer requestSource,
String requestQueuePriority, String requestQueueSet,
String repName, String repDesc)
{
String[] ret = {null, null, null, null};

if( p instanceof EPMDocument ) {


EPMDocument epmdoc = (EPMDocument)p;

if( epmdoc.getAuthoringApplication().toString().toUpperCase().equals("PROE") )
{
if(epmdoc.getDocType().toString().equals("CADDRAWING")){
ret[0]="L";
}
if(epmdoc.getDocType().toString().equals("CADCOMPONENT")){
ret[0]="M";
}
if(epmdoc.getDocType().toString().equals("CADASSEMBLY")){
ret[0]="H";
}
if (epmdoc.getDocType().toString().equals("CADDRAWING")) {

ret[1]="PROEDRW";
}
if (epmdoc.getDocType().toString().equals("CADCOMPONENT")) {

ret[1]="PROEPRT";
}
if (epmdoc.getDocType().toString().equals("CADASSEMBLY")) {

ret[1]="PROEASM";
}
ret[2]="SITHIK_PROE_REP";
ret[3]="SITHIK_PROE_DESC";
}

System.out.println("publishqueueFiltermethod outputs:");
System.out.println(" Queue Set: " + ret[1]);
System.out.println(" Priority: " + ret
[0]);
System.out.println(" RepName: " + ret[2]);
System.out.println(" RepDesc: " + ret[3]);

Customizing Windchill Visualization Services 1475


}
return ret;
}

/**
* publish.publishqueue.usesetworkers.filtermethod
*
* This method will be called when a conversion job is being
* submitted to the CADAgent representation name and description
* to be set return the worker queue set the the
* CADAGent should use, ie this job will be able to use a
* worker that has the "queueset" property that includes the
* return value. There is not reason that this has to be the
* same as the actual publsihing queue set that is being used,
* for example you could have dedicated worker for assemblies
* and parts from the same set.
* Controlled by property
* publish.publishqueue.usesetworkers.filtermethod=
* com.ptc.wvs.server.publish.MyPublishFilters/
* publishUsesetworkersFiltermethod
*
**/
public static String publishUsesetworkersFiltermethod(Persistable p,
String workerType,
String cadType, String fileName,
String requestQueuePriority,
String requestQueueSet)
{
System.out.println("publishqueueUsesetworkersFiltermethod : " + p + " " +
workerType + " " + cadType +
" " + fileName + " " + requestQueuePriority + " " + requestQueueSet);

String ret = "DEFAULT";


if( p instanceof EPMDocument ) {
EPMDocument epmdoc = (EPMDocument)p;

System.out.println( "Input docType: " + epmdoc.getDocType().


toString() );
System.out.println( "Input AuthApp: " + epmdoc.
getAuthoringApplication().toString().toUpperCase() );

if( epmdoc.getAuthoringApplication().toString().toUpperCase().
equals("PROE") )
{
if (epmdoc.getDocType().toString().equals("CADDRAWING")) {
ret="PROEDRW";
}
if (epmdoc.getDocType().toString().equals("CADCOMPONENT")) {

ret="PROEPRT";

1476 Customization Guide


}
if (epmdoc.getDocType().toString().equals("CADASSEMBLY")) {

ret="PROEASM";
}
}
}

System.out.println("WorkerSet: " + ret);

return ret;
}

public static void main(String args[])


{
System.out.println("hook " + args[0]);
System.out.println("EXITSTATUS:1");
}
}

Sample Properties File


<Property name="publish.publishqueue.usesetworkers.forqueueset.PROEDRW"
overridable="true" targetfile="codebase/WEB-INF/conf/wvs.properties""
value="PROE"/>

<Property name="wt.queue.removeCompleted.PublisherQueuePROEDRW1"
overridable="true" targetFile="codebase/wt.properties" value="false"/>

<Property name="wt.queue.removeCompleted.PublisherQueuePROEDRW2"
overridable="true" targetFile="codebase/wt.properties" value="false"/>
<AddToProperty name="publish.publishqueue.setnames" value="PROEDRW"/>

<Property name="publish.publishqueue.usesetworkers.forqueueset.PROEASM"
overridable="true" targetfile="codebase/WEB-INF/conf/wvs.properties""
value="PROE"/>

<Property name="wt.queue.removeCompleted.PublisherQueuePROEASM1"
overridable="true" targetFile="codebase/wt.properties" value="false"/>

<Property name="wt.queue.removeCompleted.PublisherQueuePROEASM2"
overridable="true" targetFile="codebase/wt.properties" value="false"/>

<AddToProperty name="publish.publishqueue.setnames" value="PROEASM"/>

<Property name="publish.publishqueue.usesetworkers.forqueueset.PROEPRT"
overridable="true" targetfile="codebase/WEB-INF/conf/wvs.properties""
value="PROE"/>

<Property name="wt.queue.removeCompleted.PublisherQueuePROEPRT1"
overridable="true" targetFile="codebase/wt.properties" value="false"/>

Customizing Windchill Visualization Services 1477


<Property name="wt.queue.removeCompleted.PublisherQueuePROEPRT2"
overridable="true" targetFile="codebase/wt.properties" value="false"/>

<AddToProperty name="publish.publishqueue.setnames" value="PROEPRT"/>

<Property name="publish.publishqueue.priorities.filtermethod"
overridable="true"
targetfile="codebase/WEB-INF/conf/wvs.properties""
value="com.ptc.wvs.server.publish.PTCWVSPublishFilters/
publishqueueFiltermethod"/>

<Property name="publish.publishqueue.usesetworkers.filtermethod"
overridable="true"
targetfile="codebase/WEB-INF/conf/wvs.properties""
value="com.ptc.wvs.server.publish.
PTCWVSPublishFilters/publishUsesetworkersFiltermethod"/>

<Property name="wt.queue.max.processQueues"
overridable="true"
targetFile="codebase/wt.properties" value="60"/>

Compiling Java File


Based on where you deploy the java file.
1. set CLASSPATH = %CLASSPATH%; %WT_HOME%\srclib\tool\
Annotations.jar
2. cd codebase\com\ptc\wvs\server\publish
3. javac PTCWVSPublishFilters.java

1478 Customization Guide


Interference Detection
You want the Description, Assignee, State, User Severity, and Name for new and
existing Interferences in an Interference Report to be set to specific values when
Windchill Visualization Services (WVS) is processing Interference Detection
results generated by the Creo View Client Adapter. You also want to change the
out-of-the-box behavior as to how WVS determines equivalency between
Interferences contained in multiple reports.

Background
When an Interference Definition has been submitted for Interference Detection,
the Interference results are returned to WVS to be processed. Based on these
results, WVS will create a new Interference Report and associate new or existing
Interference objects to that report. Each Interference object has Description,
Assignee, State, User Severity, and Name attributes with corresponding out-of-
the-box values of “blank”, “unassigned”, “Open”, “0” and a unique object
identifier. For the State attribute, the default value of “Open” is determined by the
out-of-box lifecycle template and maybe different depending on the lifecycle
template in use. This document will describe how to customize WVS to
automatically set the Description, Assignee and State based on customer business
needs.
Additionally, the first time an Interference Definition is submitted for Interference
Detection, only new Interference objects are created. All subsequent submissions
of the same Interference Definition will result in a new Interference report that
may have existing Interference objects from previous reports. The WVS
Interference processor has the ability to identify if existing Interference objects
already exist and link them to the new Interference report rather than creating new
ones. The processor conforms to a set of rules for determining if an Interference
described in the results returned from the Creo View Client Adapter matches an
Interference object already associated to the current definition. This document
explains how to customize these set of rules for determining equivalency between
Interferences.

Scope/Applicability/Assumptions
Custom Interference Detection should be used if the default values for
Description, Assignee, State, User Severity, and Name for new or existing
Interference objects are not adequate. Also should be used if the out-of-the-box
rules for determining Interference equivalency doesn’t meet requirements.

Intended Outcome
Using this best practice will allow end users to perform Interference Detection in a
manner that addresses their business requirement whenever the out-of-the-box
Interference mechanisms are not sufficient.

Customizing Windchill Visualization Services 1479


Solution
Customize Interference Detection by implementing public WVS API’s in custom
code and making WVS aware of this custom code via appropriate WVS property
changes.

Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following:
• Java Development
• WVS Interference Detection concepts such as Interference Definition and
Interference Report.
The Additional Resources section below includes references to many or all of
these subjects.

Solution Elements
Element Type Description
InterferenceDetection- Java file Contains example code
Hooks.java for implementing the
customizations that this
document describes.
Runtime Location:
Windchill/prog_
examples/wvs/com/
ptc/wvs/
InterferenceDetec
tionHooks.java
InterferenceInfo.class Class file Represents all
information regarding a
single Interference
contained in an
Interference Report
generated by the Creo
View Client Adapter.
Used by the WVS
Inteference processor for
creating new Interference
objects or updating
existing ones.
Runtime Location:
<Windchill>/
codebase/com/ptc/
wvs/server/

1480 Customization Guide


Element Type Description
publish/
InterferenceInfo.
class
WTDocument.class Class file An Interference
Definition is a Subtype of
WTDocument.
Runtime Location:
<Windchill>/
codebase/wt/doc/
WTDocument.class
wvs.properties.xconf XConf file Contains specific
properties to configure
the Windchill
Visualization Service to
utilize specific
customization code.
Runtime Location:
<Windchill>/
codebase/WEB-INF/
conf/
wvs.properties.x
conf
LifeCycleManagedWt- Class file All Interference and
MarkUp Interference Report
objects in Windchill are
LifeCycleManagedWt-
MarkUps.
Runtime Location:
<Windchill>/
codebase/ wt/
viewmarkup/
LifeCycleManaged
WtMarkUp.class

Procedure : Invoke Customization for Determining Interference


Attributes
Complete the following steps to create a custom hook for setting Interference
attributes such as Assignee, Description, State, User Severity, and Name.
1. Create a Java class with a static method in which the arguments and return
type matches the method defined in the following example. This

Customizing Windchill Visualization Services 1481


customization will return a set of attribute values that will be used to update an
existing Interference object and will return a different set of attribute values
for new Interference objects that will be created.
For a comprehensive example, see
InterferenceDetectionHooks.java located in <Windchill>/
prog_examples/wvs/com/ptc/wvs.
2. Update <Windchill>/codebase/wvs.properties.xconf to
configure the WVS Interference processor to call the customization hook. For
more information on how to accomplish this step, review the documentation
for the property
“interferencedetection.report.getinterferenceattribu
tevaluesmethod” in wvs.properties.xconf. For configuring this
example, the XConf entry will be:
<Property name="interferencedetection.report.
getinterferenceattributevaluesmethod " default
="ext.customhooks.MyCustomClass/getInterferenceAttributeValues"/>

Procedure : Invoke Customization to Change the Default Set of Rules


for Determining Interference Equivalency.
The WVS Interference processor needs to determine if an Interference described
in an Interference Report generated by a Creo View Client Adapter is equal to any
Interference objects already associated to the Interference Definition that exists in
an Interference Report created in a prior execution. The default set of rules used
for determining if an existing Interference object is equal to an Interference
described in an Interference Report are:
• The Master References of the two parts that are interfering must be equal.
• The Component Instance Paths of the two parts that are interfering must be
equal.
• The type of Interference must be the same.
Complete the following steps to create a custom hook for overriding the default
rules for determining Interference equivalency.
1. Create a Java class with a static method in which the arguments and return
type matches the method defined in the following example. This
customization will use all the default rules for determining equivalency first
by calling a WVS API. If the API returns “true”, then make an additional
check to be sure that the Interference item’s group names are also equivalent.
For a comprehensive examples, see

1482 Customization Guide


InterferenceDetectionHooks.java located in <Windchill>/
prog_examples/wvs/com/ptc/wvs.
2. Update <Windchill>/codebase/wvs.properties.xconf to
configure the WVS Interference processor to call the customization hook.
For more information on how to accomplish this step, review the
documentation for the property
“interferencedetection.report.getinterferenceattribu
tevaluesmethod” in the wvs.properties.xconf.
For configuring this example, the XConf entry will be: <Property name=
"interferencedetection.report.isinterferenceequiva
lentmethod " default="ext.customhooks.MyCustomClass/
isInterferenceEquivalent"/>

Customization Points
Custom Method: getInterferenceAttributeValues
Parameter Description
Collection<InterferenceInfo> The WVS Interference processor will
pass in a Collection of all Interference
Information extracted from an
Interference Report generated by the
Creo View Client Adapter.
WTDocument A reference to the Interference
Definition in which the new
Interference Report and Interference
objects will be associated to.

Customizing Windchill Visualization Services 1483


Return Description
Map<InterferenceInfo, Object[]> Must return a Map in which the key
will be the original InterferenceInfo
instance passed in and the value will be
an Object array of attribute values in
which the newly created Interference
object or the existing Interference
object will be initialized or set to.
index 0 – WTPrincipalReference to
assign the Interference to. If set to null,
then the Interference object will be set
to “unassigned”. If set to a different
type other than WTPrincipalReference (
e.g Object), then the assignee will be
unchanged.
index 1 – String to set the description
to. If set to null, then the Interference
object will be set with an empty
description. If set to a different type
other than String, then the description
will be unchanged.
index 2 – String to set the State to. All
states have a String representation. For
example, the assigned state string value
is “wt.lifecycle.State.ASSIGNED” in
the out-of-the-box lifecycle template. If
returning “ASSIGNED”, the assigned
state will be set on the Interference
object. If set to null or different object
type, then the state will be unchanged.
index 3 = String to set the userSeverity
to. If "null", non whole number (1.1),
not between -2,147,483,648 to
2,147,483,647, or set to a non String (i.
e Object), then the userSeverity will be
unchanged.
index 4 = String to set the name to. If
"null", a "" or an all whitespace string,
then the name will be unchanged. If set
to a non String (i.e Object), then the
name will also be unchanged. Name
has a Hard limit of characters based on
database column size and will truncate

1484 Customization Guide


Return Description
anything beyond that. (default is 60
characters) Best practice is to handle
proper sizing of the name in the hook.
If the value for a InterferenceInfo
instance is set to null, then the newly
created Interference or existing
Interference will not have any attributes
set or changed. If this method returns
null, then none of the existing
Interferences or newly created
Interferences will have the attributes set
or changed.

Custom Method: isInterferenceEquivalent


Parameter Description
InterferenceInfo The WVS Interference processor will
pass in a single InterferenceInfo
instance with all information extracted
from an Interference Report generated
by the Creo View Client Adapter.
LifeCycleManagedWtMarkUp This parameter is an existing
Interference object that is associated to
a different Interference Report
Return Description
boolean Will return true only if the two
parameters are considered equal. The
WVS Interference processor uses the
result to determine when to create new
Interference object verses associating
an existing Interference object to a new
Interference Report.

Limitations
The customization for setting Interference attribute values only supports Assignee,
Description,State, User Severity, and Name attributes.

Customizing Windchill Visualization Services 1485


Sample Code
For comprehensive examples, see InterferenceDetectionHooks.java
located in <Windchill>/prog_examples/wvs/com/ptc/wvs.

Additional Resouces
• The “Windchill Visualization Services Chapter in the Windchill Specialized
Administration Guide.
• wvs.properties.xconf file in your <Windchill>\codebase\
WEB-INF\conf directory.
• InterferenceDetectionHooks.java located in <Windchill>\
prog_examples\wvs\com\ptc\wvs

1486 Customization Guide


Modifying the Default Behavior of
Dynamic Part Generation
Before a part structure can be viewed in Creo View, the representations associated
to the parts selected by the navigation criteria must be merged into a single PVS
file. The representations used to dynamically generate the PVS structure are the
default representations of parts. If a part is associated to a CAD structure whose
children do not have an associated WTParts with representations, the geometry
for the part will not be viewable in Creo View.
Starting in Windchill 10.2 M010, it is now possible to change the default behavior
of dynamic part structure generation by using a custom filter. The filter can be
used to exclude parts, use representations other than the default representation
associated to the part or to include the entire representation for an assembly
instead of merging the representations associated to its children.

Creating a Custom Part Structure Filter


To modify the default behavior of the dynamic part filter, you must create a
custom class that includes an API with the following signature: public static
WTKeyedMap myFilterMethod(WTKeyedHashMap
filterPartStructureParentMap, WTValuedMap
representations)
Where:
• filterPartStructureParentMap is a map of parts to it's
WTPartUsage links
• representations is a map of parts to their default representations
• The return map is a WTKeyedMap of parts to the filter action to use for the
part
The possible filter actions are:
• RepStructureFilterAction. NORMAL: Normal processing. Do not do exclude
or include the representation.
• RepStructureFilterAction. EXCLUDE: Filter out this representation.
• RepStructureFilterAction. INCLUDE_REP_AND_EXCLUDE_CHILDREN:
Stop structure traversal but include the assembly representation.
• RepStructureFilterAction. EXCLUDE_REP_AND_EXCLUDE_CHILDREN:
Stop structure traversal and exclude the assembly representation.
To use a different representation than the default, the filter should replace the
existing representation in the _representations map with the representation
that should be used when viewing the part.

Customizing Windchill Visualization Services 1487


For examples of how to use the filter actions, see the example below or look at the
examples in <WT_HOME>\prog_examples\com\ptc\wvs\
PartStructureFilter.java.

Configuration Details
Customers must configure the class name and method to use for the filter by
setting the “edrload.partstructurefiltermethod” wvs.property.
The property must be set to a Class/Method. For example, if your class is located
in “ext.custom.partstructure” and the name of the class is
“PartStructureFilter” and the name of the method is
“filterPartStructure”, the following entry should be added to
site.xconf.
• <Property name="edrload.partstructurefiltermethod"
overridable="true" targetFile="codebase/
wvs.properties" value=" ext.custom.partstructure.
PartStructureFilter/filterPartStructure "/>
The modifications will not appear in the Windchill Visualization tab unless the
following property is set to “true”.
• <Property default="false" name=
"edrload.partstructurefilter.enableviztabfilter"/>
For detailed information on the properties to configure the filter, see
“Configurable and Supplier Part Filtering “ in the Windchill Visualization Services
Administrator’s Guide.

Example
Only parts in the released state should be shown in Creo View. Assembly
representations in the release state should include the assembly representation and
exclude the child representations.
/**
* This example filter can be used to include parts in the "released"
* state and exclude all others. End item parts are added to the
* return map as "NORMAL" and assemblies are added as
* "INCLUDE_REP_AND_EXCLUDE_CHILDREN".
* The result is that only released parts can be viewed.
*
* @param _root - The root node of the structure of the part being viewed.
* Not used in this example.
* @param _filterPartStructureParentMap - A map of parts to a set of
* WTPartUsageLink objects.
* Contains the structure of the part
* being viewed
* @param _representations - A map of parts to their default representation.
* Used to replace representations in
* the structure, not used in this example
*

1488 Customization Guide


* @return WTKeyedMap - A WTKeyedMap of parts to their
* RepStructureFilterAction enums
*/
public static WTKeyedMap useCase1(WTObject _root,
WTKeyedMap _filterPartStructureParentMap,
WTValuedMap _representations) {
WTKeyedHashMap retSet = new WTKeyedHashMap();
for(Iterator it=_filterPartStructureParentMap.entrySet().iterator
(); it.hasNext();) {
WTKeyedMap.WTEntry entry = (WTKeyedMap.WTEntry)it.next();
try {
WTPart part = (WTPart)entry.getKeyAsPersistable();
String partName = part.getName();
logger.debug("Inside filterPartStructure,
Part Name == " + partName);

State state = part.getLifeCycleState();


// Only include parts in the "RELEASED" state
if (state.toString().equals("RELEASED")) {
// do include this representation
if (part.isEndItem())
retSet.put(part, RepStructureFilterAction.NORMAL);
// An end part
else
retSet.put(part, RepStructureFilterAction.
INCLUDE_REP_AND_EXCLUDE_CHILDREN); // An assembly
logger.debug("Adding " + partName + " to return map to be
included");
}
else {
// don't include this representation
retSet.put(part, RepStructureFilterAction.EXCLUDE);
logger.debug("Adding " + partName + " to return map to
be excluded");
}
}
catch (WTException e) {
logger.error("Error filtering parts in the
'partStructureFilter' hook:\n " + e);
}
}
return retSet;
}

Customizing Windchill Visualization Services 1489


35
Report Generation
Report Generation Overview .................................................................................. 1493
Basic Report Example ........................................................................................... 1493
Import and Export of Report Templates ................................................................... 1494
Java Methods ....................................................................................................... 1497
Customization Details ............................................................................................ 1498
Cognos Presentation Customization ....................................................................... 1518
Reporting Info*Engine Task Data Source Customization........................................... 1524
Report Loading ..................................................................................................... 1530
ReportTemplate Data Source Customization ........................................................... 1539
Reporting Input Page Customization....................................................................... 1543
Report Localization Customization.......................................................................... 1548
Report Selection List Customization........................................................................ 1554

This chapter describes report generation tools that provide the following
functionality:
• Definition of a broad range of queries against Windchill data using a graphical
interface rather than Java programming.
• Use of these queries to generate reports in several output formats, including
HTML, XML, and CSV.
• Customization of queries and output formats, and re-use of queries and output
formats from other customizations.
• Customization of the Windchill Business Reporting (Cognos) report
presentation, data sources, and other features.
To author new queries using existing report formats, you need only be familiar
with the UML model for the business objects of interest for the query and have an
understanding of the query definition tool. Because the report generation tools

1491
build on the capabilities of the Windchill foundation and use HTML, CSS, XML,
and XSL technologies, you should also be familiar with these areas to use the
tools most effectively for customization.

1492 Customization Guide


Report Generation Overview
Reports are generated by applying presentation information to query result data.
Queries are built using the Windchill Query Builder tool and stored as a report
template business object in Windchill. When a report template query is executed,
it operates against the current database and produces output in the form of Java
objects or XML.
Reports are generated from XML output by applying presentation transformations
defined by XSLT (Extensible Stylesheet Transformation) stylesheets. The
combination of XML and XSLT allows for a separation between data collection
and formatting, thus facilitating separate customization of each. When defining
report template objects, you can select from out-of-the-box XSLT formats or
specify custom XSLT stylesheets to meet your formatting needs.

Basic Report Example


The Query Builder online help includes a step-by-step tutorial for creating a new
query. Each step of the tutorial includes links to the relevant help topics for that
step. See the “Query Builder Tutorial” topic in the Windchill Help Center for
more information.

Report Generation 1493


Import and Export of Report Templates
Two command line utilities are available for import and export of report templates
to and from the database. The import utility, LoadReportTemplate, can be
used in a standalone manner or from within wt.load.Demo. The export utility,
ExportReportTemplate, is available in standalone mode only.

Note
Individual report templates can be imported and exported using the Import and
Export actions available from Report Management. For more information, see
the help available from Report Management.

The LoadReportTemplate utility persists report template objects to the


database based on input from an XML file. In this file, each report template object
is defined in a csvReportTemplate element. The content of these elements
are defined as follows:
csvReportTemplate Description
element
csvfolder Required. This entry is the location of the report
templates in Windchill Explorer. If the specified folder
does not exist, one is created.
csvname Required.
csvdescription Optional.
csvxml Required. This entry specifies a path to the XML
source file. This file is parsed and then validated
against the QML DTD (<Windchill>/codebase/wt/
query/qml/qml.dtd). The path is first assumed to be an
absolute file path. If the file is not found, the path is
then assumed to be relative to the <Windchill>/
loadfiles directory.
csvxsltype The XSLT designation; possible options include the
following:
• DEL (delegation), which allows selection from a
set of defined XSLT formats.
• URL, which offers selection of a customized XSLT
stylesheet.
• No entry, which requires the user to select a format
style at report template generation time.
csvservice If the XSLT designation is DEL, this column is
required. The formats currently available are as
follows:

1494 Customization Guide


csvReportTemplate Description
element
HTML
CSV
TSV
XML
PDF
HTMLWithSorting
HTMLWithMerging
MSWord2000Portrait
MSWord2000Landscape
csvContainerPath Optional. This column specifies a container where the
report should be stored. If no value is specified, the
site container is used by default.
csvurl1 If the XSLT designation is URL, this column is
required and should contain a URL pointing to a
customized XSLT stylesheet.
csvurl2 This column is used only if the XSLT designation is
URL and, even then, is optional. It defines a second
URL location for an XSLT stylesheet.
csvinputPage Optional. This entry specifies an input page for the
Report.
csvresourceBundle Optional. This entry specifies a resource bundle for the
Report.

An out-of-the-box XML file, reporttemplates.xml, is provided along with


several sample XML source files. These XML files are used for persisting sample
report templates during wt.load.Demo. The reporttemplates.xml file is
located in <Windchill>/loadFiles and the sample XML files are located in
<Windchill>/loadFiles/reports.
There are three options for using the LoadReportTemplate utility in standalone
mode:
java wt.query.template.LoadReportTemplate
No parameters indicate that the default sample files defined earlier are being used.
java wt.query.template.LoadReportTemplate c:\loadReports.xml
The parameter indicates the absolut path of a user-defined XML file.
java wt.query.template.LoadReportTemplate loadReports.xml
The parameter indicates the relative path of a user-defined XML file.

Report Generation 1495


The ExportReportTemplate utility downloads multiple, persisted report template
objects from the database to the relative file exportreports.xml. This file has the
same structure as defined above.
The ExportReportTemplate utility has three optional parameters:
• The first parameter specifies a string to use to search for report template
objects by name. The "%" symbol can be used as a wildcard to match any
number of characters in the name. If this parameter is not specified, all report
template objects are exported.
• The second parameter specifies the path of the container in which to search. If
this parameter is not specified, the site container is searched to find the report
template.
• The third parameter specifies whether the container should be searched
hierarchically. If the value is true, the criteria will match the specified
container or any of its parent containers. If the value is false, only the specified
container will be matched. If this parameter is not specified, a value of true is
used.
The following example exports all report template objects in the site container that
have a name starting with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly%

The following example exports all report template objects in the Windchill PDM
library, the DefaultOrg organization, and site containers that have a name starting
with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly%
"/wt.inf.container.OrgContainer=
DefaultOrg/wt.inf.library.WTLibrary=Windchill PDM"

The following example exports all report template objects in the Windchill PDM
library that have a name starting with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly%
"/wt.inf.container.OrgContainer=
DefaultOrg/wt.inf.library.WTLibrary=Windchill PDM" false

1496 Customization Guide


Java Methods
The ability to call Java methods has been added to make report authoring easier.
Because Java methods are always invoked in a method server, to ensure security
only those Java methods specified in a configuration file can be invoked in a
report. By default, this configuration file is:
<Windchill>\conf\queryBuilderMethods.xml
where <Windchill> is the installed location of your Windchill solution.

Note
The default configuration file can be overridden by setting the wt.query.qml.
allowedMethodsXMLFile property in wt.properties.

The following attributes are used in specifying the Java methods in the
configuration file:
• class—The package and class containing the method. This attribute is
required.
• name—The name of the method. This attribute is required.
• static—Indicates whether the method is a static method. This attribute is
optional, and if not specified the value is assumed to be false.
The format for specifying a Java method in the configuration file is shown in the
following example:
<methods>
<method class="java.lang.Object" name="toString"/>
<method class="java.lang.Object" name="getClass"/>
<method class="example.HelloWorld" name="example" static="true"/>
</methods>

To add a new Java method, add a new method element to the configuration file,
as shown in the example. Java methods can be removed from the configuration
file, removing them from availability for use in authoring reports, by deleting its
method element.
After adding a new Java method, use the Load Application Data action from the
Query Builder Maintenance Dashboard. This action loads the new Java method and
makes it available for use in the Query Builder. For more information, see Query
Builder Maintenance Dashboard.

Report Generation 1497


Customization Details
After a report exists, there are a number of ways to customize various aspects of
the report:
• Customizing Macros on page 1498
• Customizing Query Builder Types on page 1500
For reports using custom input pages, additional customizations are supported:
• Customizing the Report Output Format on page 1501
• Customizing the Report Generation Client on page 1513
• Customizing the Report Generation URL on page 1516

Customizing Macros
Customizing macros uses the standard Windchill application services delegation
mechanism. This customization example creates a new macro to automatically
compute a cutoff time.
1. Create a class that implements the MacroExpressionProcessor interface by
performing the following steps:
a. Create a new package or use an existing one. Name the package, for
example, myPackage.
b. Create a new class and inherit from the MacroExpressionProcessor
interface in the wt.query.report package. Name the class, for example,
TimeCutoffMacroProcessor.
c. Compile the class.
d. Fill in the implementation of the buildExpression( ) method. This
implementation reads the current system time in milliseconds, computes
the new time, and creates a new Date. The Date value is returned as a wt.
query.DateExpression. This is necessary because of special handling of
dates in SQL expressions to take into account Java representation of dates
and timezone settings.
public class TimeCutOffMacroProcessor implements MacroExpressionProcessor {

@Override

public ColumnExpression buildExpression( Element a_element,


Map a_parameterMap ) throws QMLException
{
final int DAYS=3;
long currentSeconds= (System.currentTimeMillis()/1000);
long timeSeconds= currentSeconds - (60*60*24*DAYS);
java.util.Date time= new java.util.Date(timeSeconds * 1000);
return (ColumnExpression) DateExpression.newExpression(time,

1498 Customization Guide


Timestamp.class.getName());

@Override

public Object getValue()throws WTException{


final int DAYS=3;
long currentSeconds= (System.currentTimeMillis()/1000);
long timeSeconds= currentSeconds - (60*60*24*DAYS);
java.util.Date time= new java.util.Date(timeSeconds * 1000);

return time;
}
}
e. Fill in the implementation of the getValue( ) method. This value is the
actual Date value as computed in the preceding step. This method is called
to populate Report Builder input fields when a macro is specified as a
default value.
2. Create a logical name for the macro and map it to the implementation class.
For example, for logical name "TIME_CUTOFF" and class "myPackage.
TimeCutoffMacroExpressionProcessor", the entry would be as follows:
wt.services/svc/default/wt.query.report.MacroExpressionProcessor/
TIME_CUTOFF/java.lang.Object/0=myPackage.TimeCutoffMacroProcessor/singleton

The OOTB entries that exist in dbservice.properties.xconf are:


<Service context="default" name="wt.query.report.MacroExpressionProcessor">
<Option cardinality="singleton" requestor="java.lang.Object"
selector="CURRENT_TIME" serviceClass=
"wt.query.report.CurrentTimeMacroProcessor"/>
<Option cardinality="singleton" requestor="java.lang.Object"
selector="CURRENT_USER_NAME" serviceClass=
"wt.query.report.UserNameMacroProcessor"/>
<Option cardinality="singleton" requestor="java.lang.Object"
selector="TIME_CUT_OFF" serviceClass="ext.mypkg.TimeCutOffMacroProcessor"/>
</Service>
3. Create a new report query that uses the new macro by performing the
following steps:
a. Open the existing Foldered query and save it as a new query, for example,
FolderedModified.
b. Remove the criteria based on cabinet name.

Report Generation 1499


c. Add criteria. On the Criteria tab, set the following values as shown in the
following table:
Field Value
Class Foldered
Attribute thePersistInfo.modifyStamp
Operator >
Value TIME CUTOFF
The TIME_CUTOFF macro is now available for use in reports from the
Criteria tab of the Query Builder.
d. Save the query.
4. Execute the report.
For reports that use macros in criteria or default values, Query Builder evaluates
the macro at runtime and displays the resulting value in the Criteria pane of the
report generation window. It is also possible to use a macro as input in a Criteria
pane input field. The macro name should start and end with the $$ characters to
denote the value as a macro. For example, to use the out-of-the-box CURRENT_
USER_NAME macro in an input field, enter the value as $$CURRENT_USER_
NAME$$.

Customizing Query Builder Types


Query Builder uses object model information to present the list of all possible
types to build queries against. It does this by searching for all types that
implement the wt.fc.NetFactor interface. However, there may be classes that do
not implement the wt.fc.Net.Factor interface, yet have subclasses that implement
the Persistable interface and therefore can be used in queries. An example is wt.
index.Indexable. To allow queries to be built using these types, these types can be
listed as resources in a service properties file. The out-of-the-box entry in
dbservice.properties handles the Indexable interface as follows:
wt.services/rsc/default/wt.query.report.ClassName/
wt.index.Indexable/java.lang.Object/0=wt.index.Indexable

To customize the list of Query Builder types, new entries can be added. For
example, for the class myPackage.myClass, the entry would be as follows:
wt.services/rsc/default/wt.query.report.ClassName/
myPackage.myClass/java.lang.Object/0= myPackage.myClass

This is necessary only if the class does not implement the NetFactor interface, but
does have subclasses that implement the Persistable interface.

1500 Customization Guide


Customizing the Report Output Format

Note
This customization is supported for reports using custom input pages.

Several report output formats are provided out-of-the-box. All of these formats are
intended to be general purpose. That is, they should produce reasonable output
from any query. If none of these formats are appropriate, you can modify them or
create completely new formats.

CSS Customization
All of the HTML report formats provided, except those derived from Microsoft
Word, use a CSS1 stylesheet to specify font, color, size, and spacing details. Use
of CSS1 allows these details to be separated from other aspects of page layout and
placed into one or more re-usable stylesheets. Therefore, the easiest way to
customize these aspects of the HTML reports is to edit the CSS files that they use.
For further information about CSS1, refer to the W3C CSS1 specification,
currently available at the following URL: http://www.w3.org/TR/REC-CSS1

Note
If you have difficulty with this URL, try the site URL www.w3.org.

Two CSS files are involved: htmlFormat4Print.css and htmlFormat4Screen.css.


Both are located in <Windchill codebase>/templates/reports. The
htmlFormat4Print.css file is intended to specify the appearance of HTML when
printed and the htmlFormat4Screen.css file when viewed on screen. Actually,
browsers do not support this aspect of CSS and, therefore, the printed output is
controlled by htmlFormat4Screen.css as well. However, you may prefer
htmlFormat4Print.css to htmlFormat4Screen.css, which is designed primarily for
consistency with other Windchill HTML pages.
To change the CSS stylesheet used by a report or to make larger changes to the
output format than possible through CSS1, you must customize XSLT stylesheets
as described in the next section.

XSLT Customization
As mentioned earlier, reports are produced by applying XSLT stylesheet
transformations to XML query results. This includes all the out-of-the-box
formats. XSLT stylesheets are capable of producing not only any HTML layout
but also any other XML or text format.

Report Generation 1501


XSLT stylesheets are based on the concepts of templates and rules. Most XSLT
stylesheets are largely composed of XML or HTML tags and text that are static;
that is, included verbatim in the output. The remainder of the stylesheet is then
composed of rules for computing the dynamic portion of the output from the input
XML. Depending on the mix of templates and rules, the nature of XSLT
customization can vary from simple HTML authoring to pure programming. For
the definitive specification on XSLT, refer to the W3C XSLT specification,
currently available at the following URL: http://www.w3.org/TR/xslt

Note
If you have difficulty with this URL, try the site URL www.w3.org.

For additional information about XSLT, refer to the “What is XSLT?” link and the
“Resources” area currently available at the following URL: http://www.xml.com

Note
If you have difficulty with this URL, try the site URL www.xslinfo.com

Stylesheets Provided
One technique for customizing the output format is to modify one of the XSLT
stylesheets that are provided in <Windchill>/codebase/templates/
reports/. These stylesheets are described in detail in the following table.

Note
Within fields that specify an XSLT stylesheet in the Windchill UI, you must
enter file paths that are relative to <Windchill>/codebase/. For
example, excel97WebQuery.xsl must be referenced as "templates/
reports/excel97WebQuery.xsl"

XSLT Standard Description


Stylesheet Format Name
identity.xsl XML Performs the identity transformation on the
XML query results; that is, it outputs the
XML input.
csvFormat.xsl CSV (Comma Produces comma-separated-values format
Separated (useful for reading into spreadsheets, and
Variable) so forth).

1502 Customization Guide


XSLT Standard Description
Stylesheet Format Name
tsvFormat.xsl TSV (Tab Produces tab-separated-values format
Separated (useful for reading into spreadsheets, and
Variable) so forth).
simpleHtmlForm HTML Produces a simple HTML format. Unlike
at.xsl the other HTML formats provided, this
format does no extra formatting on numeric
columns.
htmlWithSorting HTML (with Similar to simpleHtmlFormat.xsl except
.xsl sorting) that sorting is provided through hyperlinks
on the column headers.
htmlWithMerg- HTML (with Similar to simpleHtmlFormat.xsl except
ing .xsl merging) that vertically duplicated cells are merged
under certain conditions. This is a time-
consuming transformation compared to the
others provided.
sortedHtm- Produces the same results as
lAsXM L.xsl htmlWithSorting.xsl except that the output
is well-formed XML rather than traditional
HTML, and the results contain additional
non-HTML attributes. This is to facilitate
application of further XSLT transforms (for
example, mergeHTMLCells.xsl) to the
result.
mergeHTMLCell Merges cells in HTML (which must be
s.xsl well-formed XML) similar to
htmlWithMerging.xsl. Additionally, the
input must have extra attributes
annotations. This stylesheet is not intended
for use directly on the query result XML.
Instead, when applied to the results of
sortedHtmlAsXML.xsl, the overall effect is
to produce HTML with both sorting and
merging.
msw2000ls.xsl Microsoft Word Produces a simple HTML format
2000 HTML containing Microsoft Word 2000 metadata.
(Landscape) When the result is dropped onto Microsoft
Word 2000, the originally specified
margins, table borders, and so on are
preserved. Also, decimal tab stops are
specified on floating point data columns.

Report Generation 1503


XSLT Standard Description
Stylesheet Format Name
The result has landscape page orientation.
msw2000p.xsl Microsoft Word Same as msw2000ls.xsl except the result
2000 HTML has portrait page orientation.
(Portrait)
xslfo.xsl PDF Produces XSL Formatting Objects, an
XML-based standard for high-precision
page layout (see http://www.w3.org/TR/
xsl). This is referred to as PDF format in
standard format lists because the default is
to post-process this format to dynamically
produce PDFs. This is done through
Apache FOP (see http://xml.apache.org/
fop) and is controlled by the following user
preference:
/wt/query/report/template/postprocmap/
appl ication/xslfo+xml
This format is currently limited by the
capabilities of FOP (for example, column
widths must be provided rather than being
computed from contents) and will improve
in the future as FOP improves.
excel97WebQuer Produces a version of Excel Web Query (.
y.xsl iqy) format compatible with both Excel 97
and higher. This Excel format records the
URL from which the spreadsheet data
came, and can refresh the data from the
URL periodically or on demand. For best
results with Excel 2000, set the MIME type
for Excel Web Query (IQY) files to be
application/x-excel-web-query; on
downland, this format is then automatically
loaded into Excel 2000 only. With Excel
97, you must save the downloaded file and
select it from within the Excel 97 'Run Web
Query...' command.
excel2000WebQ Produces a version of Excel Web Query (.
uery.xsl iqy) format compatible only with the Excel
version currently supported with Windchill.
(For details about which third party

1504 Customization Guide


XSLT Standard Description
Stylesheet Format Name
products are supported, reference the
Windchill Software Matrices.)
It uses a new feature in Excel Web queries
to attempt to preserve the formatting in the
spreadsheet rather than that in the HTML
URL data source.
barChart.xsl Produce various types of charts
llineChart.xsl corresponding to their names. The first
result column is assumed to contain labels
pieChart.xsl and the rest are assumed to contain chart
scatterChart.xsl data. Output is initially produced as SVG
(Scalable Vector Graphics), a standard
XML-based vector graphics format (see
http://www.w3.org/TR/svg). Because this
format requires a client viewer (for
exampe, Adobe's free SVG Viewer
available at http://www.adobe.com/svg/
viewer/install/m ain.html), the default is to
post-process this format to rasterize the
SVG into JPEG. SVG, JPEG, or PNG
output formats can be selected by the
following user preferences:
/wt/query/report/template/postprocmap/ima
ge/svg+xml
/wt/query/report/template/postprocmap/svg
Rasterizer/rasterFormat
includes/linker. Provides an XSLT template,
xsl generateURLHref, that is used by the
provided HTML and XSL FO formats to
produce hyperlinks to Windchill objects
from XML result nodes that contain
additional attribute information provided
by the query layer when entire Windchill
objects are selected. Object, version, e-
mail, and content download links are
currently supported.
includes/ The shared implementation behind
excelWe excel97WebQuery.xsl and
bQueryBase.xsl excel2000WebQuery.xsl. This stylesheet

Report Generation 1505


XSLT Standard Description
Stylesheet Format Name
allows stylesheets which include it to
specify the relative URL of an XSLT
stylesheet that produces HTML tables. The
produced Excel Web Query then obtains its
data by executing the report (again) but
using the specified HTML table format.
Thus, by changing this HTML format, one
can change the data that appears in Excel as
a result of this Web query. Currently both
excel97WebQuery.xsl and
excel2000WebQuery.xsl use
simpleHtmlFormat.xsl.
includes/chart.xsl The shared implementation behind
barChart.xsl, lineChart.xsl, pieChart.xsl,
and scatterChart.xsl. This stylesheet works
by using Apache Batik (see http://xml.
apache.org/batik) on the server to capture
JChart graphics as SVG and optionally
rasterize them. Note that custom charts and
graphics can easily be captured as well by
implementing wt.query.template.Chartable
interface and replacing "wt.query.template.
ChartCreater" in this file with the name of
the custom Chartable implementation.
includes/msw200 The shared implementation behind
0.xsl msw2000ls.xsl and msw2000p.xsl. The
page size, margins, and orientation are all
specified as inputs. This stylesheet is
intended solely for inclusion from other
stylesheets.
includes/htmlWit The shared implementation behind
h SortingBase. htmlWithSorting.xsl and
xsl sortedHtmlAsXML.xsl. This stylesheet is
intended solely for inclusion from other
stylesheets.

1506 Customization Guide


XSLT Standard Description
Stylesheet Format Name
includes/localize Provides an XSLT named template (that is,
String.xsl a macro) for localizing strings. The
implementation uses an XSLT extension
function to call back into Java to access
Java resource bundles. This stylesheet is
intended solely for inclusion from other
stylesheets.
includes/urlEnco Provides an XSLT named template for
de.xsl URL encoding. The implementation uses
an XSLT extension function to call
WTURLEncoder.encode in Java. This
stylesheet is intended solely for inclusion
from other stylesheets.

Due to the template-based nature of XSLT, some modifications can be made to the
provided stylesheets based almost solely on a knowledge of the intended output
format (such as HTML). For example, the provided formats that use CSS1
stylesheets generate the references to these files using the following lines in the
XSLT stylesheets:
<link rel="stylesheet" type="text/css"
href="{$windchill}/templates/reports/htmlFormat4Screen.css"
media="screen"/>

<link rel="stylesheet" type="text/css"


href="{$windchill}/templates/reports/htmlFormat4Print.css"
media="print"/>

The only part of these lines that is not strictly HTML is the portion within the { }
braces which, though similar to JavaScript expression usage, is actually an XSLT
XPath expression. In this case, the expression is referencing the variable
windchill, which was previously assigned the URL of the Windchill codebase.

XML Resource Bundles


One aspect of the provided XSLT stylesheets is that they use XML resource
bundles for localization of text. Rather than producing different versions of each
XSLT stylesheet for each locale, the locale-dependent text has been extracted into
separate XML files. These are loosely referred to as XML resource bundles, and
are retrieved and searched through XSLT based on the locale.

Report Generation 1507


This approach was taken for the following reasons:
• To allow ease of localization by using the same technology, syntax, and tools
as those behind XSLT and HTML authoring; that is, XML.
• To allow a tighter coupling between XSLT stylesheets and their localization
data. Because relative URLs are used to look up XML resource bundles, they
can be installed relative to the XSLT files that reference them, rather than
relative to the Windchill codebase.
• To allow localization without dependence on XSLT extension functions.
The XML resource bundles used by the provided XSLT stylesheets are located at
<Windchill codebase>/templates/reports/defReportRB_*.xml.
If you decide to use this technique in your own XSLT stylesheets, see the XML
resource bundles provided and the XSLT files provided for usage examples. Keep
in mind the following issues:
• XML resource bundles must be well-formed XML. For further information,
refer to XML.com’s annotated XML specification, currently available at the
following URL: http://www.xml.com/pub/axml/axmlintro.html

Note
If you have difficulty with this URL, try the site URL www.xml.com.

The W3C unannotated, original version of the XML specification is currently


available at the following URL: http://www.w3.org/TR/REC-xml

Note
If you have difficulty with this URL, try the site URL www.w3.org.

• The encoding listed in the <?xml ...?> header should match that actually used
when saving the file and should be one supported by the XML parser used
(Xerxes 1.2.2). For example, on Windows NT, you can use the Save as
Unicode option in NotePad and specify an encoding of "unicode" in the XML
resource bundle.

1508 Customization Guide


New Formats
Besides modifying existing XSLT, you can also author entirely new XSLT
stylesheets. You can author new stylesheets using the following steps:
1. Author a sample of the intended output format. For example, use an HTML
editor to produce a sample of the intended format; create a sample document
in Microsoft Office and save it as HTML (this is how the Microsoft Word-
based HTML formats were created); or export an Adobe Illustrator drawing as
SVG.

Note
The use of Apache Batik, as described in the various chart.xsl stylesheets
(see the table in the section on Stylesheets Provided on page 1502 earlier
in this chapter), provides an alternative means of producing SVG with
minimal knowledge of XSLT.

2. Copy static pieces of the sample output to a skeleton XSLT stylesheet, editing
or escaping them as necessary to ensure that they are well-formed XML. (All
XSLT must be well-formed XML.)
3. Author XSLT to transform the input XML into the dynamic portions of the
output, using the sample output as a guide.
The number and complexity of transformations to be done in step 3 can vary
greatly from one format to another and largely determine the effort involved in
creating a new format. XSLT provides extensive capabilities for sorting, filtering,
summing, and combining XML data. Additionally, you can provide XSLT
extension functions and elements that call other languages, including Java and
JavaScript. See the Saxon documentation for further details.

XML Result Format


Understanding the query result XML format is extremely important to
successfully retrieving the desired data from it using XSLT (or any other
technique). An outline of this format is shown below. The portions in bold
represent dynamic data and ellipses (...) represent omitted items.
<?xml version="1.0" encoding="UTF-8" ?>
<queryResult>
<metadata>
<name>Report Name</name>
<description>Report Description</description>
<objectIdentifier>Report Object Id</objectIdentifier>
<sourceSystem>Windchill Codebase URL</sourceSystem>
<sourceGateway>Windchill Gateway URL</sourceGateway>
<executingPrincipal>

Report Generation 1509


<fullName>User’s Full Name</fullName>
<objectIdentifier>User Object ID</objectIdentifier>
</executingPrincipal>
<timeOfExecution>Time when Executed</timeOfExecution>
<locale>Locale of User</locale>
</metadata>
<auxData>
<dataItem name="requestParam1">value</dataItem>
. . .
<dataItem name="requestParamN">value</dataItem>
</auxData>
</qml>
. . .
</qml>
<actualParameter parameterId="ParamName1"> Value
</actualParameter>
. . .
<actualParameter parameterId="ParamNameN"> Value
</actualParameter>
<result>
<heading tag="column1TagName"
type="Java data type">column header</heading>
. . .
<heading tag="columnNTagName"
type="Java data type">column header</heading>
<row idx="1">
<column1TagName>value</column1TagName>
. . .
<columnNTagName>value</ColumnTagName>
</row>
. . .
<row idx="N">
. . .
</row>
</result>
</queryResult>

If an entire Windchill top-level object (a Persistable) is selected, additional


attributes are generated on the column tag element, including the object ID,
branch ID (if the object is versioned), and classname of the object. WTUser
objects also include email attributes. These attributes are generated primarily to
facilitate generation of hyperlinks. Out-of-the-box XSLT stylesheets for HTML
and PDF formats use these attributes whenever they are present to produce
hyperlinks to the objects.

1510 Customization Guide


Additional flexibility for generating hyperlinks is provided by use of the
characters $$ in column names. If a column name containing $$ is specified
through the Query Builder, an individual cell is not created for it; instead, the
name is parsed as follows. If the part of the column name preceding $$ matches
another column name that does not contain $$, its data is added to the other
column as an attribute, which is determined by the part following $$.
For example, assume the following columns are specified through Query Builder:
• Part
• Part$$branchID
• Part$$type
Each XML row would then contain a Part element like the following:
<Part branchID="dataFromBranchIdColumn"
type="dataFromTypeColumn">dataFromPartColumn</Part>

Rows would not contain individual Part$$branchID or Part$$type columns. This


functionality allows you to select the right data to obtain hyperlinks (as described
earlier in this section) without having to select entire Persistable objects.
If the column type is java.util.Date, column data is formatted based on the HTTP
request's Locale. In addition, the column element has a "value" attribute
containing the raw Java string value. If other date-formatting customization is
needed, this value could be used.
The table below summarizes the data conveyed by the various top-level elements
in the query result XML.
Element Description
metadata Meta-information about the query from which the data
resulted and the user executing it.
auxData The request parameters used.
qml Fully defines the details of the report template query
which was made (see <Windchill codebase>/wt/query/
qml/qml.dtd for further details).
actualParameters The query parameters used when executing the query.
result The column headers and types, and the rows of data.

Using XSLT Stylesheets as Report Formats


To use an XSLT stylesheet as a report format, you must specify it either in the
report template user interface or, for report templates that specify their format as
“Ask Upon Generate”, upon generation using the HTML report generation form.
In either case, two means of specifying formats are allowed: custom and standard.

Report Generation 1511


Specification of custom formats is done using up to two relative or absolute
URLs. When the URLs are not absolute, they are relative to the Windchill
codebase. When two XSLT URLs are specified, they are applied to the report
results in series. The custom specification mechanism allows use of XSLT
stylesheets that are not located on the Windchill server and facilitates testing of
new stylesheets. It also allows the application of two XSLT stylesheets in a series,
which is not possible through the standard format mechanism.
Specification of standard formats is done by selecting one from a list. Most of the
provided XSLT stylesheets are part of this list. Additional formats can be added to
this list by editing dbservice.properties. These property entries begin with wt.
services/rsc/default/wt.query.report.DefaultXSL.
If an existing format is being replaced with a customization, then there may be an
additional property entry for the format type that overrides the XSL. This property
begins with wt.services/svc/default/com.ptc.core.query.report.client.generation.
ReportSAXTransform and should be removed.
The format of these entries is that of the Windchill application services delegation
mechanism. If localization of the additional entries is required, edit the Java
resource bundle wt.query.template.TemplateResource.

1512 Customization Guide


Customizing the Report Generation Client

Note
This customization is supported for reports using custom input pages.

The report generation client consists of an HTML form that can prompt the user
for additional report generation input and an HTTP processor that executes the
report and applies the XSL transformations. Both of these clients can be
customized in the same manner as typical HTML client customizations. For
further information, see Customizing HTML Clients Using the Windchill JSP
Framework on page 289.
In addition, report generation-specific code is available as static methods in a
separate class so it can be reused. The ReportTemplateHelper class provides many
methods for processing reports (See the wt.query.template.ReportTemplateHelper
class entry in your installed Windchill Javadoc for more information).

Note
In previous releases, reports that used subtypes (that is, types created using the
Type and Attribute Management utility) needed to be processed using the report
commands (See the com.ptc.core.query.report.command.common package
entry in your installed Windchill Javadoc for more information). The
ReportTemplateHelper APIs now directly support subtypes and customer-
created attributes. While report commands are still supported, they are no
longer required.

Both of the clients mentioned above rely on a wrapper API developed for XSLT
processors. The API can be found in the wt.xml.xslt package entry in your
installed Windchill Javadoc for more information.
This API provides the following functionality:
• Independence from individual XSLT implementations (for example, Saxon,
the XSLT processor library currently in use)
• A high-level abstraction for XML source that hides the details of a particular
implementation (for example, String, Java IO stream, DOM, or SAX)
• A clean API for XSLT operations in Windchill
• Easy-to-use, high-level facilities for complex chaining of XSLT
transformations

Report Generation 1513


For additional capabilities beyond those provided through this API, you can use
the standard JAXP (Java API for XML Processing) APIs, or access Saxon
directly. For further information, see the Saxon Web page, currently available at
the following URL:
http://saxon.sourceforge.net
Note, however, that the XSLT library bundled with Windchill may change in the
future and that users of the Windchill XSLT and JAXP APIs will be affected less
by any such change.

Report Generation Form


The report generation form is used to gather additional report input parameters
prior to execution. It consists of two main sections: report parameters and output
format.
The report parameters section is built from data specified in the query. Given a
report query as an XML source, the ReportTemplateHelper
buildParameterTemplates( ) method returns an array of ParameterTemplate
instances that represent the parameters of the query. The current client accesses
this parameter template data to build the form to prompt the user for input. Note
that the processing bypasses any parameter templates if the specified name is
included in the HTTP parameters (see the section Customizing the Report
Generation URL that follows). This is an indirect way to customize the form. For
example, fully specifying all parameter values in the report generation URL would
cause no parameter input fields to be generated. Also, the current form processing
completely bypasses the form and goes directly to the report execution processing
if the XSL specification has been set in the report template and all required
parameters (if any) have had values specified in the HTTP parameters.
The output format section is generated based on the XSL specification of the
report template object. If one exists, the output format section is bypassed.
Otherwise, the input fields for specifying the format are generated. The
ReportTemplateHelper getAvailableXSLFormats( ) method is used to build the
drop-down choice for the standard XSL.

Report Generation Output


The report generation output relies on the XSLT API. The basic steps are as
follows:
1. Generate report data as XML using the ReportTemplateHelper generateXML()
method.
2. Obtain a list of XSL stylesheets to apply. This can be specified as an attribute
of the report template object or as HTTP parameters. The report template
object XSL Specification attribute has precedence over the HTTP parameter
values. This logic is implemented in the ReportTemplateHelper.getXSLSpec()
method.

1514 Customization Guide


3. Create XSLT Transform objects chaining together the array of Stylesheets as
necessary. This method is implemented in ReportTemplateHelper.
getTransform().
4. Get the post-processor based on the output media type using
ReportTemplateHelper.getPostProcessor(). This method uses the preferences
mechanism to retrieve the class name of the post-processor.
5. Set the response output type and generate data to the response output stream:
if(postProcessor==null)
{
// No post processor found
response.setHeader("content-type",
ReportTemplateHelper.concatMediaTypeAndEncoding(
outputMimeType, finalSheet.getOutputEncoding()));
transform.outputToStream( response.getOutputStream() );
}
else
(
// Post processor found
response.setHeader("content-type",
ReportTemplateHelper.concatMediaTypeAndEncoding(
postProcessor.getOutputMediaType(),
postProcessor.getOutputEncoding()));
postProcessor.process( transform, response.getOutputStream() );

Creating a New Client


The preceding sections describe the current report generation client and some
simple customization points. Using the XSLT API, ReportTemplateHelper
methods, and report commands as a basis, there are many ways that an entirely
new client could be created. However, detailed discussions on this topic are
beyond the scope of this document.
The following are possible example customizations:
• Use the ReportTemplateHelper APIs or report commands that return
TypeInstances, QueryResult or Java Swing TableModel objects. These
methods can be used in a Java client that uses a specific type of display or
must implement additional result set processing.
• Execute report generation in a background or batch mode (for example,
running reports nightly) and saving the results in Windchill.

Report Generation 1515


Customizing the Report Generation URL

Note
This customization is supported for reports using custom input pages.

Understanding the report generation URL is important for customizing


applications to seamlessly integrate report generation functionality. The URLs that
invoke reports can be created dynamically or set up statically (for example,
bookmarked) with known URL parameters. There are two types of report
generation URLs: Generate Form and Execute Report. The Generate Form URL
requests additional input from the user (only if necessary) and generates a form
action button that leads to the Execute Report page. The Execute Report page
executes the query and returns output to the HTTP request output stream.
Both of these URLs can be edited directly to add URL parameters. Either the
original or the edited URL can be bookmarked or used in a hyperlink for future
reuse. The URLs can also be generated programatically. The
ReportTempateHelper class provides APIs for each type of URL. Several
versions, each taking different parameters, are also available. See the
getGenerateFormURL( ) and getExecuteReportURL( ) classes entry in your
installed Windchill Javadoc for more information.
The Generate Form URL can have parameter values specified directly. For any
parameter names that are specified on the URL, the input field is bypassed. In
addition, all URL parameters are passed to the Execute Report URL through the
form’s action button. The Execute Report URL also derives all report parameter
values from the URL parameters (through ReportTemplateHelper methods). If a
URL parameter does not exist for a report parameter, then the report parameter’s
default value is used. In addition, several other URL parameters, described in the
following table, can be used.
URL Parameter Description
Name
jrb Name of a Java resource bundle for localization of result
column headers. The provided XSLT stylesheets are all
capable of localizing the result column headers if the name
of a Java resource bundle is provided to them. This is
intended to allow for re-use of a single query to support
multiple locales because the report template user interface
provides no means of entering strings per locale.
format Specifies the format type: formatDelegate or
formatCustom. This parameter is used only if the report
template object has no XSL specification.
delegateName Specifies the delegate name to obtain an XSL stylesheet
from Windchill codebase. The delegate name must match

1516 Customization Guide


URL Parameter Description
Name
a value specified in the dbservice.properties file. This
parameter is used only if the report template object has no
XSL specification and the format URL parameter has a
value of "formatDelegate".
xsl1 Specifies a URL for a custom XSL stylesheet. This
stylesheet is applied immediately to the query result and
can generate direct output to the user, or output suitable
for input to another XSL stylesheet. This parameter is
used only if the report template object has no XSL
specification and the cformat URL parameter has a
value of "formatCustom".
xsl2 Specifies a URL for a custom XSL stylesheet. This
stylesheet is applied to the output of the first XSL
stylesheet (specified by xsl1) and should generate output
to the user. This parameter is used only if the report
template object has no XSL specification, the format
URL parameter has a value of "formatCustom", and the
xsl1 URL parameter has been specified.

Report Generation 1517


Cognos Presentation Customization
Objective
You want to create a Cognos report that queries data from an existing Windchill
Data Source.

Background
Cognos is a third party reporting tool that is integrated with Windchill. It exposes
Windchill Data Source objects in Cognos that can be used in Cognos reports to
retrieve data from Windchill. Cognos is used to format and present the data for
your report.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/Cognos/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
Assume you will name your new report <MyReport> and it will use the
<MyDataSource> object to retrieve data from Windchill. It is also assumed that
you will be able to create a Report object in Windchill in the Site context.
The WBR solution provides several out-of-the-box Windchill Data Source
objects. If custom Windchill Data Source objects are required for your report, see
ReportTemplate Data Source Customization on page 1539 for more details.

1518 Customization Guide


Intended Outcome
The end result of this solution is the creation of your report in Cognos. A sample
output of a report is shown below.

Solution
Use Cognos Report Studio to create a report using a Windchill Data Source.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Cognos Report Authoring
• JMX Console Basic Usage

Report Generation 1519


Solution Elements
Element Type Description
<MyDataSource> Cognos Cognos Object The Cognos object that is
Data Source used to query data from
Windchill.
<MyReport> Cognos Cognos Object The Cognos object for a
Report report that contains the
definition of the query
and specifies the
presentation formatting.
<MyReport> Windchill Windchill Object The Windchill object that
Report is displayed to end users
in the Windchill User
Interface. It acts as a
proxy to a corresponding
Cognos Report object.

Procedures
This section contains detailed information about the following customization
procedures:
• Creating a Report on page 1520
• Creating a Report in a non-Site context on page 1521
• Deleting a Report on page 1522

Creating a Report
1. Login to Cognos using the <WBRHomeURL>.
2. Navigate to “Public Folders > Windchill”.
3. Launch “Report Studio”.
4. Select <MyDataSource> as the Data Source for the report. These appear in the
“Insertable Objects” window under the “Source” tab.
5. Use Cognos Report Studio features to complete the report.
6. Save the report to top level “Public Folders > Windchill” folder as
<MyReport>.
7. Verify the report in Cognos. Refresh the “Public Folders > Windchill” folder
and the <MyReport> object should be listed. Use the “Run with options…”
action to run the report.

1520 Customization Guide


8. Expose your report to Windchill. Launch Java Console from installed
Windchill shortcuts. There are two ways to do this:
• Connect to the Embedded Servlet Engine (based on Tomcat) JVM
instance. Select reporting management bean from the MBeans tab, “com.
ptc > Monitors > ReportingSystem”. From the Operations tab, click
“exposeReports”.
• Select the Refresh Reports List button in Windchill Site/Reports to refresh
the page.
9. View the <MyReport> Report in Windchill. The object will be displayed in
“Site > Reports” . Note that the “Ready For Use” column shows “No” for this
object. This means that other users with read-only access will not see this
report. The “Ready For Use” attribute can be used to limit report access to end
users while the report is being developed.
10. Edit <MyReport> to make the Report accessible to end users. Select the Edit
action, then Select Home for “Display Context(s)” and check the “Ready For
Use” checkbox. Click OK to save these changes. <MyReport> will now be
visible to all users with read access from both “Site > Report” and “Home >
Reports”.
11. Verify the report in Windchill. Navigate to “Home > Reports” and Select the
“View Report” action for the <MyReport> object.

Creating a Report in a non-Site context


In the primary procedure above, the Cognos Report was created in the
“Windchill” public folder in Cognos. This folder correlates to the Site context in
Windchill and the Windchill Report object is created in this context. A variation of
the primary procedure is to create the Cognos Report and correlated proxy
Windchill Report in a non-Site context such as an organization. You will need to
create a folder structure in Cognos that corresponds to the non-Site contexts that
you wish to use in Windchill. For example, assume you have an organization
<MyOrg> that contains a product <MyProduct> and you want to create a report,
<MyProductReport>, in the <MyProduct> context.
Prior to following the above primary procedure steps, create the following folders
in Cognos
1. Under the “Public Folders > Windchill” folder, create a folder with the name,
“wt.inf.container.OrgContainer=<MyOrg>”.
2. Under the “Public Folders > Windchill > wt.inf.container.OrgContainer=
<MyOrg>” folder, create a folder with the name, “wt.pdmlink.
PDMLinkProduct =<MyProduct>”.
3. In step 6 of the above procedure, save the report to the “Public Folders >
Windchill > wt.inf.container.OrgContainer=<MyOrg> > wt.pdmlink.
PDMLinkProduct =<MyProduct>” folder as <MyProductReport>.

Report Generation 1521


4. In step 6, save the report to the "Public Folders > Windchill > wt.inf.container.
OrgContainer=<MyOrg> > wt.pdmlink.PDMLinkProduct =<MyProduct>"
folder as <MyProductReport>.
5. After exposing the report in step 8, the Windchill Report will be displayed in
"Product: <MyProduct> > Reports".

Deleting a Report
A report that is no longer needed can be removed from the system by deleting
both the Cognos and Windchill Report objects. Assume you want to delete
<MyReport>.
1. Use the Cognos UI to browse to <MyReport> in the “Public Folders >
Windchill” folder (if it is a non-Site context report, then it will be in a sub-
folder) and select the “Delete” action.
2. Then, use the WindchillUI to locate <MyReport> and select the “Delete”
action.

Note
The Reports table supports a multiple row delete action if the Reports table is
within a context and you have delete access rights for Windchill Report
objects in that context.

Limitations
The Cognos report authoring capabilities are designed for many different types of
Data Sources. The WBR integration uses XML Data Sources. These may have
some limitations when compared to other types of Cognos Data Sources. In most
cases, Cognos is able to implement the similar functionality for XML Data
Sources, but there may be implications. For example, it is possible to use
aggregate functions to summarize data, but this processing takes place in the
Cognos server after all data has been received so this may cause performance and
scalability issues.
Cognos Reports have a one-to-one association with the Windchill Report business
object. This object implements the AccessControlled interface so that standard
Windchill access control can be applied. Note that there is no access control
concept of “execution” rights. If a user has “read” access, then that user is also
able to execute the report. The out-of-the-box access control policy for Windchill
Report objects is specified for the Site context which provides Read access for all.
Other access control rules will apply to Report objects based on type inheritance.
For example, the Report object extends WTObject so at the Site level, Full access
is granted for Administrators.

1522 Customization Guide


Cognos Reports are subject to the Cognos server’s access control policies. When
Cognos is deployed as part of WBR, the integration does not alter Cognos default
access control permissions, users, or groups apart from configuring Cognos to
share Windchill LDAP for authentication. Further alteration to the access control
permissions, users, or groups in Cognos must be done via Cognos’ tools, i.e. via
their UI or API which is described in the Cognos documentation. For a good
overview, see the "Initial Security" chapter in the Cognos Administration and
Security Guide.

Sample Code

Examples of Usage in Windchill Code


Windchill supports out-of-the-box reports for both the Windchill ProjectLink and
Windchill PDMLink solutions. See the Windchill Basic Administration Guide for
details. Directly modifying the associated objects is not supported.

Related Package/Class Javadoc


• CognosIntegration module
○ com.ptc.windchill.cognos
• Reporting module
○ com.ptc.windchill.enterprise.report
• Related Customization Documentation
○ Cognos Help (http:// <WBRHost>/Cognos/documentation/help_docs.html)
• Related Windchill Documentation
○ Windchill Basic Administration Guide
○ Windchill Specialized Administration Guide

Related Websites
• http://www.ibm.com/cognos/support

Report Generation 1523


Reporting Info*Engine Task Data Source
Customization
Objective
You want to create a new Windchill programmatic data retrieval task to use in a
report.

Background
The Windchill Business Reporting (WBR) solution uses Data Source objects to
retrieve data from Windchill. One type of Data Source is an Info*Engine task. An
Info*Engine task is a text-based document that uses programmatic constructs to
retrieve and manipulate Windchill data. The task must return its data in a tabular
format (i.e. each element must have the same number of attributes) and task must
be commented with special tags and syntax to define it as a WBR Data Source.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
Assume you have access to the Windchill server tasks directory,
<WindchillHome>/tasks, to create an Info*Engine task <MyTask> in sub-directory
<MyTaskPackage>.
For WBR integration, you must also have access rights to update the reporting
meta model.
This document does not contain details on how to construct Info*Engine tasks.
See the Info*Engine User's Guide for this information.

Intended Outcome
The end result of this solution is the creation of your Data Source that can be used
to author Cognos reports.

Solution
Construct an Info*Engine Task Data Source.

1524 Customization Guide


Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Info*Engine User's Guide
• The Windchill APIs related to the Windchill business objects that will be used
in the Info*Engine task
• JConsole User Interface
• Cognos User Interface

Solution Elements
Element Type Description
<MyTask> Info*Engine Task The Info*Engine task for
retrieving and
manipulating Windchill
data.

Procedure – Creating an Info*Engine Task Data Source


1. Create an Info*Engine task XML file in <WindchillHome>/tasks/
<MyTaskPackage>.
2. Write report task to return results in tabular format. This is an otherwise
normal Info*Engine task that follows certain additional conventions. First, it
returns a tabular Group where each column has objects of the same type. The
following are the allowed column types:
• java.lang.Boolean
• java.lang.Long
• java.lang.String
• java.sql.Timestamp
• java.util.Date
• java.lang.Double
• com.ptc.core.meta.common.FloatingPoint
• com.ptc.core.meta.common.Hyperlink
• java.math.BigDecimal
3. Add WBR Data Source parameter information to the task comments. There
can be zero or more parameter comments. Each specified parameter must exist
on a single line. The syntax for the parameter comment is as follows:
@param <type> <name> <description>

Report Generation 1525


where <type> is the parameter Java type, <name> is the parameter name, and
<description> describes the parameter. The following are the allowed
parameter types:
• java.lang.Boolean
• java.lang.Long
• java.lang.String
• java.sql.Timestamp
• java.util.Date
• java.lang.Double
• java.math.BigDecimal
4. Add WBR Data Source column information to the “return” task comment. The
column information must be specified in the correct format for this task to be
considered a Data Source. The syntax for the column comment is as follows:
@return <type> ${<variableName>} {columns: <columnList>}

where <type> is the Info*Engine task output type, <variableName> is a


reference to the task variable that will be returned, and <columnList>
describes the tabular format of the output. For more information on <type>
and {<variableName>} consult section "SOAP Comments" in the Info*Engine
User's Guide. The column is a comma separate list of one or more type and
name pairs for each column in the tabular output. The type and name are
separated by whitespace. The following are the allowed column types:
• java.lang.Boolean
• java.lang.Long
• java.lang.String
• java.sql.Timestamp
• java.util.Date
• java.lang.Double
• com.ptc.core.meta.common.FloatingPoint
• com.ptc.core.meta.common.Hyperlink
• java.math.BigDecimal
5. Add task as a method to a ReportTask type. Create a file named “.
delegateInfo” in the same directory as the task file. The file should contain the
following two lines:
repositoryType=com.ptc.windchill

typeId=com.ptc.windchill.enterprise.report.ReportTask

1526 Customization Guide


6. Create and Install a package for <MyTask>. See “Advanced User Topics >
Packages” in the Info*Engine User's Guide.
7. Update the Cognos model to recognize this new Data Source. Launch
JConsole from installed Windchill shortcuts. Connect to the Embedded Servlet
Engine (based on Tomcat) JVM instance. Select reporting management bean
from the MBeans tab, “com.ptc > Monitors > ReportingSystem”. From the
Operations tab, click “updateModel”.
8. Verify that the Data Source exists in Cognos. Login to Cognos using the
<WBRHomeURL> and launch “Report Studio”. Find <MyTask> Data Source
under “Windchill > Report Tasks > com.ptc.windchill.enterprise.report.
ReportTask” in the “Insertable Objects” window under the “Source” tab.
The following is an example of task comments for a Data Source.
<!--com.infoengine.soap.rpc.def

Report Task Example.

@param java.lang.String param1 A string parameter named param1.

@param java.lang.Long param2 A numeric parameter named param2.

@return INFOENGINE_GROUP ${out} {columns: java.lang.String


name, com.ptc.core.meta.common.Hyperlink url, java.util.Date
deadline, java.math.BigDecimal duration}

-->

Customization Points

Procedure – Creating an Info*Engine Task Data Source under another


Type
In the primary procedure above, the Info*Engine Task was created using the
default reporting type, com.ptc.windchill.enterprise.report.ReportTask. The type
correlates to the “Windchill > Report Tasks > com.ptc.windchill.enterprise.report.
ReportTask” level of the Source tab. The Report task type can be used to group
Data Sources logically. A variation of the primary procedure is to create the
Info*Engine Task under another type, “myPackage.MyReportTask”.
1. This type will need to be added to the comma separated list of reporting types
specified in the property com.ptc.windchill.enterprise.report.
reportTaskClassNames
2. This property must be changed before executing step 7 of the Creating an
Info*Engine Task Data Source procedure above.

Report Generation 1527


3. In step 5 of the Creating an Info*Engine Task Data Source procedure above,
the .delegateInfo entry for typeId should specify “myPackage.MyReportTask”.
4. In step 8 of the Creating an Info*Engine Task Data Source procedure above,
the Data Source will now be available under “Windchill > Report Tasks >
myPackage.MyReportTask”.

Procedure – Deleting an Info*Engine Task Data Source


An Info*Engine Task Data Source that is no longer needed can be removed from
the system by deleting it from Windchill and updating the Cognos model.
Alternatively, the task comments can be removed so that it is not recognized as a
Data Source.
1. To remove a task, uninstall the package and remove the XML file from the
tasks directory.
2. Then, update the Cognos model using step 3 of the Creating an Info*Engine
Task Data Source procedure above.

Limitations
The typeId in the .delegateInfo file maps to the SOAP class and the task file name
maps to the SOAP method within that class. Both of these names should only
contain characters valid for Java identifiers. In addition, the methods must all be
unique for a given class. For a given typeId, each task name must be unique.

Sample Code

Examples of Usage in Windchill Code


There are several out-of-the-box reports that use Info*Engine Task Data Sources.
These Data Sources are listed in the “Windchill > Report Tasks > com.ptc.
windchill.enterprise.report.ReportTask” level of the Source tab. These Data
Sources can be used for creating Cognos reports. However, directly modifying the
associated Info*Engine Tasks is not supported.

Packaged Samples
A demo Info*Engine task Data Source, ContextItems, is available in the
“Windchill > Report Tasks > com.ptc.windchill.enterprise.report.ReportTask”
level of the Source tab. The task source is located in <WindchillHome>/tasks/com/
ptc/windchill/enterprise/reports/ContextItems.xml. It retrieves the union of all
Parts and Documents in a specified context.

1528 Customization Guide


Additional Resources

Related Best Practices


• Reporting — ReportTemplate Data Source Customization
• Reporting — Cognos Presentation Customization

Related Package/Class Javadoc


• Reporting module
○ com.ptc.windchill.enterprise.report

Related Customization Documentation


• None

Other Related Windchill Documentation


• Info*Engine User's Guide(Prerequisite)
• Info*Engine Implementation Guide
• Windchill Specialized Administration Guide

Related Websites
• http://support.cognow.com/support

Report Generation 1529


Report Loading
Objective
You want to load reporting objects into a Windchill Business Reporting (WBR)
system.

Background
The Windchill Business Reporting (WBR) solution uses Windchill and Cognos
objects in the system. Often times these objects are developed in another system
such as a development system and then moved to another system where they are
used in production. This document describes how these Reporting objects are
loaded into a system.
For Windchill business objects, the standard Windchill Data Loading mechanism
is used. These tools are based on describing objects and their attributes in XML
files. The loading is accomplished by instantiating the business objects, populating
the attributes specified in the XML files, and using standard Windchill create
APIs.
For Cognos report objects, standard Cognos SOAP APIs are used. Cognos report
attributes are specified in a Java properties file and the report’s definition is
specified in an associated XML file. These files are processed and the data is
passed to a Cognos SOAP API for creating reports.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/Cognos/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
Assume you have access to the Windchill server tasks directory,
<WindchillHome>/tasks, to create an Info*Engine task <MyTask> in its associated
sub-directory <MyTaskPackage>. Assume that this task has already been
developed and tested on another source system, <WindchillSourceHome>.
Assume you have access to the Windchill UI and the ReportTemplate,
<MyReportTemplate> in the Site context of another source system,
<WindchillSourceHome>.

1530 Customization Guide


Assume you will load a new Windchill Report object, <MyReport>, and it will use
the <MyReportTemplate> to retrieve data from Windchill. It is also assumed that
you will be able to create a Report object in Windchill in the Site context.
For WBR integration, you must also have access rights to update the reporting
meta model.

Intended Outcome
The end result of this solution is the creation of your reporting objects into your
WBR system.

Solution
Construct and execute load files for Reporting objects.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Info*Engine User's Guide
• JConsole User Interface
• Cognos User Interface
• Report Management User Interface
• Windchill Data Loading

Solution Elements
Element Type Description
<MyTask> Info*Engine Task The Info*Engine task for
retrieving and
manipulating Windchill
data.
<MyReportTemplate> Windchill Object The Windchill object that
Windchill specifies a query for
ReportTemplate retrieving Windchill data.
<MyReportTempla XML File The XML file that
teQML> Windchill specifies a query
ReportTemplate Query associated with a
Definition Windchill
ReportTemplate.
<MyReportTemplate XML File The XML file that
Load> Windchill Data specifies data loading
Load Specification directives associated with
a Windchill

Report Generation 1531


Element Type Description
ReportTemplate.
<MyReport> Windchill Windchill Object The Windchill object that
Report is displayed to end users
in the Windchill User
Interface. It acts as a
proxy to a corresponding
Cognos Report object.
<MyReportLoad> XML File The XML file that
Windchill Data Load specifies data loading
Specification directives associated with
a Windchill Report.
<MyCognosReport> Cognos Object The Cognos object for a
Cognos Report report that contains the
definition of the query
and specifies the
presentation formatting.
<MyCognosReportXML> XML File The XML file that
Cognos Report Query and specifies the query and
Presentation Definition presentation associated
with a Cognos Report.
<MyCognosReportAttri Properties File The Properties file that
butes> Cognos Report specifies attributes
Attributes associated with a Cognos
Report.

Procedure – Loading an Info*Engine Task Data Source


1. Copy the task XML file, <WindchillSourceHome>/tasks/<MyTaskPackage>/
<MyTask>.xml in <WindchillHome>/tasks/<MyTaskPackage>. This file could
also be provided by PTC or another 3rd party developer.
2. Copy the associated “.delegateInfo” file in this same directory.
3. Create and Install a package for <MyTask>. See “Advanced User Topics >
Packages” in the Info*Engine User's Guide.
4. Update the Cognos model to recognize this new Data Source. Launch
JConsole from installed Windchill shortcuts.
5. Connect to the Embedded Servlet Engine (based on Tomcat) JVM instance.
6. Select reporting management bean from the MBeans tab, “com.ptc > Monitors
> ReportingSystem”.
7. From the Operations tab, click “updateModel”.

1532 Customization Guide


8. Verify that the Data Source exists in Cognos. Login to Cognos using the
<WBRHomeURL> and launch “Report Studio”.
9. Find <MyTask> Data Source under “Windchill > Report Tasks > com.ptc.
windchill.enterprise.report.ReportTask” in the “Insertable Objects” window
under the “Source” tab.

Procedure – Loading a ReportTemplate Data Source


1. Create the file, <WindchillHome>/loadFiles/reports/custom/
<MyReportTemplateQML>.xml using the Report Management “Export”
action. This file could also be provided by PTC or another 3rd party developer.
2. Create a load file <WindchillHome>/loadFiles/custom/
<MyReportTemplateLoad>.xml.
<?xml version="1.0"?>
<!DOCTYPE NmLoader SYSTEM "standardX10.dtd">
<NmLoader>
<csvReportTemplate
handler="wt.query.template.LoadReportTemplate.createReportTempl
ate">
<csvfolder>/Default</csvfolder>
<csvname><MyReportTemplate></csvname>
<csvdescription></csvdescription>
<csvxml>custom/<MyReportTemplateQML>.xml </csvxml>
<csvxslType></csvxslType>
<csvservice></csvservice>
<csvcontainerPath></csvcontainerPath>
<csvurl1></csvurl1>
<csvurl2></csvurl2>
</csvReportTemplate>
</NmLoader>

3. Load <MyReportTemplate> using the following command.


windchill wt.load.LoadFromFile -d
<WindchillHome>/loadFiles/custom/<MyReportTemplateLoad>.xml -
CONT_PATH /

4. Verify the ReportTemplate exists in Windchill by launching Report


Management in the Site context.
5. Update the Cognos model to recognize this new Data Source. Launch
JConsole from installed Windchill shortcuts.
6. Connect to the Embedded Servlet Engine (based on Tomcat) JVM instance.
7. Select reporting management bean from the MBeans tab, “com.ptc > Monitors
> ReportingSystem”.
8. From the Operations tab, click “updateModel”.
9. Verify that the Data Source exists in Cognos. Login to Cognos using the
<WBRHomeURL> and launch “Report Studio”. Find <MyReportTemplate>

Report Generation 1533


Data Source under “Windchill > Report Templates” in the “Insertable Objects”
window under the “Source” tab.

Procedure – Loading a Windchill Report Object


1. Create a load file <WindchillHome>/loadFiles/<MyReportLoad>.xml.
<?xml version="1.0"?>
<!DOCTYPE NmLoader SYSTEM "standardX10.dtd">
<NmLoader>
<csvCreateReport
handler="com.ptc.windchill.enterprise.report.LoadReport.createR
eport">
<csvname><MyReport></csvname>
<csvcontainerPath/>
<csvdescription></csvdescription>
<csvinputPage/>
<csvresourceBundle/>
<csvuiContext></csvuiContext>
<csvreadyForUse/>
<csvsoapClass/>
<csvsoapMethod/>

<csvreportTemplateName><MyReportTemplate></csvreportTemplateNam
e>
<csvreportTemplateContainerPath/>
</csvCreateReport>
</NmLoader>

2. Load <MyReport> using the following command.


windchill wt.load.LoadFromFile -d
<WindchillHome>/loadFiles/custom/<MyReportLoad>.xml -CONT_PATH
/

3. Verify the Report exists in Windchill in the Reports table of the Site context.

Procedure – Loading a Cognos Report


1. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/
<MyCognosReportXML>.xml based on an existing Cognos Report.
2. Use Cognos Report Studio menu item “Tools > Copy Report to Clipboard” to
copy the XML definition to the system clipboard.
3. Then, paste the clipboard contents into a text editor and save it to file. This file
could also be provided by PTC or another 3rd party developer.
4. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/
<MyCognosReportAttributes> .properties. The base names from this and the
previous step must match exactly (e.g. MyCognosReport.xml and
MyCognosReport.properties.)
type=report
defaultName=<MyCognosReport>
#defaultDescription=

1534 Customization Guide


#resourceBundle=

5. Load <MyCognosReport> using the following command.


windchill com.ptc.windchill.cognos.CognosProxy loadreports
<WindchillHome>/loadFiles/cognosReports/custom

6. Verify the report in Cognos. Refresh the “Public Folders > Windchill” folder
and the <MyCognosReport> object should be listed. Use the “Run with
options…” action to run the report.

Customization Points

Procedure – Loading Multiple Task Data Sources


In the primary procedureProcedure – Loading an Info*Engine Task Data Source
on page 1532 above, a single Info*Engine Task is loaded. To load multiple tasks,
repeat step 1 for each task.
Each step in the remainder of the procedure only needs to be executed once. In the
last step, verify that all Data Sources were loaded.

Procedure – Loading Multiple ReportTemplate Data Sources


In the primary procedureProcedure – Loading a ReportTemplate Data Source on
page 1533 above, a single ReportTemplate is loaded. To load multiple
ReportTemplates, in step 2, specify a separate “csvReportTemplate” element for
each ReportTemplate.
Each step in the remainder of the procedure only needs to be executed once. In the
last step, verify that all Data Sources were loaded.

Procedure – Loading Multiple Windchill Report Objects


In the primary procedureProcedure – Loading a Windchill Report Object on page
1534 above, a single Windchill Report object is loaded. To load multiple
Windchill Report objects, in step 2, specify a separate “csvReport” element for
each object.
Each step in the remainder of the procedure only needs to be executed once. In the
last step, verify that all Windchill Report objects were loaded.

Report Generation 1535


Procedure – Specifying Windchill Report Object Attributes
In the primary procedureProcedure – Loading a Windchill Report Object on page
1534 above, only the basic Windchill Report Object attributes are specified. The
following are the additional attributes that can be specified. For additional
information see the Report javadoc.
csvReport Description
Element
csvname Required. This entry specifies the Report’s name.
csvcontainerPath Optional. This entry specifies a container where the report
should be stored. If no value is specified, the site container
is used by default.
csvdescription Optional. This entry specifies a description of the Report.
csvinputPage Optional. This entry specifies an input page for the Report.
csvresourceBundle Optional. This entry specifies a resource bundle for the
Report.
csvuiContext Optional. This entry specifies the UI context mask to be
used to control where the Report is displayed in the
Windchill UI.
csvreadyForUse Optional. This entry specifies whether the Report is ready
for use for end users. If no value is specified, the default
value is false.
csvsoapClass Optional. This entry specifies the soap class if the Report
uses a report task as its data source. This element is used
along with the “csvsoapMethod” element to completely
specify the report task. The Report must specify either a
report task or ReportTemplate as its data source.
csvsoapMethod Optional. This entry specifies the soap method if the
Report uses a report task as its data source. This element is
used along with the “csvsoapClass” element to completely
specify the report task. The Report must specify either a
report task or ReportTemplate as its data source.
csvreportTemplateN Optional. This entry specifies the ReportTemplate name if
ame the Report uses a ReportTemplate as its data source. This
element is used along with the
“csvreportTemplateContainerPath” element to completely
specify the ReportTemplate. The Report must specify
either a report task or ReportTemplate as its data source.
csvreportTemplateC Optional. This entry specifies the ReportTemplate name if
ontainerPath the Report uses a ReportTemplate as its data source. This
element is used along with the “csvreportTemplateName”
element to completely specify the ReportTemplate. The
Report must specify either a report task or ReportTemplate
as its data source.

1536 Customization Guide


Procedure – Loading Multiple Cognos Reports
In the primary procedure above, Procedure – Loading a Cognos Report on page
1534, a single Cognos Report is loaded.
To load multiple Cognos Reports, repeat steps 3 and 4, for each Cognos Report.
Each step in the remainder of the procedure only needs to be executed once. In the
last step, verify that all Cognos Reports were loaded.

Procedure – Specifying Cognos Report Attributes


In the primary procedureProcedure – Loading a Cognos Report on page 1534
above, only the basic Cognos Report attributes are specified. The following are
the additional attributes that can be specified.
Property Name Description
type Optional. This entry specifies the Report’s type. The valid
values are report, query, and reportTemplate. If not value
is specified, then the default value is "report".
defaultName Required. This entry specifies the Report’s name.
defaultDescription Optional. This entry specifies a description of the Report.
resourceBundle Optional. This entry specifies the name of a Java resource
bundle that is used to localize entries in the corresponding
Cognos report specification XML file.

Limitations
For Cognos Report loading, there are load file directories that are used for
Windchill out-of-the-box reports. These directories should not be used for custom
load files. The reserved directories are <WindchillHome>/loadFiles/cognosReports
and <WindchillHome>/loadFiles/cognosReports/<assemblyId> where
<assemblyId> is a standard Windchill assembly ID such as wnc, pdml, pjl, etc.

Sample Code

Examples of Usage in Windchill Code


There are several out-of-the-box reports that use the load files described in this
document. These are located in the <WindchillHome>/loadFiles,
<WindchillHome>/loadFiles/reports, and <WindchillHome>/loadFiles/
cognosReports directories.

Packaged Samples
A demo load file for Windchill ReportTemplate and Report objects is available in
<WindchillHome>/loadXMLFiles/DemoReports.xml.

Report Generation 1537


Additional Resources
• Reporting Info*Engine Task Data Source Customization on page 1524
• ReportTemplate Data Source Customization on page 1539
• Cognos Presentation Customization on page 1518

Related Package/Class Javadoc


• Foundation module
○ wt.query.qml
○ Reporting module
• Reporting module
○ com.ptc.windchill.enterprise.report

Other Related Windchill Documentation


• Info*Engine User's Guide
• Windchill Data Loading Reference and Best Practices Guide
• Info*Engine Implementation Guide
• Windchill Specialized Administration Guide
• Report Management online help

Related Websites
• http://www.ibm.com/cognos/support

1538 Customization Guide


ReportTemplate Data Source
Customization
Objective
You want to create a new Windchill data query to use in a Report.

Background
The Windchill Business Reporting (WBR) solution uses Data Source objects to
retrieve data from Windchill . One type of Data Source is a ReportTemplate. A
ReportTemplate is a standard, persistent Windchill business object that is
maintained via the Report Management utility. This applet launches the Query
Builder to create and edit a query that is stored as part of the ReportTemplate.
When the ReportTemplate query is executed, standard Windchill APIs are used
that apply all Windchill business logic (e.g. calling Windchill object methods,
applying access control, etc.). Once a new ReportTemplate object is created it can
be referenced from a Report object or exposed and used in the WBR solution as a
custom Data Source.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
Assume you have access rights to create a ReportTemplate business object
<MyReportTemplate> in the Site context.
For WBR integration, you must also have access rights to update the reporting
meta model.
This document does not contain details on how to construct ReportTemplate
queries. See the Query Builder online tutorial and help for this information.

Intended Outcome
The end result of this solution is the creation of your Data Source that can be used
to author Cognos reports.

Report Generation 1539


Solution
Use Report Management and Query Builder to construct a ReportTemplate Data
Source.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Report Management User Interface
• Query Builder User Interface
• The Windchill data model for the area(s) related to the Windchill business
objects that will be used in the ReportTemplate query
• JConsole User Interface
• Cognos User Interface

Solution Elements
Element Type Description
<MyReportTemplate> Windchill Object The Windchill object that
Windchill specifies a query for
ReportTemplate retrieving Windchill data.

Procedure – Creating a ReportTemplate Data Source


1. Navigate to the Windchill “Site > Utilities” and launch the Report
Management utility.
2. From the Report Management UI, click “New” to launch Query Builder.
3. Create a ReportTemplate query and save. This creates a ReportTemplate
business object in Windchill that can be used as a WBR Data Source.
4. Update the Cognos model to recognize this new Data Source. Launch
JConsole from installed Windchill shortcuts. Connect to the Embedded Servlet
Engine (based on Tomcat) JVM instance. Select reporting management bean
from the MBeans tab, “com.ptc > Monitors > ReportingSystem”. From the
Operations tab, click “updateModel”.
5. Verify that the Data Source exists in Cognos. Login to Cognos using the
<WBRHomeURL> and launch “Report Studio”. Find <MyReportTemplate>
Data Source under “Windchill > Report Templates” in the “Insertable Objects”
window under the “Source” tab.

1540 Customization Guide


Customization Points

Procedure - Creating a ReportTemplate Data Source in a non-Site context


In the primary procedure above, the ReportTemplate was created in the Site
context. The Site context in Windchill correlates to the “Windchill > Report
Templates” level of the Source tab. A variation of the primary procedure is to
create the ReportTemplate in a non-Site context such as an organization.
1. Assume you have ReportTemplate create access in the organization <MyOrg>.
2. In step 1, navigate to the “Utilities” page under <MyOrg> instead of the Site
Utilities page.
3. In step 5, the Data Source will now be available under “Windchill > Report
Templates > <MyOrg>”.

Procedure – Deleting a ReportTemplate Data Source


A ReportTemplate Data Source that is no longer needed can be removed from the
system by deleting it from Windchill and updating the Cognos model.
1. Launch Report Management from the context associated with the
ReportTemplate, select the object, and click “Delete”.
2. Then update the Cognos model using step 4 of the above Creating a
ReportTemplate Data Source procedure.

Limitations
None.

Sample Code

Examples of Usage in Windchill Code


There is no out-of-the-box functionality that depends directly on ReportTemplate
Data Source objects. However, there are several out-of-the-box ReportTemplate
objects and these are available in Cognos as ReportTemplate Data Source objects.
These Data Sources can be used for creating Cognos reports. However, directly
modifying these ReportTemplates is not supported.

Packaged Samples
A demo ReportTemplate Data Source object, PartList, is available. It can be
loaded using the following command:
wt.load.LoadFromFile -d
<WindchillHome>/loadXMLFiles/DemoReports.xml -CONT_PATH /

Report Generation 1541


Note that if these objects were already loaded, exceptions may occur when
running this command. The PartList ReportTemplate object is a simple query for
Parts that returns two columns with part number information. It will be created at
the Site context and will be available in Cognos after executing the update model
operation.

Related Customization Topics


• Reporting Info*Engine Task Data Source Customization on page 1524
• Cognos Presentation Customization on page 1518

Related Package/Class Javadoc


• Foundation module
○ wt.query.qml
○ Reporting module
• Reporting module
○ com.ptc.windchill.enterprise.report

Other Related Windchill Documentation


• Report Management online help (Prerequisite)
• Query Builder online help (Prerequisite)
• Windchill Specialized Administration Guide

Related Websites
• http://www.ibm.com/cognos/support

1542 Customization Guide


Reporting Input Page Customization
Objective
You want to provide a parameter input page for the reports in your Windchill
Business Reporting (WBR) system.

Background
The Windchill Business Reporting (WBR) solution supports reports with
parameters. Both Windchill and Cognos viewers provide a basic input page that is
presented to users to gather parameter values when the report is executed. Often
times this input page requires customization for a better end user experience.
There are two basic approaches for customizing input pages, use a standard
Windchill Java Server Page (JSP) or use Cognos report functionality. The
Windchill JSP approach can be used from the Windchill or Cognos viewers. The
Cognos approach can only be used with the Cognos viewer.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/Cognos/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
Assume you have access to the Windchill server JSP directory,
<WindchillHome>/codebase/wtcore/jsp, to create the JSP input page
<MyInputPage> in its associated sub-directory <MyInputPagePackage>.
Assume you have access rights to edit an existing Windchill Report object,
<MyReport> in the Site context.

Intended Outcome
The end result of this solution is the use of your custom input when executing a
report.

Solution
Construct and specify a custom input page for reports.

Report Generation 1543


Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Java Server Page (JSP)
• Cognos Report Studio

Solution Elements
Element Type Description
<MyInputPage> JSP File The custom JSP page for specifying report
input parameter values.
<MyReport> Windchill Object The Windchill object that is displayed to
Windchill Report end users in the Windchill User Interface. It
acts as a proxy to a corresponding Cognos
Report object.

Procedure – Specifying a Windchill JSP Input Page


1. Create a Windchill JSP page, <WindchillHome>/codebase/wtcore/jsp/
<MyInputPagePackage>/<MyInputPage>.jsp.
The JSP specified an input field for “param1” with default value “default1”
and a pre-specified value, “value2” that is passed as a hidden input field for
“param2”. This contrived example does not do any meaningful programmatic
manipulation of the parameters, input fields, or values. It only demonstrates
the basic mechanism for specifying parameters to a report. The details of JSP
syntax and programming are beyond the scope of this document.
<%@page contentType="text/html"
%><%@page pageEncoding="UTF-8"

%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"


%><%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"

%><fmt:requestEncoding value="UTF-8"
/>

<html>
<head>
<title>My Input Page</title>
</head>
<body>
<h2>My Input Page</h2>
<form>

1544 Customization Guide


<%
String paramName = “param1”;
String defaultInputValue = “default1”;
%>
Name: <input type="text" name="<c:out value='<%=paramName%>'/>"
value="<c:out value='<%=defaultInputValue%>'/>" size="60"/><br
/>
<blockquote><input type="submit" value='Execute
Report'/></blockquote>

<%
String hiddenParamName = “param2”;
String hiddenValue = “value2”;
%>

<input type="hidden" name="<c:out


value='<%=hiddenParamName%>'/>" value="<c:out
value='<%=hidenValue%>'/>"/>

%>
</form>
</body>
</html>

2. Update <MyReport> to specify the input page. Navigate to the Windchill “Site
> Reports” page, select the edit action for <MyReport>.
3. Enter “wtcore/jsp/<MyInputPagePackage>/<MyInputPage>.jsp” into the
“Input Page” text field and click “OK”.
4. Verify the report in Windchill. Navigate to the “Home > Reports” page and
Select the “View Report” action for the <MyReport> object.

Procedure – Specify a Cognos Input Page


As a third party reporting tool, Cognos is designed for authoring reports and input
pages. Refer to the Cognos documentation for complete details.

Customization Points

Procedure – Specifying Optional Parameters


Cognos reports that use Windchill Data Sources require every parameter value to
be specified. However, a report can be more useful, if the user can optionally
leave parameter values unspecified and the report ignores the related criteria or

Report Generation 1545


implicitly uses a suitable default. To achieve this behavior, it is possible to pass a
parameter value consisting of a single space (“ “) and by making a single space
the default value for the parameter in you input page, the user will not be required
to enter anything into the parameter input field. When using this technique, you
must ensure that the underlying Data Source will be able to properly handle the
empty space values that are passed.

Procedure – Populating Cognos Components Using Data


Sources
Cognos input pages can use Windchill Data Sources to populate components. For
example, a list of Windchill Products could be displayed in a picker component.
When this component is populated, it would dynamically retrieve Products from
Windchill and show their display names. When the user selects the display name,
the internal Windchill object ID can be passed as a parameter value input to the
report.

Procedure – Specifying Extra Parameters


By default, only the Data Source parameters are included in the Cognos request
from Windchill. This means that any hidden form fields that might otherwise seem
like request parameters are stripped off from the http request sent to Cognos (via a
HTTP redirect). However, additional parameters can be explicitly added by
including a parameter named “extraReportParameters” which specifies a list of
parameter names that will be included in the Cognos request. Assume you want to
pass a parameter with name, “paramA” with value “valueA” that is not in the list
of parameters for the report’s Data Source. The following is an example for
specifying this.
type="hidden" name="paramA" value="valueA"/>
type="hidden" name="extraReportParameters" value="paramA"/>

Data Source
Also data source parameters can be excluded using the usual "parametersToOmit"
request attribute. Note, this is a servlet request object attribute list not a parameter
list. it was chosen for simplicity and ease of use.

Procedure – Specifying Parameters To Omit


By default, only the Data Source parameters are included in the Cognos request
from Windchill. However, parameters can be explicitly excluded using the
"parametersToOmit" request attribute. Note, this is a servlet request object
attribute list. Assume you want to omit the parameter with name, “param1” that is
in the list of parameters for the report’s Data Source. The following is an example
for specifying this.
<%

1546 Customization Guide


request.setAttribute("parametersToOmit",
Arrays.asList("param1"));
%>

Limitations
None.

Sample Code

Examples of Usage in Windchill Code


All of the out-of-the-box reports use Windchill JSP input pages.

Related Websites
• http://www.ibm.com/cognos/support

Report Generation 1547


Report Localization Customization
Objective
You want to provide localized versions of your custom reports in your Windchill
Business Reporting (WBR) system.

Background
The Windchill Business Reporting (WBR) solution uses Windchill and Cognos
objects. There are both Data Source and Report objects that contain text that can
be localized. Localizing the text in these objects allows the text to be displayed in
the client's locale.

Scope/Applicability/Assumptions
This documentation assumes that the Windchill Business Reporting (WBR)
solution (i.e. Cognos) has been successfully installed and configured. The
Windchill instance name is referred to as <WindchillInstanceName>. The Cognos
root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is
installed on <WBRHost>, then the <WBRHomeURL> would be http://
<WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to
<WBRHomeURL> and you have sufficient Cognos privileges to view Windchill
Data Source objects and create reports.
• Assume you have access to create files in the source directory associated with
<MyPackage> in <WindchillHome>.
• Assume you have created an Info*Engine task <MyTask> in its associated
sub-directory <MyTaskPackage> in <WindchillHome>.
• Assume you have created the ReportTemplate, <MyReportTemplate> in the
Site context of <WindchillHome>.
• Assume you have created a Windchill Report object, <MyReport> in the Site
context.
• Assume you have created a Cognos Report, <MyCognosReport> in the
Windchill folder.
For WBR integration, you must also have access rights to update the reporting
meta model.
This document describes procedures for using standard Java resource bundles to
externalize text used in the WBR system. To support localized text, a language
specific resource bundle must be created and the text translated to the appropriate
language. It is assumed that you require support for more than one language and
you have the ability to translate text to your supported languages.

1548 Customization Guide


The text elements that are referred to in this document consist of report names,
parameters, and columns. The actual data displayed in WBR reports is returned
from Data Sources. Localizing this data is not covered in this document.

Intended Outcome
The end result of this solution is the use of your WBR reports in more the one
language based on the client locale.

Solution
External localized text to Java resource bundles that can be translated to support a
specific client locale.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Info*Engine User's Guide
• JConsole User Interface
• Cognos User Interface
• Report Management User Interface

Solution Elements
Element Type Description
<MyTask> Info*Engine Task The Info*Engine task for
retrieving and
manipulating Windchill
data.
<MyTaskResource> Resource Bundle Info The resource bundle info
Properties File file used to localize
Info*Engine task text
items.
<MyReportTemplate> Windchill Object The Windchill object that
Windchill specifies a query for
ReportTemplate retrieving Windchill data.
<MyReportTemplateReso Resource Bundle Info The resource bundle info
urce> Properties File file used to localize
ReportTemplate text
items.
<MyReport> Windchill Windchill Object The Windchill object that
Report is displayed to end users
in the Windchill User

Report Generation 1549


Interface. It acts as a
proxy to a corresponding
Cognos Report object.
<MyReportResource> Resource Bundle Info The resource bundle info
Properties File file used to localize
Report text items.
<MyCognosReport> Cognos Object The Cognos object for a
Cognos Report report that contains the
definition of the query
and specifies the
presentation formatting.
<MyCognosReportResour Resource Bundle Info The resource bundle info
ce> Properties File file used to localize
Cognos Report static text.

Procedure - Localizing an Info*Engine Task Data Source


1. Create the file, <WindchillHome>/src/<MyPackage>/<MyTaskResource>.
rbInfo. Add entries, as necessary, for the task method name, parameter names,
and column names. Create language specific versions of <MyTaskResource>.
rbInfo and generate the associated java source and compiled class files.
2. Edit the task XML file, <WindchillHome>/tasks/<MyTaskPackage>/
<MyTask>.xml to specify the resource bundle. The following line should be
added to the task comments.
{resouceBundle: <MyPackage>.<MyTaskResource> }

3. Update the Cognos model to incorporate the localized text. Launch JConsole
from installed Windchill shortcuts. Connect to the Embedded Servlet Engine
(based on Tomcat) JVM instance. Select reporting management bean from the
MBeans tab, “com.ptc > Monitors > ReportingSystem”. From the Operations
tab, click "updateModel".

Procedure - Localizing a ReportTemplate Data Source


1. Create the file, <WindchillHome>/src/<MyPackage>/
<MyReportTemplateResource>.rbInfo. Add entries, as necessary, for the task
method name, parameter names, and column names. Create language specific
versions of <MyReportTemplateResource>.rbInfo and generate the associated
java source and compiled class files.
2. Update <MyReportTemplate> to specify the resource bundle. Navigate to the
Windchill Site ▶ Utilities and launch the Report Management utility. From the
Report Management UI, select <MyReportTemplate>, and click "Update"

1550 Customization Guide


to launch Query Builder. Select the Report ▶ Properties menu item and enter
<MyPackage>.<MyReportTemplateResource> into the "Resource
Bundle" text field. Click "OK" and save the changes.
3. Update the Cognos model to incorporate the localized text. Launch JConsole
from installed Windchill shortcuts. Connect to the Embedded Servlet Engine
(based on Tomcat) JVM instance. Select reporting management bean from the
MBeans tab, “com.ptc > Monitors > ReportingSystem”. From the Operations
tab, click "updateModel".

Procedure - Localizing a Windchill Report Object's Name


1. Create the file, <WindchillHome>/src/<MyPackage>/<MyReport>.rbInfo.
Add an entry for the Report Object's Name. Create language specific versions
of <MyReportResource>.rbInfo and generate the associated java source and
compiled class files.
2. Update <MyReport> to specify the resource bundle. Navigate to the Windchill
"Site > Reports" page, select the edit action for <MyReport>. Enter
"<MyPackage>.<MyReportResource>" into the "Resource Bundle" text field
and click "OK".
3. Verify the Report attribute "localizedName" is the translated text based on the
client locale.

Procedure - Localizing a Cognos Report


1. Once the Cognos meta model is localized (see Procedure - Localizing an
Info*Engine Task Data Source on page 1550 and Procedure - Localizing a
ReportTemplate Data Source on page 1550), there is only a single step
required to localize the report's name, parameters, and columns. The Report
Studio locale must be set to "en_ZW" before authoring a report.
2. Verify the report name, parameters, and columns is the translated text based on
the client locale when the report is executed. Use the "Run with options…"
action to run the report.

Report Generation 1551


Customization Points

Procedure - Localizing Cognos Report Static Text


When the above Procedure - Localizing a Cognos Report on page 1551 is
followed all report parameter and column names are automatically localized based
on the Data Source meta-model information. Any additional text added to a report
such as banners or labels is not automatically localized. This can be accomplished
using Windchill utilities.
1. Add the static text fields to <MyCognosReport>.
2. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/
<MyCognosReportXML>.xml based on an <MyCognosReport>t. Use Cognos
Report Studio menu item "Tools > Copy Report to Clipboard" to copy the
XML definition to the system clipboard. Then, paste the clipboard contents
into a text editor and save it to file.
3. Generate the base resource bundle file, <WindchillHome>/src/<MyPackage>/
<MyCognosReportResource>.rbinfo using the CongosProxy utility.
windchill com.ptc.windchill.cognos.CognosProxy outputrbinfo
<WindchillHome>/loadFiles/cognosReports/custom/<MyCognosReportX
ML>.xml
<WindchillHome>/src/<MyPackage>/<MyCognosReportResource>.rbinfo
4. Create language specific versions of <MyCognosReportResource>.rbInfo and
generate the associated java source and compiled class files.
5. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/
<MyCognosReportAttributes>.properties. The base names from this and step 2
must match exactly (e.g. MyCognosReport.xml and MyCognosReport.
properties.
type=report
defaultName=<MyCognosReport>
resourceBundle=<MyPackage>/<MyCognosReportResource>.rbinfo
6. Load <MyCognosReport> using the following command.
windchill com.ptc.windchill.cognos.CognosProxy loadreports
<WindchillHome>/loadFiles/cognosReports/custom/<MyCognosReportA
ttributes>.properties
7. Verify the report in Cognos. Refresh the "Public Folders > Windchill" folder
and the <MyCognosReport> object should be listed. Use the "Run with
options…" action to run the report. Try setting different client locales to
ensure that the static text is translated properly.

1552 Customization Guide


Limitations
To localize a Cognos report, the Report Studio locale must be set to "en_ZW"
before authoring a report. Cognos reports reference localized data source and
column names based on the Report Studio locale. Any change to these data source
and column names for this locale will result in not being able to look up the
translated text in another locale. The official workaround recommended by
Cognos is to use non-volatile names in a special locale. This special locale is "en_
ZW".

Sample Code

Examples of Usage in Windchill Code


All out-of-the-box reports are localized for all Windchill supported locales.

Related Packages/Class Javadoc


• Foundation modulue
wt.query.template
• Reporting module
com.ptc.windchill

Related Customization Documentation


• Internationalization and Localization on page 2063

Other Related Windchill Documentation


• Info*Engine User's Guide
• Info*Engine Implementation Guide
• Windchill Specialized Administration Guide
• Report Management online help

Related Websites
• http://support.congos.com/support

Report Generation 1553


Report Selection List Customization
• PSB Ribbon Customization on page 1554
• Right Click Menu Customization on page 1562

PSB Ribbon Customization


You can add custom reports to the PSB ribbon toolbar under the “Reports” menu.
• This applies only to the “Reports” menu of the Part information page,
Structure tab (PSB); it is not supported in other structures.
• There is a maximum of 25 custom reports possible
• The custom reports must be added to the end of the existing OOTB reports
○ there is no ability to insert custom reports within the list of OOTB reports
○ there is no ability to re-order the existing OOTB reports
• It is possible to hide the OOTB reports and only display the custom reports

Customization Steps
1. Create resource bundle Java file. For example:
a. Create a <Windchill>\src\com\customReports\psb\
directory and create a file named psbCustomActionsRB.java (see
example source code below).
b. In a Windchill shell, go to <Windchill>\src directory and compile
the java file (replace <Windchill> as appropriate):
javac -cp <Windchill>\codebase;<Windchill>\
codebase\WEB-INF\lib\*;<Windchill>\lib\* com\
customReports\psb\psbActionsRB.java -d <Windchill>\
codebase
For example:
javac -cp C:\ptc\Windchill\codebase;C:\ptc\
Windchill\codebase\WEB-INF\lib\*;C:\ptc\Windchill\
lib\* com\customReports\psb\psbActionsRB.java -d
C:\ptc\Windchill\codebase
This will compile the RB info file to the <Windchill>\codebase\
com\customReports\psb directory.

1554 Customization Guide


Note
For more information on resource bundles see Resource Info (.rbInfo)
Files on page 2071.

2. Add action definition entries to <Windchill>\codebase\config\


actions\custom-actions.xml (see example source code below).
a. The url parameter for each action must be changed to point to the custom
report url.
b. Note: the resourceBundle specified in the <objecttype name=
"psb" resourceBundle="com.
customReports.psb.psbActionsRB"> element must match the
java class name of the resource bundle created in step 1 above.
3. Add the action model definition to <Windchill>\codebase\config\
actions\custom-actionModels.xml (see example source code
below).
a. Note: this is overriding the toolbar action model definition for the PSB
found in <Windchill>\codebase\config\actions\psb-
actionModels.xml. If other patches are installed that modify psb-
actionModels.xml, those changes must be merged into the custom-
actionModels.xml file.
b. Uncomment the number of custom reports needed in the section
highlighted in yellow.
c. The “separator” entries are optional and can be placed between any of the
custom report entries.
d. Do not change the name of the actions.
e. OOTB report entries can be commented out

Sample Code : psbCustomActionsRB.java

Note
Sample code for custom reports 02 through 25 removed for readability.

package com.customReports.psb;

import wt.util.resource.RBComment;
import wt.util.resource.RBEntry;
import wt.util.resource.RBPseudo;

Report Generation 1555


import wt.util.resource.RBUUID;
import wt.util.resource.WTListResourceBundle;

@RBUUID("com.customReports.psb.psbCustomActionsRB")
public final class psbCustomActionsRB extends WTListResourceBundle {

/********
* Custom Report 01
*/
@RBEntry("Custom Report 01 Description")
// this is what is displayed in the menu
public static final String PSB_CUSTOMREPORTGWT01_DESCRIPTION
= "psb.psbCustomReportGWT01.description";

@RBEntry("Custom Report 01")


// not used, but is here for completeness in case used in the future
public static final String PSB_CUSTOMREPORTGWT01_TITLE
= "psb.psbCustomReportGWT01.title";

@RBEntry("Custom Report 01 Tooltip")


// not used, but is here for completeness in case used in the future
public static final String PSB_CUSTOMREPORTGWT01_TOOLTIP
= "psb.psbCustomReportGWT01.tooltip";

@RBEntry("height=900,width=1000")
// specifies the size in pixels of the report window
@RBPseudo(false)
@RBComment("DO NOT TRANSLATE")
public static final String PSB_CUSTOMREPORTGWT01_MOREURLINFO
= "psb.psbCustomReportGWT01.moreurlinfo";

@RBEntry("report_view.png")
// the name of the icon file, as found in <Windchill>/netmarkets/images
@RBPseudo(false)
@RBComment("DO NOT TRANSLATE")
public static final String PSB_CUSTOMREPORTGWT01_ICON
= "psb.psbCustomReportGWT01.icon";

[ Sample code for custom reports 02 through 25 removed for readability ]

} // end class
package com.customReports.psb;

import wt.util.resource.RBComment;
import wt.util.resource.RBEntry;
import wt.util.resource.RBPseudo;
import wt.util.resource.RBUUID;
import wt.util.resource.WTListResourceBundle;

1556 Customization Guide


@RBUUID("com.customReports.psb.psbCustomActionsRB")
public final class psbCustomActionsRB extends WTListResourceBundle {

/********
* Custom Report 01
*/
@RBEntry("Custom Report 01 Description")
// this is what is displayed in the menu
public static final String PSB_CUSTOMREPORTGWT01_DESCRIPTION
= "psb.psbCustomReportGWT01.description";

@RBEntry("Custom Report 01")


// not used, but is here for completeness in case used in the future
public static final String PSB_CUSTOMREPORTGWT01_TITLE
= "psb.psbCustomReportGWT01.title";

@RBEntry("Custom Report 01 Tooltip")


// not used, but is here for completeness in case used in the future
public static final String PSB_CUSTOMREPORTGWT01_TOOLTIP
= "psb.psbCustomReportGWT01.tooltip";

@RBEntry("height=900,width=1000")
// specifies the size in pixels of the report window
@RBPseudo(false)
@RBComment("DO NOT TRANSLATE")
public static final String PSB_CUSTOMREPORTGWT01_MOREURLINFO
= "psb.psbCustomReportGWT01.moreurlinfo";

@RBEntry("report_view.png")
// the name of the icon file, as found in <Windchill>/netmarkets/images
@RBPseudo(false)
@RBComment("DO NOT TRANSLATE")
public static final String PSB_CUSTOMREPORTGWT01_ICON
= "psb.psbCustomReportGWT01.icon";

[ Sample code for custom reports 02 through 25 removed for readability ]

} // end class

Sample Code : custom-actions.xml


Make sure resourceBundle parameter is set correctly with the Java class name of
the resource bundle.

Report Generation 1557


Note
Sample code for custom reports 02 through 25 removed for readability.

<listofactions>

<objecttype name="psb"
resourceBundle="com.customReports.psb.psbCustomActionsRB">

<action name="psbCustomReportGWT01" ajax="component">


<command class="com.ptc.cat.ui.client.action.LaunchURLAction"
method="execute" url="/ptc1/psb/customAction" windowType="popup"/>
<supportedTypes>
<type value="wt.part.WTPart"/>
<type value="wt.part.WTPartUsageLink"/>
<type value="wt.part.PartUsesOccurrence"/>
<type value="wt.part.RTPartPathOccurrence"/>
</supportedTypes>
</action>

[ Sample code for custom reports 02 through 25 removed for readability ]

</objecttype>

</listofactions>

Sample Code : custom-actionModels.xml


Uncomment the number of custom reports needed in the section highlighted
below in yellow. The “separator” entries are optional and can be placed between
any of the custom report entries. Do not change the name of the actions.

Note
Uncomment the number of custom reports needed in the section of code with
the psbCustomReportGWT action names.

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE actionmodels SYSTEM "actionmodels.dtd">
<actionmodels>

<model name="psbRelatedPartsTreeToolBar">
<action name="editingGroupGWT" type="psb" />
<action name="insertExistingPartStructureGWT" type="psb" />
<action name="removeGWT" type="psb" />
<action name="insertNewPartStructureSplitGWT" type="psb" />
<action name="insertNewPartStructureGWT" type="psb" />

1558 Customization Guide


<action name="insertMultiNewPartStructureGWT" type="psb" />
<action name="editSplitGWT" type="psb" />
<action name="editGWT" type="psb" />
<action name="editUsageLinkTreeGWT" type="psb" />
<action name="editCommonAttrsGWT" type="psb" />
<action name="separator" type="separator" />
<action name="renameGWT" type="psb" />
<action name="createOccurrencesGWT" type="psb" />

<action name="checkInOutGroupGWT" type="psb" />


<action name="checkoutGWT" type="psb" />
<action name="undocheckoutGWT" type="psb" />
<action name="checkinGWT" type="psb" />
<action name="findCheckoutItemsGWT" type="psb" />

<action name="clipboardGroupGWT" type="psb" />


<action name="pasteFromClipboardToTreeWithLargeIconGWT" type="psb" />
<action name="copyToWindchillWithLargeIconGWT" type="cat" />
<action name="pasteFromClipboardToTreeGWT" type="psb" />
<action name="pasteSelectToTreeGWT" type="psb" />

<action name="viewingGroupGWT" type="psb" />


<action name="relatedObjectsWithLargeIconGWT" type="psb" />
<action name="configurableTableViewGWT" type="cat" />
<action name="configurableTableViewListGWT" type="cat" />
<action name="separator" type="separator" />
<action name="saveStructureViewGWT" type="cat" />
<action name="configurableTableViewManagerGWT" type="cat" />
<action name="separator" type="cat" />
<action name="sourcingContextGWT" type="psb" />
<action name="sourcingContextListGWT" type="psb" />
<action name="separator" type="cat" />
<action name="findSourcingContextGWT" type="psb" />
<action name="displayGWT" type="cat" />
<action name="displayOccurrencesGWT" type="psb" />
<action name="separator" type="separator" />
<action name="selectAllGWT" type="cat" />
<action name="separator" type="separator" />
<action name="expandAllLevelsFromRootGWT" type="cat" />
<action name="psbExpandSubmenuGWT" type="psb" />
<action name="expandOneLevelGWT" type="cat" />
<action name="expandTwoLevelsGWT" type="cat" />
<action name="expandThreeLevelsGWT" type="cat" />
<action name="expandFourLevelsGWT" type="cat" />
<action name="expandFiveLevelsGWT" type="cat" />
<action name="separator" type="separator" />
<action name="expandAllSelectedLevelsGWT" type="cat" />
<action name="expandNLevelsGWT" type="cat" />
<action name="collapseAllLevelsGWT" type="cat" />
<action name="psbEndExpandSubmenuGWT" type="psb" />
<action name="separator" type="separator" />

Report Generation 1559


<action name="viewLayout2Panel" type="cat" />
<action name="viewLayout3Panel" type="cat" />
<action name="separator" type="separator" />
<action name="refreshGWT" type="cat" />

<action name="newAddToGroupGWT" type="psb" />


<action name="newActionsGWT" type="psb" />
<action name="saveAsGWT" type="psb" />
<action name="separator" type="separator" />
<action name="newPromotionRequestTreeGWT" type="psb" />
<action name="newPartConfigGWT" type="psb" />
<action name="newRepresentationTreeGWT" type="psb" />
<action name="newPARGWT" type="psb"/>
<action name="addToActionsGWT" type="psb" />
<action name="addToBaselineGWT" type="cat" />
<action name="addToPackageGWT" type="cat" />
<action name="SBAddToPrj" type="cat" />

<action name="filterGroupGWT" type="ec" />


<action name="editFilterWithLargeIconGWT" type="ec" />
<action name="filterPropertiesGWT" type="ec" />
<action name="savedFiltersGWT" type="ec" />

<action name="toolsGroupGWT" type="psb" />


<action name="compareActionsGWT" type="psb" />
<action name="launchStructureCompareGWT" type="psb" />
<action name="launchCompareToCADGWT" type="dsv" />
<action name="openActionsGWT" type="psb" />
<action name="openInProductViewGWT" type="psb" />
<action name="openInPSEGWT" type="psb" />
<action name="openInMPSEGWT" type="psb" />
<action name="openInSPSEGWT" type="psb" />

<action name="psbReportsGroupGWT" type="psb" />


<action name="psbReportsGWT" type="psb" />
<action name="psbReportMultiLevelCompListGWT" type="psb" />
<action name="separator" type="separator" />
<action name="psbReportSingleLevelConsolBOMGWT" type="psb" />
<action name="psbReportSingleLevelBOMGWT" type="psb" />
<action name="psbReportSingleLevelBOMWithNotesGWT" type="psb" />
<action name="separator" type="separator" />
<action name="psbReportMultiLevelBOMGWT" type="psb" />
<action name="psbReportMultiLevelBOMWithReplacementsGWT" type="psb" />
<action name="psbReportMultiLevelBOMWithAMLAVLGWT" type="psb" />
<action name="psbReportMultiLevelBOMWithAMLGWT" type="psb" />
<action name="separator" type="separator" />
<action name="singleSourceOEMPartsGWT" type="psb" />
<action name="uniqueManufacturerPartsGWT" type="psb" />
<action name="separator" type="separator" />
<action name="changeBaselineReportGWT" type="change" />

1560 Customization Guide


<!--<action name="separator" type="separator" />
<action name="psbCustomReportGWT01" type="psb" />
<action name="psbCustomReportGWT02" type="psb" />
<action name="psbCustomReportGWT03" type="psb" />
<action name="psbCustomReportGWT04" type="psb" />
<action name="psbCustomReportGWT05" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT06" type="psb" />
<action name="psbCustomReportGWT07" type="psb" />
<action name="psbCustomReportGWT08" type="psb" />
<action name="psbCustomReportGWT09" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT10" type="psb" />
<action name="psbCustomReportGWT11" type="psb" />
<action name="psbCustomReportGWT12" type="psb" />
<action name="psbCustomReportGWT13" type="psb" />
<action name="psbCustomReportGWT14" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT15" type="psb" />
<action name="psbCustomReportGWT16" type="psb" />
<action name="psbCustomReportGWT17" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT18" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT19" type="psb" />
<action name="psbCustomReportGWT20" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT21" type="psb" />
<action name="psbCustomReportGWT22" type="psb" />
<action name="psbCustomReportGWT23" type="psb" />
<action name="psbCustomReportGWT24" type="psb" />
<action name="separator" type="separator" />
<action name="psbCustomReportGWT25" type="psb" />-->

<action name="exportActionsGWT" type="cat"/>


<action name="exportCsvGWT" type="cat" />
<action name="exportHtmlGWT" type="cat" />
<action name="exportPdfGWT" type="cat" />
<action name="exportTextGWT" type="cat" />
<action name="exportXlsGWT" type="cat" />
<action name="exportXlsxGWT" type="cat" />
<action name="exportXlsReportGWT" type="cat" />
<action name="exportXmlGWT" type="cat" />
</model>

</actionmodels>

Report Generation 1561


Right Click Menu Customization
However, it is possible to add a menu item to the right-click context menus in the
structure that can launch actions or other jsp pages (e.g., reports). There is an
example action that can be used as a basis for creating custom actions or reports.
Perform the following steps see the example action.
1. There is an example jsp file installed in the following location:
<Windchill>/codebase/netmarkets/jsp/part/custom/
customAction.jsp.
2. In <Windchill>/codebase/config/actions/psb-
actionmodels.xml, find the psbRelatedPartsTreeContextMenu
model and uncomment the "customActionGWT" action by removing the
<!-- and --> delimiters.
<model name="psbRelatedPartsTreeContextMenu">
...<snip>...
<!-- <action name="customActionGWT" type="psb"/> -->
</model>

The customActionGWT is defined in the <Windchill>/codebase/


config/actions/psb-actions.xml file:
<action name="customActionGWT" ajax="component">
<command class="com.ptc.cat.ui.client.action.LaunchURLAction"
method="execute" url="/ptc1/psb/customAction" windowType="popup"/>
<supportedTypes>
<type value="wt.part.WTPart" />
<type value="wt.part.WTPartUsageLink" />
<type value="wt.part.PartUsesOccurrence" />
<type value="wt.part.RTPartPathOccurrence" />
</supportedTypes>
</action>

3. Restart the MethodServer and navigate to the Structure tab of a Part


information page.
4. Right-click on any part in the structure and select Custom Action in the menu.
This launches a window as defined by customAction.jsp.
5. To create custom actions or report, define the action in the appropriate
*-actions.xml file (e.g., psb-actions.xml) using the
customActionGWT as an example.

1562 Customization Guide


• Change the name of the action, the url parameter and supportedTypes
as needed.
• Add the resourceBundle parameter to specify the file that contains the
label of the action (see “Resource Info (.rbInfo) Files” section).
• Then update the model definition in the appropriate
*-actionmodels.xml file to include the action defined.

Report Generation 1563


36
Packages Customization
Package Type-Based Properties ............................................................................ 1566
Identifying Users in Context Replication and Activating Replicated Users .................. 1580
Select Files – Copy Forward Exclusion Decisions .................................................... 1594
Windchill Replication Package Command Line Sample Scripts ................................. 1597

This section contains information on customizing packages.

1565
Package Type-Based Properties
Package type-based properties are a new feature in the Windchill 10.0 release that
allows customization properties to be assigned to Package objects by class type or
subtype. These properties differ from those typically set in wt.properties,
and from preferences set in the Preference Manager, in that different types of
Package objects may have different settings for the same property. For example,
the EnableContentControl property may be set to “false” for Package types
while simultaneously being set to “true” for TechnicalDataPackage types.
Package type-based properties are intended only for site-level and organization-
level customization, and can only be changed by the Windchill site administrator.

Type-Based Properties XML File


Type-based properties are configurable and customizable by loading an XML file
that describes the property sets. The following is a sample customized type-based
properties XML file:
<?xml version="1.0" encoding="utf-8"?>
<WPTypeBasedProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="WPTypeBasedProperties.xsd">

<WPTypePropertySet name="Default">
<WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage">
<EnableContentControl>false</EnableContentControl>
<CollectorId>CreateWPBaseline</CollectorId>
<IncludedManifestOptions>
<ManifestOption default="true">Interactive</ManifestOption>
</IncludedManifestOptions>
<IncludedDeliveryOptions>
<DeliveryOption>Full</DeliveryOption>
<DeliveryOption>Incremental</DeliveryOption>
</IncludedDeliveryOptions>
</WPTypeProperties>

<WPTypeProperties typeId="com.ptc.windchill.wp.tdp.TechnicalDataPackage">
.
. </WPTypeProperties>
</WPTypePropertySet>

<WPTypePropertySet name="My Customized Set">


<WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage">
.
.
.
</WPTypePropertySet>

</WPTypeBasedProperties>

1566 Customization Guide


A type-based property consists of a <WPTypeBasedProperties> root
element that contains one or more <WPTypePropertySet> elements. In turn,
each <WPTypePropertySet> element contains one or more
<WPTypePropertySet> elements. And finally, each
<WPTypeProperties> element contains one or more elements to set specific
properties. Note that within a single <WPTypeProperties> element a specific
property, such as <IncludedDeliveryOptions>, may only be given once.

Reading and Loading Type-Based Properties XML


File
Type-based property sets are created and modified by loading an XML file that
describes these sets (see sample in Type-Based Properties XML File on page
1566). This XML file can reside anywhere as long as the location is specified to
the loader.
The loader is invoked from a Windchill shell while the Method Server is running:
java com.ptc.windchill.wp.WPTypeBasedPropertiesLoader
-load <XML file>

Note
The loader prompts for the site administrator user-id and password to perform
this operation.

For convenience, the loader can be used to create an XML file that describes the
current type-based property sets in the system or to recreate the default property
set from the initial install. The newly created XML file can then be modified and
loaded as described above.
To retrieve the currently loaded sets, execute the loader from a Windchill shell
while the Method Server is running as:
java com.ptc.windchill.wp.WPTypeBasedPropertiesLoader
-read <XML file>
To retrieve the OOTB default set from the initial installation, execute the loader
from a Windchill shell while the Method Server is running as:
java com.ptc.windchill.wp.WPTypeBasedPropertiesLoader
-read <XML file> -default

Packages Customization 1567


Property Sets
A property set allows for a specific configuration of package types. For example,
in one set, traditional Packages (WorkPackage type) can be configured to only
allow for the creation of Interactive manifests (offline view) deliveries; while
Technical Data Packages can be configured to only allow for Static manifests.
Another set may define that Interactive and Static manifests are valid for both
types of packages.
Multiple sets can be defined in the system, but how the system behaves depends
on the current active property set. The active set is selected from the Packages
“Property Set” preference. Property sets are named by specifying a non-blank
“name” attribute in the XML file. For example:
<WPTypePropertySet name="My Customized Set">
This XML element defines a new property set named “My Customized Set”,
which can be selected from a list when changing the Packages “Property Set”
value in the Preference Manager.
A property set named “Default” is available, even if it is not defined in the type-
based properties XML file. In this case the “Default” properties set specifies
OOTB system default values.
An active set can be defined at the site level or at the organization level; hence,
one set may be the active one at one organization while a different organization
may have a different active set.

Type-Based Property Descriptions


The following sections describe various property settings (see example in Type-
Based Properties XML File on page 1566).
Properties are given as XML elements that are located within
<WPTypeProperties> elements for each package type. For example, the
following defines property values that are used for packages of type
com.ptc.windchill.wp.WorkPackage, and all of its sub-types and soft-
types.
<WPTypeBasedProperties ...>
<WPTypePropertySet name="My Customized Set">
<WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage">
:
(Type-based properties for com.ptc.windchill.wp.WorkPackage)
:
</WPTypeProperties>
</WPTypePropertySet>
</WPTypeBasedProperties>

1568 Customization Guide


If different property values are required for a sub-type or soft-type, then additional
<WPTypeProperties> elements can be added. For example, the following
defines one set of property values for packages of type
com.ptc.windchill.wp.WorkPackage, and a different set of property
values for the soft-type com.ptc.windchill.wp.WorkPackage|com.MyCompany.
MyPackage.
<WPTypeBasedProperties ...>
<WPTypePropertySet name="My Customized Set">
< WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage">
:
(Type-based properties for com.ptc.windchill.wp.WorkPackage)
:

</WPTypeProperties>
<WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage|com.MyCompany.MyPackage">
:
(Properties for com.ptc.windchill.wp.WorkPackage|com.MyCompany.MyPackage)
:

</WPTypeProperties>
</WPTypePropertySet>
</WPTypeBasedProperties>

The actual property value used for any specific package type is taken from the
most specific type defined in the XML file. If the exact package type cannot be
found in the XML file, then the file is re-examined for a parent type. This process
continues up the type hierarchy until either an exact type match is found, or the
root package type com.ptc.windchill.wp.AbstractWorkPackage is
reached. If the root type is reached, then the system default property values are
used (see Reading and Loading Type-Based Properties XML File on page 1567
for obtaining an XML file with system default values). Note that custom property
values cannot be set for the root package type.
The following sections describe each specific property that can be set. Single-
valued properties are specified by a single XML element, and multi-valued
properties are specified by an outer XML element with one or more inner XML
elements. All of the properties describe in the following sections are optional. If a
property value is not specified for a specific type of package, then the value from
its parent type is used.

EnableContentControl
The EnableContentControl property is used to enable or disable content
control processing. For more information, see . See the File Table topic in the
Windchill Help Center for more information.

Packages Customization 1569


The following tag enables content control processing for this package type:
<EnableContentControl>true</EnableContentControl>

Default value: false

CollectorId
The CollectorId property controls which collection component instance to
use when the “Configure…” link is selected from the “Add to Package” window.
For example:
<CollectorId>MyCustomCollectorId</CollectorId>

Default value: CreateWPBaseline

ExcludedSeedTypes
The ExcludedSeedTypes property controls object types that cannot be added
as seeds to a package. Object types specified in this property cannot be pasted into
the “Initially Selected Objects” table in the “Add to Package” window. They are
not returned in the “Search Results” table when searching for initially selected
objects.
For example, the following excludes objects of type WTDocument and part soft-
type com.MyCompany.MyCustomPart from being added to the “Initially
Selected Objects” table.
<ExcludedSeedTypes>
<SeedType>wt.part.WTPart|com.MyCompany.MyCustomPart</SeedType>
<SeedType>wt.doc.WTDocument</SeedType>
</ExcludedSeedTypes>

Default value: none – no object types are excluded and the full range of package
seed types is available

IncludedContentRoles
The IncludedContentRoles property controls which types of content files
associated with a package object are added to an exported zip file (created using
the “Zip for Delivery” action). Content files associated to a package by the WP_
EXP_SECONDARY content role are always added, regardless of the values given
for this property.
For example, the following specifies that in addition to content files associated by
role WP_EXP_SECONDARY, an export file contains content files associated with
the package object by roles MyCustomContentRole and SECONDARY:
<IncludedContentRoles>
<ContentRoleKey>MyCustomContentRole</ContentRoleKey>
<ContentRoleKey>SECONDARY</ContentRoleKey>
</IncludedContentRoles>

1570 Customization Guide


The value in the <ContentRoleKey> element must be a key defined in class
wt.content.ContentRoleType. It can be a key for either a custom role or
an OOTB role.
Default value: none – only content files associated to a package object by the WP_
EXP_SECONDARY role is added to an export file

IncludedDeliveryOptions
The IncludedDeliveryOptions property controls which delivery options
are presented in the “Zip Package for Delivery” window. The valid delivery
options are:
• Full – displays option “Provide complete delivery”. If selected, an exported
zip file contains all the package contents that are accessible to the recipient.
• Incremental – displays option “Provide incremental delivery from”. If
selected, an exported zip file contains only the package contents that are
accessible to the recipient, and were not included in the base delivery.
• Incremental manifest – displays option “Provide complete delivery with
incremental information from”. If selected, an exported zip file contains all the
package contents that are accessible to the recipient, similar to the “Full”
option, but also containa a manifest file describing incremental changes
between the base delivery and the new delivery.
Regardless of the options specified, all exported zip files for the first version of a
package uses the “Full” option, and the “Zip Package for Delivery” window does
not display the delivery options.
Also, regardless of the options specified, all exported zip files for any version of a
package uses the “Full” option if this is the first version delivered to a recipient.
For example, the following causes all three delivery options to be displayed for
recipients of earlier package versions:
<IncludeDeliveryOptions>
<DeliveryOption>Full</DeliveryOption>
<DeliveryOption>Incremental</DeliveryOption>
<DeliveryOption>Incremental manifest</DeliveryOption>
</IncludeDeliveryOptions>

If either of the incremental delivery options are selected in the “Zip Package for
Delivery” window, then a base delivery must also be specified. Only earlier
deliveries to the same recipient may be used as a base delivery.
Default values: Full, Incremental

Packages Customization 1571


IncludedManifestOptions
The IncludedManifestOptions property controls which manifest options
are presented in the “Zip Package for Delivery” window. The valid manifest
options are:
• Interactive – displays option “Include offline viewer”. If selected, an exported
zip file contains an offline view of the package and its contents, but does not
contain a manifest file.
• Static – displays option “Include manifest file”. If selected, an exported zip
file contains a manifest file and the content files associated with the package
object and its members. It does not contain an offline view. The manifest is
also associated to the Delivery object as a primary content file. The name of
the manifest file can be controlled using the ManifestFileName property
(see the ManifestFileName section for more information).
• None – displays option “Do not include any manifest”. If selected, an exported
zip file contains the content files associated with a package object and its
members. It does not contain an offline view or a manifest file.
For example, the following causes all three manifest options to be displayed, and
the “Static” option is pre-selected by default.
<IncludedManifestOptions>
<ManifestOption>Interactive</ManifestOption>
<ManifestOption default="true">Static</ManifestOption>
<ManifestOption>None</ManifestOption>
</IncludedManifestOptions>

The “default=true” attribute specifies which option is pre-selected in the


display. If this attribute is not specified, then the first option given in the XML list
is pre-selected.
Default value: Interactive

ManifestFileName
The ManifestFileName property defines the file name to be used when a
static manifest is created during export (see the IncludedManifestOptions
section).
For example, the following would set the manifest file name to MyManifest.txt:
<ManifestFileName>MyManifest.txt</ManifestFileName>
Default value: manifest.txt

1572 Customization Guide


StaticManifestClassOverride
The StaticManifestClassOverride property is used to override the
OOTB Java class used to create a static manifest for an exported zip file (see the
IncludeManifestOptions section for more information). The content and
format of a static manifest file can be customized by creating a new Java class and
setting this property to its fully qualified class name.
A custom Java class for creating a static manifest file has the form:
package com.MyCompany

import java.io.InputStream;
import com.ptc.netmarkets.wp.ixb;
import wt.util.WTException;

class MyStaticManifest extends AbstractStaticManifest {


protected InputStream createManifest(WPZipContent zipContent) throws WTException {
:
(Create custom static manifest file)
:
>
}

For example, the following would specify that custom Java class
com.MyCompany.MyStaticManifest be used to create a static manifest
file:
<StaticManifestClassOverride>
com.MyCompany.MyStaticManifest
</StaticManifestClassOverride>

Default value: com.ptc.netmarkets.wp.ixb.StaticManifest

ExcludedMemberContentRoles
The ExcludedMemberContentRoles property controls which types of
content files associated with package members are excluded from an export file.
Also, when Content Control is enabled (see the EnableContentControl
section for more information) content files for these roles are excluded from
display in the “Select Files” window. For example, the following specifies that
content files associated by roles THUMBNAIL and THUMBNAIL3D is not added to
an export file:
<ExcludedMemberContentRoles>
<ContentRoleKey>THUMBNAIL</ContentRoleKey>
<ContentRoleKey>THUMBNAIL3D</ContentRoleKey>
</ExcludedMemberContentRoles>

Packages Customization 1573


The value in the <ContentRoleKey> element must be a key defined in class
wt.content.ContentRoleType. It can be a key for either a custom role or
an OOTB role.
Default value: None.

RetainCollectionResults
The RetainCollectionResults property controls retention of extended
collection information when creating a new package or modifying an existing
package using the “Add to Package”, “Refresh”, “Save As” (with refresh) and
“Revise” (with refresh) actions. Retaining extended collection information enables
advanced package editing features, such as the “Edit Filters” action.
For example, the following tag enables retention of extended collection
information:
<RetainCollectionResults>true</RetainCollectionResults>

Default value: False.

IncludedDeliveryFormatOptions
The IncludedDeliveryFormatOptions property controls which format
options are presented in the Zip Package for Delivery window.
The valid format options are:
• Non_Importable : Displays the Export Only option. If selected, an
exported zip file only contains an offline view of the package and its contents,
and cannot be imported.
• Windchill_Importable : Displays the Windchill Importable option. If
selected, the exported file is required to be a complete delivery (that is, options
for incremental delivery are disabled), and the exported zip file contains data
allowing it to be imported into another Windchill system.
For example, the following causes the Export Only and Windchill Importable
options to be displayed, with Export Only pre-selected by default.
<IncludedDeliveryFormatOptions>
<DeliveryFormat default="true">Non_Importable</DeliveryFormat>
<DeliveryFormat>Windchill_Importable</DeliveryFormat>
</IncludedDeliveryFormatOptions>
The default=true attribute specifies which option is pre-selected in the
display. If this attribute is not specified, then the first option given in the XML list
is pre-selected.
Default value: Non_Importable

1574 Customization Guide


ExportOnlyContentFileNaming
The ExportOnlyContentFileNaming property controls which content file
renaming scheme is used to eliminate duplicates in an export file. The valid file
renaming options are:
• AppendSequenceID : Appends sequence identifiers to content file names
to eliminate duplicates (for example, “MyContentFile[2].txt”).
Content files are only renamed when duplicates exist. This function is similar
to the renaming scheme used in prior Windchill releases, and does not
guarantee consistent content file names between two or more separate exports.
• PrependIdentity : Prepends the business object identity to content file
names to eliminate duplicates using the following forms:
○ When Display > Expose Organization is set to True, ObjectType -
ObjectNumber, ObjectName, OrganizationID,
Revision.Iteration - Filename (for example, “Document –
000000001, doc_ex, 12345, A.1 - MyContentFile.txt,” where “12345”
identifies the Organization Name, CAGE Code, DUNS Number, or ISO
6523 for the organization).
○ When Display > Expose Organization is set to False, ObjectType -
ObjectNumber, ObjectName, Revision.Iteration -
Filename (for example, “Document – 000000001, doc_ex, A.1 -
MyContentFile.txt”).
If the full path of a renamed content file exceeds the system path limits then
the file is renamed again using the AppendSequenceID scheme. Content
files associated with CAD documents are only renamed when duplicates exist.
Content files associated with all other type of business object are always
renamed, even when no duplicates exist. This scheme is intended to maintain
consistent content file names between two or more separate exports.
For example, the following causes the prepend object identity scheme to be used
to eliminate duplicate content file names during export.
< ExportOnlyContentFileNaming>PrependIdentity</ExportOnlyContentFileNaming>
Default value: AppendSequenceID

ExportAuditLevelFullMemberInfo
The ExportAuditLevelFullMemberInfo property determines if an audit
event is emitted only for the delivery record being exported, or whether audit
events are also emitted for each of the object in the package in addition to the
delivery.
• Default value is 'true' for collector-based package types
• Default value is 'false' for replication packages

Packages Customization 1575


Note
In addition to enabling the ExportAuditLevelFullMemberInfo, you
have to enable an Export event based on instructions in the “Configuring
Audit Event Recording” topic in the Windchill Help Center.

ImportAuditLevelFullMemberInfo
The ImportAuditLevelFullMemberInfo property determines if an audit
event is emitted for only the received delivery being imported, or for each of the
members being imported in addition to the received delivery.
• Default value is 'true' for collector-based package types
• Default value is 'false' for replication packages

Note
In addition to enabling the ImportAuditLevelFullMemberInfo, you
have to enable an Import event based on instructions in the “Configuring
Audit Event Recording” topic in the Windchill Help Center.

DomainOverride
The DomainOverride property specifies the domain that a package type is
created in. If it is not defined, then a package is created in the domain defined by
the Package preference “Default Domain Path for Packages”.
For example, the following tag results in this package type being created in the
“MyDomain” domain instead of the “Default” domain as defined by the
Package preference “Default Domain Path for Packages”:
<DomainOverride>/MyDomain</DomainOverride>
• Default value: None. If not specified, then a new package is created in the
domain defined by the Package preference “Default Domain Path for
Packages”.

ShowPackageContentsTableAsTree
The ShowPackageContentsTableAsTree property controls whether the
package contents table is displayed as a tree table or as a list table. When
displayed as a list table, nested managed collection members can be viewed with
the View Nested Contents action. This property replaces the prior site-wide
com.ptc.netmarkets.wp.showPersistedCollectionHolderCon
tentTreeView wt property.

1576 Customization Guide


Default value is 'true'.

DisableAccessControlOnLinkExport
The DisableAccessControlOnLinkExport property controls whether
access control is disabled when links are processed during package exports.
Enabling this property allows a link which refers to a role object which is
inaccessible to the principal performing the zip to still be exported even if the link
export handler accesses and includes information from the role objects in its
export metadata. When disabled, links which refer to role objects inaccessible to
the principal performing the zip are filtered out of package exports. This property
only applies to importable package exports.
Default value is 'false'.
The following link handlers include role information in their metadata:
Link Handler Description
ExpImpForEPM- Container path of role A object
ContainedIn.java
ExpImpForEPMVar- Container paths of role objects
iantLink.java
ExpImpForModelI- Container path of role A object
temContainedIn.java
ExpImpForEPM- Container paths of role objects
BuildRuleAssocia-
tionLink.java
ExpImpForEPMDe- Container paths of role objects
scribeLink.java
ExpImpForEPMRe- Container paths of role objects
ferenceLink.java
ExpImpForEPM- Container paths of role objects
MemberLink.java
ExpImpForEPM- Container paths of role objects
BuildRule.java
Version information of role objects
ExpImpForEPM- Container paths of role objects
BuildHistory.java
Associated built object information
Occurrence information
Deleted build references

Packages Customization 1577


Considerations for Replication Package Types
Some properties and specific property values are not allowed for replication
packages types.
Examples:
• ExcludedSeedTypes does not make sense for
ReplicationPackages as replication packages have no seed but gets all
objects in selected containers. If you try to set ExcludedSeedTypes in
typebased property for ReplicationPackage or its subtype, you get
the error: “Invalid property: ExcludedSeedTypes found in
property set: Default, for type:
WCTYPE|com.ptc.windchill.wp.rep.ReplicationPackage”
• ReplicationPackage is only used for import, so DeliveryFormat
cannot have the value Non_Importable_Types. If you try to set that in
typeload, you get the error: Invalid property value:
DeliveryFormat = Non_Importable_Types for type:
WCTYPE|com.ptc.windchill.wp.rep.ReplicationPackage

Invalid Properties
The following are invalid properties for ReplicationPackage and it's
subTypes :
• RetainCollectionResults
• EnableContentControl
• CollectorId
• ExcludedSeedTypes
• ExcludedMemberContentRoles
• ExportOnlyContentFileNaming

Invalid Values
The following are invalid values for ReplicationPackage and it's
subTypes :
• “Interactive” is invalid value for ManifestOption and OOTB default
value is “None”. “None” & “Static” are only valid values for
ManifestOption.
<IncludedManifestOptions>
<ManifestOption default="true">None</ManifestOption>
</IncludedManifestOptions>
• “Non_Importable_Types “ is invalid values for DeliveryFormat
and OOTB default values is “Windchill_Importable_Types”.
<IncludedDeliveryFormatOptions>
<DeliveryFormat default="true">

1578 Customization Guide


Windchill_Importable_Types
</DeliveryFormat>
</IncludedDeliveryFormatOptions>
• “Incremental manifest” is invalid value for DeliveryOption and an
OOTB default value is “Incremental”. “Full” & “Incremental” are only valid
values.
<IncludedDeliveryOptions>
<DeliveryOption>Incremental</DeliveryOption>
</IncludedDeliveryOptions>

Default Values
The OOTB default values for ReplicationPackage and it's subType is:
<WPTypeProperties typeId="com.ptc.windchill.wp.rep.ReplicationPackage">
<IncludedContentRoles>
<!-- example:
<ContentRoleKey>MyCustomContentRole</ContentRoleKey>
-->
</IncludedContentRoles>
<IncludedDeliveryFormatOptions>
<DeliveryFormat default="true">
Windchill_Importable_Types
</DeliveryFormat>
</IncludedDeliveryFormatOptions>
<IncludedManifestOptions>
<ManifestOption default="true">None</ManifestOption>
</IncludedManifestOptions>
<ManifestFileName>
<!-- Manifest file name does not support the XML file extension.
manifest.txt
</ManifestFileName>
<IncludedDeliveryOptions>
<DeliveryOption>Incremental</DeliveryOption>
</IncludedDeliveryOptions>
<StaticManifestClassOverride>com.ptc.netmarkets.wp.ixb.StaticManifest
</StaticManifestClassOverride>
<DomainOverride/>
<ExportAuditLevelFullMemberInfo>false
</ExportAuditLevelFullMemberInfo>
<ImportAuditLevelFullMemberInfo>false
</ImportAuditLevelFullMemberInfo>
<ShowPackageContentsTableAsTree>true
</ShowPackageContentsTableAsTree>
<DisableAccessControlOnLinkExport>false</DisableAccessControlOnLinkExport>
</WPTypeProperties>

Packages Customization 1579


Identifying Users in Context Replication
and Activating Replicated Users
You can change the default behavior of how Windchill identifies matching users
in the target system during a context replication package import, determining
when replication of users is necessary. You can also change how the system
identifies such replicated users if converting them to active users becomes
necessary.

Background
This information details configuration and customization hooks for the following
two scenarios:
• Identifying matching users in the target system during context replication
package import and determining when replicated users are created.
During a context replication package import, user data may be included for
object attributes such as “creator” in the delivery ZIP files. By default, user
names are used to identify users on the target system if there is not an exact
match to the user’s distinguished name. If a matching user is not found in the
target system, it may result in the creation of a replicated user, if that is the
chosen resolution. You can change how users are identified in context
replication package import, and instead of user name, the user’s email address
can be used to identify users on the target system. It is also possible to change
this to use custom logic based on other attributes of the user.
• Identifying a replicated user when it comes time to activate/convert to an
active user.
Replicated users created during the Context Replication Package Import
represent inactive users that are known to the Windchill installation but who
cannot log into Windchill or interact with its business objects. Replicated users
can become regular users on activation. Activation occurs automatically when
in the process of creating a new “active” user, the system locates a matching
Replicated user entry for that user and converts that instead. By default, the
user name of the user being created is used to identify a matching Replicated
user to activate.
Sites can change how a Replicated user is identified during activation, and
instead of the user name of the user that is being created, the email address of
that user can be used to identify an existing Replicated user. It is also possible
to change this to use custom logic based on other attributes of the user being
created.

1580 Customization Guide


Scope/Applicability/Assumptions
• The two configuration scenarios described in this information must be applied
in consideration to each other. For example, if you change the behavior to use
email addresses to identify users during context replication package import, it
is recommended that you change how replicated users are identified during
user activation to use email addresses as well. This will ensure that the
processes leading to the generation of replicated users and their transformation
to active users happens based on similar characteristics of the users.
• The preference User Email in Context Replication Deliveries is relevant to the
information in this section. This preference determines if user email addresses
are included in the delivery ZIP files created as part of context replication.
When certain objects are included in the delivery ZIP files, user data is
included for object attributes such as “Creator”.
○ If the preference is set to “Yes”, user email addresses are included with the
object information during delivery creation.
○ If the preference is set to “No”, user email addresses are not included.
By default user names are used to identify users on the target system from the
information included in the delivery ZIP files, if there is not an exact match to
the user's distinguished name. You can also configure your system to use email
addresses to identify users, rather than user names. If you set this preference to
No, you should not configure your system to match users by email addresses
because it will not be able to identify the users.

Intended Outcome
By using the configuration or customization strategies described in this section,
you are able to change the behavior of:
• How matching users in the target system are identified during Context
Replication Package Import
• How replicated users are identified when it comes time to activate/convert to
an active user

Prerequisite knowledge
To achieve the intended outcome, you need to have an understanding of the
following:
• Basic development involving JAVA, XML
• Basic understanding of the Service Delegate infrastructure

Packages Customization 1581


Solution

Scenario One — How matching users in the target system


are identified during Context Replication Package Import
The intended outcomes can be achieved either by changing the appropriate service
delegate configuration to apply one of OOTB delegates or by writing a custom
delegate.
The role of the configured PrincipalMatchDelegate service
implementation in determining how a user in the target system is found, is as
described the following diagram.

Solution Elements
These elements determine how matching users in the target system are identified
during Context Replication Package Import.

Note
In the following, the selector value is a pre-determined designator of the
usage context and is meant for identifying the service configuration
appropriate for a specific usage. The selector value must not be modified –
only the corresponding serviceClass value may be changed

1582 Customization Guide


Element Type Description
service.proper Service Delegate Location: <Windchill>
ties.xconf configuration file codebase/service.
properties
The following service
configuration elements
determine which
serviceClass is applied in
each of the following
cases:
If Source data references
a non-disabled user the
selector is
UserInContextReplicatio-
nImport :
<Service context=
"default" name="wt.org.
delegate.
PrincipalMatchDele-
gate">
<Option cardinality=
"singleton" requestor=
"wt.org.WTUser"
selector=
"UserInContextReplica-
tionImport" serviceClass=
"wt.org.delegate.
ImportedUserByUserNa-
meMatchDelegate"/>
</Service>
If Source data references
a disabled user the
selector is
DisabledUserInContex-
tReplicationImport :
<Service context=
"default" name="wt.org.
delegate.
PrincipalMatchDele-
gate">

Packages Customization 1583


Element Type Description
<Option cardinality=
"singleton" requestor=
"wt.org.WTUser"
selector=
"DisabledUserInContex-
tReplicationImport"
serviceClass="wt.org.
delegate.
ImportedDisabledUser-
MatchDelegate"/>
</Service>
ImportedUserByU OOTB delegate JAVA Location: <Windchill>/
serNameMatchDele class codebase/wt/org/
gate ImportedUserByUserNa-
meMatchDelegate.class
This delegate
implementation is for use
with the selector
“UserInContextReplica-
tionImport”. OOTB, this
is the delegate configured
by default for this
selector.
This delegate is only for
use in finding matching
non-disabled users in
Context Replication
Import. It uses the source
user’s name to find a
matching non-disabled
user in the target system
ImportedUserByE OOTB delegate JAVA Location:
mailIdMatchDele class <Windchill>codebase/wt/
gate org/
ImportedUserByEmailId-
MatchDelegate.class
This delegate
implementation is for use
with the selector
“UserInContextReplica-
tionImport”. This is NOT

1584 Customization Guide


Element Type Description
the delegate configured
by default for this
selector.
This delegate is only for
use in finding matching
non-disabled users in
Context Replication
Import. It uses the source
user’s email address to
find a matching non-
disabled user in the target
system
ImportedDisabledU OOTB delegate JAVA Location:
serMatchDelegate class <Windchill>codebase/wt/
org/
ImportedDisabledUser-
MatchDelegate.class
This delegate
implementation is for use
with the selector
“DisabledUserInContex-
tReplicationImport”. This
is the delegate configured
by default for this
selector.
This delegate is only for
use in finding matching
disabled users in Context
Replication Import. It
uses the source user’s
name, email address, full
name, and last name to
find a matching disabled
user in the target system
PrincipalMatchDe Delegate JAVA interface All customized delegate
legate for customizers implementations must
adhere to the contract
established by this
interface

Packages Customization 1585


Procedure
• To change the behavior so that user’s email addresses are used to identify
non-disabled users on the target system during context replication import,
change the serviceClass in the configuration element associated with the
selector UserInContextReplicationImport to use the
wt.org.ImportedUserByEmailIdMatchDelegate implementation:
<Service context="default" name="wt.org.delegate.PrincipalMatchDelegate">
<Option cardinality="singleton" requestor="wt.org.WTUser"
selector="UserInContextReplicationImport"
serviceClass="wt.org.delegate.ImportedUserByEmailIdMatchDelegate"/>
</Service>

Note
This configuration is only supported for the selector
UserInContextReplicationImport. It does not apply to the
selector DisabledUserInContextReplicationImport since
there are no alternative delegate implementations for the selector
DisabledUserInContextReplicationImport other than the
default one configured OOTB.

• To change the behavior to use more customized logic based on other attributes
of the user, see Customization Points on page 1590.

Scenario Two : How replicated users are identified when it


comes time to activate/convert to an active user
The role of the configured PrincipalMatchDelegate service
implementation in determining how a replicated user is found for activation, is as
described in the following diagram.
The following diagram details the role of the configured
PrincipalMatchDelegate in Replicated User Activation.

1586 Customization Guide


Solution Elements
These elements determine how replicated users are identified when it comes time
to activate/convert to an active user

Note
In the following, the selector value is a pre-determined designator of the
usage context and is meant for identifying the service configuration
appropriate for a specific usage. The selector value must not be modified –
only the corresponding serviceClass value may be changed

Packages Customization 1587


Element Type Description
ReplicatedUserFor OOTB delegate JAVA Location: <Windchill>
ActivationByUser class \codebase/wt/org/
NameMatchDelegate ReplicatedUserForActiva-
tionByUserNameMatch-
Delegate.class
This delegate
implementation is for use
with the selector
“ReplicatedUserForActi-
vation”. This is the
delegate configured by
default for this selector.
This delegate is only for
use in finding a matching
replicated during user
creation. It uses the
source user’s name to find
a matching replicated user
that can be converted into
an active user
ReplicatedUserFor OOTB delegate JAVA Location: <Windchill>
ActivationByEmai class \codebase/wt/org/
lIdMatchDelegate ReplicatedUserForActiva-
tionByEmailIdMatchDe-
legate
This delegate
implementation is for use
with the selector
“ReplicatedUserForActi-
vation”. This is not the
delegate configured by
default for this selector.
This delegate is only for
use in finding a matching
replicated user during
user creation. It uses the
source user’s email
address to find a
matching replicated user
that can be converted into
an active user

1588 Customization Guide


Element Type Description
service.proper Service Delegate Location: <Windchill>\
ties.xconf configuration file codebase/service.
properties
The following service
configuration elements
determine which
serviceClass is applied for
the selector
ReplicatedUserForActiva-
tion.
<Service context=
"default" name="wt.org.
delegate.
PrincipalMatchDele-
gate">
<Option cardinality=
"singleton" requestor=
"wt.org.WTUser"
selector=
"ReplicatedUserForActi-
vation" serviceClass="wt.
org.delegate.
ReplicatedUserForActiva-
tionByUserNameMatch-
Delegate"/>
</Service>
PrincipalMatchDe Delegate JAVA interface Location: <Windchill>
legate for customizers \codebase/wt/org/
PrincipalMatchDelegate.
class
All customized delegate
implementations must
adhere to the contract
established by this
interface

Procedure
• To change the behavior so that user’s email addresses are used to identify
replicated users during user activation, change the serviceClass
associated with the selector ReplicatedUserForActivation to use the

Packages Customization 1589


ReplicatedUserForActivationByEmailIdMatchDelegate
implementation:
<Service context="default" name="wt.org.delegate.PrincipalMatchDelegate">
<Option cardinality="singleton" requestor="wt.org.WTUser"
selector="ReplicatedUserForActivation"
serviceClass="wt.org.delegate.
ReplicatedUserForActivationByEmailIdMatchDelegate"/>
</Service>
• To change the behavior to use more customized logic based on other attributes
of the user, see Customization Points on page 1590.

Customization Points
wt.org.PrincipalMatchDelegate
All customized delegate implementations in this document must adhere to the
contract established by this interface. Specialized delegate implementations can
encapsulate rules specific to the installation.

WTPrincipal wt.org.PrincipalMatchDelegate.match(WTPrincipal
querySpec) throws WTException
The PrincipalMatchDelegate interface specifies one single API: public
WTPrincipal match(WTPrincipal querySpec) throws
WTException;
This API finds a match among existing principals based on rules that are
applicable to a usage context.

1590 Customization Guide


Parameter Default Possible Required? Description
Value Values
querySpec NA WTPrincipal Yes The criteria to
(WTUser, be used for
WTGroup, or matching must
WTOrganiza- be initialized
tion) in
See corresponding
Limitations on attributes in a
page 1592 principal
object of the
desired type
(user, group,
or
organization),
which acts as
the query
specification
Return: The matching
WTPrincipal principal
found based on
any internal
logic in the
implementa-
tion. If a match
is not found, a
NULL result
must be
returned
Custom delegate can then be specified in the appropriate service configuration
element:
<Service context="default" name="wt.org.delegate.PrincipalMatchDelegate">
<Option cardinality="singleton"
requestor="wt.org.WTUser"
selector="<<APPLICABLE_SELECTOR_VALUE>>"
serviceClass="<<CUSTOM_DELEGATE_CLASS>>"/>
</Service>

Packages Customization 1591


Limitations
• Each delegate implementation provided OOTB is only for use with a specific
delegate selector context. The designated selector context is described in
Solution on page 1582.
• Although the PrincipalMatchDelegate interface defines the contract
for all WTPrincipal sub-classes, support for service delegate-based
matching is currently only available with WTUser processing and only in the
scenarios described here. Support for other sub-classes (WTGroup,
WTOrganization) in these scenarios is not yet available via delegate-based
processing. These are intended for future use.

Sample Code
Writing a Custom Delegate
A custom delegate would implement the PrincipaMatchDelegate and
override the match(…) API to provide some custom logic. The following
example shows the logic for finding a match by user name:
public WTPrincipal match(WTPrincipal querySpec) throws WTException {

if (querySpec == null || !(querySpec instanceof WTUser)) {


if (logger.isDebugEnabled()) logger.debug("Input principal is null");
return null;
}

// Clone right away to avoid auto-inflate when calling getters


WTUser querySpecClone = (WTUser) querySpec.cloneAsInflated();

String userName = ((WTUser) querySpecClone).getName();


if (userName == null || userName.trim().isEmpty()) return null;

WTPrincipal result = null;


String userNames[] = new String[] { userName };

result = OrganizationServicesHelper.manager.findPersistedUser
userNames, null /* email */, null /* fullName */, null /* surname
*/, null /* status */, null /* internal */, Boolean.FALSE /* disabled */);

return result;
}

Examples of Usage in Windchill Code


• <Windchill>\codebase\service.properties
• <Windchill>\codebase\wt\org\delegate\
PrincipalMatchDelegate.class

1592 Customization Guide


• <Windchill>\codebase\wt\org\delegate\
ImportedUserByUserNameMatchDelegate.class
• <Windchill>\codebase\wt\org\delegate\
ImportedUserByEmailIdMatchDelegate.class
• <Windchill>\\codebase\wt\org\delegate\
ImportedUserByUserNameMatchDelegate.class
• <Windchill>\codebase\wt\org\delegate\
ReplicatedUserForActivationByUserNameMatchDelegate.
class
• <Windchill>\codebase\wt\org\delegate\
ReplicatedUserForActivationByEmailIdMatchDelegate.
class

Packaged Samples
• <Windchill>\prog_examples\principal\
principalmatchdelegate\
ImportedUserByUserNameMatchDelegate.java
• <Windchill>\prog_examples\principal\
principalmatchdelegate\
ReplicatedUserForActivationByUserNameMatchDelegate.
java

Related Package/Class Javadoc


• wt.org.delegate

Packages Customization 1593


Select Files – Copy Forward Exclusion
Decisions
You can define some rules to reconcile the exclusion decisions taken by user over
the package maturity.

Background
As a part of the default implementation rules are defined to reconcile the decisions
taken by user over the package maturity like for update of package contents,
SaveAs or Revise action where the explicit user decisions are copied forward over
the contents present in target package. The default implementation can be
customized to extend the behavior that suit the respective business requirement.
The default implementation provided copies the user explicit decisions from the
latest versions in the old package to the new versions in the updated package.

Scope/Applicability/Assumptions
• This information should be applied by a developer or customizer who is
responsible for configuring the information page for some object in Windchill.
• It is assumed that you have basic knowledge about Packages and Select Files
functionality.

Intended Outcome
The intended outcome will depend on the implementation as per the respective
business requirement.

Solution
A custom java class would be written which would override the default behavior
for copy forward of explicit decisions on package update.

Prerequisite knowledge
To achieve the intended result you need to have an understanding of the following:
• Basic knowledge about Packages and Select Files.
• Basic knowledge of object versioning in Windchill.
• The management of properties files in Windchill, including the use of
xconfmanager.

1594 Customization Guide


Solution Elements
Element Type Description
ContentControlDe Java Interface This interface needs to be
cisionVersionDele implemented by the new
gate custom class
AbstractContent Abstract Class This is the Abstract class
ControlDecision which has the
VersionDelegate ContentControl
Link Comparator
contentcontrol- XCONF file This is used to configure
service.proper the new Custom class
ties.xconf

Procedure – Create new Custom class for copy forward of explicit


decisions
1. Create the new custom java class <custom class> which
implements "ContentControlDecisionVersionDelegate" and
provide custom implementation for
"copyExclusionInfoForRevision" API.
2. The implementation of above API should be as per the respective business
requirement.
3. Check the contentcontrol-service.properties.xconf file for
the entry for :
<!-- ContentControlDecisionVersionDelegate -->
<Service name="com.ptc.windchill.contentcontrol.delegates.
ContentControlDecisionVersionDelegate">
<Option serviceClass="com.ptc.windchill.contentcontrol.delegates.
DefaultContentControlDecisionVersionDelegate"
requestor="java.lang.Object"
selector="null"
cardinality="singleton"/>
</Service>

Change the following serviceClass attribute with the fully qualified name
of the new custom implementation class.
<Service name="com.ptc.windchill.contentcontrol.delegates.
ContentControlDecisionVersionDelegate">
<Option serviceClass="<custom class>"
requestor="java.lang.Object"
selector="null"
cardinality="singleton"/>
</Service>

Packages Customization 1595


4. Run xconfmanager -p to propagate the above changes to
service.properties.
5. Restart the method server to effect the changes.

Customization Points
The ContentControlDecisionVersionDelegate interface a single API
void opyExclusionInfoForRevision(WTKeyedMap masterToOldCClMap,
WTKeyedMap masterToNewCClMap) throws WTPropertyVetoException ;
The parameters are as follows:
• masterToOldCClMap : WTKeyedMap; : This map contains the master
object as key and the list of old ContentControlLinks as value
• masterToNewCClMap : WTKeyedMap; : This map contains the master
object as key and the list of new ContentControlLinks as value
By getting the list of old and new ContentControlLinks for the same master
the exclusion info can be copied from the old links to the new links. The list of
new ContentControlLinks does not have the ContentControlLinks
for which the same version exists in the old links. For this the exclusion info will
be copied from the old links by default. Only the versions which did not exist
earlier will be added to the list.

Sample Code
The default implementation for this functionality is provided as
DefaultContentControlDecisionVersionDelegate in the
com.ptc.windchill.contentcontrol.delegates package.

1596 Customization Guide


Windchill Replication Package Command
Line Sample Scripts
You can automate the process of uploading and importing the received deliveries.
This section shows some example scripts and includes information on how this
can be achieved using a job or task scheduler.

Note
For more information on the utility, see the “Windchill Package Command
Line Utility” topic in the Windchill Help Center.

Windows
In following sample, the upload_import_rd.cmd script is run every 8 hours.
schtasks /create /tn "Context Replication cron job" /tr
"C:\import_scripts\upload_import_rd.cmd /sc hourly 8

This is a sample upload_import_rd.cmd script to upload and import all


uploaded received deliveries in a single job.

@echo off

GOTO EXECUTE

:EXECUTE

cd C:\ptc\Windchill\bin
windchill.exe com.ptc.windchill.rd.cli.WindchillPackage import -u demo
-c "/wt.inf.container.OrgContainer=Demo Organization/wt.pdmlink.PDMLinkProduct=NI_import"
-l "C:\Packages" -r -d

IF %ERRORLEVEL% == 1 GOTO IMPORT_FAILURE

GOTO END

:IMPORT_FAILURE
ECHO [Error] Import command has failed. Please see logs for details

:END

Packages Customization 1597


UNIX
In following sample, the upload_import.sh shell script is run every 8 hours.
* 8 * * * /bin/sh /path/to/script/upload_import.sh

In the following sample, the shell script runs the upload and import commands in
sequence and the input of the upload is redirected in a file. This file is then given
as input to an import command, so that import is started for only those received
deliveries which are uploaded in the same script.
#!/bin/sh
java com.ptc.windchill.rd.cli.WindchillPackage import -u wcadmin -l
“D:\packages” -c “/wt.inf.container.OrgContainer=Demo Organization/wt.pdmlink.
PDMLinkProduct=Drive System” -d -m
IF [$?= 1]then exit 1
fi
exit 0

1598 Customization Guide


37
DTI Customization Framework
Add Custom Attributes to Microsoft Office ............................................................... 1600
Customize the Windchill tab in Microsoft Office ........................................................ 1602
Customize Windchill Actions in Windows Explorer ................................................... 1617
Customize the DTI Document Search Window......................................................... 1620
Using DTI with Form-Based Authentication ............................................................. 1621

Windchill supports a Microsoft Office integration known as Windchill Desktop


Integration (DTI). DTI supports Windchill actions, such as Create Document,
Check In, Check Out, and Search, from within Microsoft Office applications under
the Windchill tab.
Windchill Desktop Integration supports customization to suit your site-specific
action implementations. This customization involves the introduction of custom
attributes and new actions (launch points) on the Microsoft Office ribbon.

1599
Add Custom Attributes to Microsoft
Office
You can map Windchill attributes to Microsoft Office properties. For more
information, see “Windchill Desktop Integration” in the Windchill Help Center.

Caution
The custom properties limit in Microsoft Office documents is 255 chars. This
limit can be enforced by a string length constraint in the Type and Attribute
Management utility.

To add additional attributes to DTI, perform the following actions:


1. Stop the method server.
2. Create a backup copy of msoimap.xml. This file is located under the
following directory:
<Windchill>\codebase\com\ptc\windchill\enterprise\
nativeapp\msoi\server\msoimap.xml
3. Customize or add attributes to msoimap.xml using the following syntax:
<attribute>
<ms_name>Name_To_Display_In_Microsoft_Office</ms_name>
<wt_name>Windchill_Attribute_Introspection_Name</wt_name>
</attribute>

Note
To find the introspection name (the <wt_name> value), open a Windchill
shell and execute the InfoReport command for a specific object type.
For example:
InfoReport wt.doc.WTDocument

Results are located in the following file:


<Windchill>\temp\doc.WTDocument.out

4. Start the method server.


To verify your changes, open a Microsoft Office application and select Windchill ▶
Properties ▶ Refresh Properties.

1600 Customization Guide


Example
In the following example, the Created By, Modified By, and Created On attributes
are added to the Microsoft Office custom properties:
<type key="wt.doc.WTDocument">

<attribute>
<ms_name>Created By</ms_name>
<wt_name>creator.name</wt_name>
<display>true</display>
<attrFormat>string</attrFormat>
</attribute>

<attribute>
<ms_name>Modified By</ms_name>
<wt_name>modifier.name</wt_name>
<display>true</display>
<attrFormat>string</attrFormat>
</attribute>

<attribute>
<ms_name>Created On</ms_name>
<wt_name>thePersistInfo.createStamp</wt_name>
<display>true</display>
<attrFormat>string</attrFormat>
</attribute>

</type>

DTI Customization Framework 1601


Customize the Windchill tab in Microsoft
Office
Windchill Desktop Integration provides a way to add custom actions to the
Microsoft Office ribbon menu.
To add a custom action to the menu, you must:
1. Customize the ribbon UI.
2. Invoke the actions using command configurations.
3. Inject implementation using VBA macros.
4. Implement server-side customizations.

Customize the Ribbon


Windchill Desktop Integration allows system administrators to introduce custom
buttons on the Windchill tab in Microsoft Office applications. The only
requirement is the presence of a valid XML file with the custom ribbon user
interface definition. This file must be located in the following location:
<Windchill>/codebase/com/ptc/windchill/enterprise/nativeapp
/msoi/client/custom/wtCustomMenu.xml
For more information on the ribbon UI, see the Microsoft documentation on
ribbons at the following link:
http://msdn.microsoft.com/en-us/library/cc872782.aspx
All custom actions required to be implemented must be located inside an action
group. This serves as the root/document element for the custom ribbon UI in
XML.
Adding a button node as child to the group makes it display on the ribbon UI as
a clickable item.
The following example illustrates a custom action group with two buttons:
<group id="MyCustomActions" tag="MyCustomActions"
getLabel="MsoiGetLabel" getScreentip="MsoiScreentip"
getVisible="MsoiServerVisible">

<button id="CustomAction01" tag="CustomAction01" enabled="true"


label="Custom Action 01"
screentip="Click this to launch the first custom action"
getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="ca1"/>

<button id="CustomAction02" tag="CustomAction02" getEnabled="MsoiIsEnabled"


getLabel="MsoiGetLabel" getScreentip="MsoiScreentip" getImage="MsoiGetImage"
onAction="MsoiOnAction" keytip="ca2"/>
</group>

1602 Customization Guide


To control the visibility of the group:
• getVisible—To make the group visible only when connected to an active
Windchill server, set this attribute to MsoiServerVisible.
• visible—If the group should be visible at all times, remove the getVisible
attribute and set visible to true.
To control the button state:
• getEnabled—If you set this attribute to MsoiIsEnabled, then the button
remains disabled unless server-side changes explicitly render the button
enabled or disabled.
• enabled—If the button should be enabled whenever the group is visible,
remove the getEnabled attribute from the button node and set enabled to
true.

Note
The attributes label and screentip control the label and the tooltip for
the button respectively. In general, static text marginally improves
performance.
To localize a custom menus, you must use getLabel and getScreentip
instead.

Creating an Application-Specific Custom Menu


Windchill Desktop Integration supports customization of the ribbon UI for a
specific Microsoft Office application. Append the short application name to the
file name. For example, the following file would create a new button that only
displays in Microsoft Excel:
<Windchill>/codebase/com/ptc/windchill/enterprise/
nativeapp/msoi/client/custom/wtCustomMenuExcel.xml
Add the following code:
<?xml version="1.0"?>
<groups>
<group id="ExcelActionsGroup" tag="ExcelActionsGroup"
label="Excel actions group" screentip="Custom Excel
actions group" visible="true">

<button id="MyExcelButton" tag="MyExcelButton" enabled="true"


label="Invoke my own custom Excel action"
screentip="Clicking here will launch my own Excel action."
getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="ea"/>
</group>
</groups>

DTI Customization Framework 1603


Localizing Text
Windchill Desktop Integration allows a way to localize the text displayed on the
ribbon UI. This enables end users to see translations in their native languages.

Note
• Localization of ribbon button labels and screentips work only when the
label and screentip attributes are replaced with getLabel and
getScreentip attributes. The values for these attributes must be set to
MsoiGetLabel and MsoiScreentip respectively.
• PTC recommends that the id and the tag attributes be left as unique text.
Windchill Desktop Integration use the tag attribute for further processing,
as mentioned below.

To localize the ribbon UI, perform the following actions:


1. Localize the label.
• Add a new node to the following file (or its locale-specific equivalents) on
the server:
<Windchill>/codebase/com/ptc/windchill/
enterprise/nativeapp/msoi/client/custom/
wtCustomLabels.xml
For example, adding the relevant node text to wtCustomLabels_
ru.xml translates the menu into Russian.
The format of the node is as follows:
<CustomAction02>
<short>Custom Action 02</short>
</CustomAction02>
• The parent node name (“CustomAction02”) must match the tag
attribute of the group and button.
2. Localize the tooltip.
This is similar to the label except that the child node should be named
tooltip. The format of the node is as follows:
<CustomAction02>
<short>Custom Action 02</short>
<tooltip>Click here to launch this custom action</tooltip>
</CustomAction02>
3. Deploy the translations to all clients.

1604 Customization Guide


After the changes are saved on the server, a copy of this file is automatically
picked up by the Windchill Desktop Integration client.

Add Custom Commands


Windchill Desktop Integration allows the addition of new commands to the
existing set. These commands are the implementations of sets of actions to be
triggered, based on interaction with the new controls on the ribbon UI.
These commands can be controlled from the server directly rather than
implementing the changes on each client system.
Customized ribbon actions are located in the following server file:
<Windchill>/codebase/com/ptc/windchill/enterprise/
nativeapp/msoi/client/custom/wtCustomActions.xml
After the changes to this file are saved, the Windchill Desktop Integration client
automatically picks up a copy of the changes from the server when it connects to
the server the next time.
The following example illustrates a custom command:
<command key="CustomAction01">
<action method="run_macro" type="CLIENT">
<defaultdata key="macro_name">DisplayHelloWorldAlert</defaultdata>
</action>
<action serverAction="customization.DTICustomizationDemo" type="WIZARD"/>
</command>

Note
In this example, method and serverAction are actually implemented on
the client and the server respectively. Each attribute value should be
accompanied with implementation.
Otherwise, an Action not found error will be displayed by Windchill
Desktop Integration.

Adding Action Specific Data


The file is pre-populated with the text Add your description below this.
If the intent is only to pass the data retrieved from the server from an earlier action
to the next one, then you can use an empty macro_args data node. For more
information, see the can be second run_macro action instance from the
SearchParts example implementation scenario later in this topic.

DTI Customization Framework 1605


Create Custom Commands Using Macros
Windchill Desktop Integration only expects the macro code to be available to the
Office document in question.
DTI can run both types of macros: those which were injected into the Office
document through the import_module action or those which already existed in
the document.

Note
PTC recommends that the macros be thoroughly tested using live Microsoft
Office documents before being uploaded on the Windchill server for
deployment. Windchill Desktop Integration is not responsible for any
exceptions arising during macro execution. All errors are displayed to the
users.

The following example illustrates a custom action configuration:


<action method="run_macro" type="CLIENT">
<defaultdata key="macro_name">Macro1</defaultdata>
<defaultdata key="macro_args">Albert Einstein</defaultdata>
</action>

Note
The macro_name key is a reserved and mandatory keyword.
The macro_args is optional and can be used in case additional data needs to
be provided to the macro.

Handling Multiple Inputs


In case the macro needs multiple inputs, PTC recommends that this be handled
using VBA code within the macro itself.
For example, assuming the macro needs more than one argument, an XML file
could be generated with the relevant data and the relative filename provided as a
value to macro_args. This XML file could again be placed on the server so that
it is picked up by all Windchill Desktop Integration clients on the subsequent
connect action. Alternatively, multiple pieces of information could be provided
using some delimiter (with proper XML escaping). The VBA macro code could
again split the data on the delimiter and recreate the original information.

1606 Customization Guide


Injecting Macros
1. Create macro modules for injection.
The following example illustrates how to create a macro module for injection
in Microsoft Excel:
a. Create a new folder named “Excel” under <Windchill>/codebase/
com/ptc/windchill/enterprise/nativeapp/msoi/
client/custom.
b. Create Module1.bas under it. and paste the following code into the file:
Sub Macro1(sUsername As String)
MsgBox("Hello " & sUsername & "! This is a macro alert.")
End Sub

Note
The Windchill Desktop Integration client automatically picks up all
modules on the subsequent connect action on the server.

2. Import macro modules into Microsoft Office.


Importing macro modules into Microsoft Office requires changes to the
wtCustomActions.xml file on the server. The following example
illustrates the import module action:
<action method="import_module" type="CLIENT">
<defaultdata key="module_path">custom\Excel\Module1.bas</defaultdata>
</action>

Note
If the value of module path parameter is not an absolute path, then it is
expected to be the relative path from the custom folder.

Note
The module is imported to different files and templates based on the
Microsoft Office application in question. For example, Microsoft Word
typically imports into the Normal.dot* template. Excel directly imports
into the open workbook. The location can be confirmed by using the VBA
editor (shortcut Alt + F11).

DTI Customization Framework 1607


Removing Macros
To remove the macro in the Microsoft Office document after it has been run, use
the following action configuration:
<action method="remove_module" type="CLIENT">
<defaultdata key="module_name">Module1</defaultdata>
</action>
The module_name key value should match with what is displayed as the
module name in the VBA editor (Alt + F11).

Server Side Customization


When any set of actions require interaction with the Windchill server, either user
interaction in the form of an action window or some data to be retrieved over the
web, it is necessary to implement the action on the remote Windchill server. There
are three steps to this server side customization:
1. Defining the custom action.
2. Designing the user interface.
3. Implementing the form processor.

1. Define the Custom Action


To handle server side operations of DTI customization, create a new custom
action. A custom action can be defined in any *-actions.xml file. Refer to
User Interface Customization for more details.
To handle server side operations of DTI customization, create a new custom
action. A custom action can be defined in any *-actions.xml file. For more
information, see User Interface Customization on page 229.
For example, you could modify <Windchill>/codebase/config/
actions/custom-actions.xml to introduce the following XML fragment
as a child node to the listofactions root node.
<objecttype name="test_object" class="wt.doc.WTDocument">
<action name="test_action">
<command class="com.ptc.customization.forms.TestFormProcessor"
method="execute" windowType="popup"
url="/netmarkets/jsp/customization/Test.jsp"/>
</action>
</objecttype>

This is the configuration for the test_action action defined for objects of type
test_object. Invocation of this action would launch Test.jsp. On
completion of interaction with the user interface rendered by this page, a response
is built in TestFormProcessor and can be passed on to the client, if desired.

1608 Customization Guide


2. Design the User Interface
In case the server interaction involves any action windows, it is necessary to
design the corresponding user interface. In its most simplistic form, the user
interface can be a simple JSP file that resides on the server and performs some
actions on a set of Windchill objects. For further information on implementing
custom user interfaces, see User Interface Customization.
In case the server interaction involves any action window, it is necessary to design
the corresponding user interface. In its most simplistic form, the user interface can
be a simple JSP file that resides on the server and performs some actions on a set
of Windchill objects. For further information on implementing custom user
interfaces, see User Interface Customization on page 229.

3. Implement the Form Processor


When the data is to be submitted to the Windchill server, the form processor is
responsible for generating the response to be returned to the client. The basic
guideline of customizing Windchill UI remains the same, however.
For more information, see Customizing the UI with Ajax on page 291.

Implementation Example
In the following example, the user needs to select a set of Windchill parts and
query certain properties of these selected parts. We add these properties in a
Microsoft Excel sheet in the form of column headers. The properties to be selected
and its sequence will be provided as an input to the Windchill server. The response
from the server would be picked up by the client and will be populated in a tabular
form in the Microsoft Excel sheet.
A working example of this example is also available in the Windchill installation.
To deploy the sample, use a Windchill shell and perform the following actions:
1. Navigate to prog_examples/DTI_Customization.
2. Under each src and src_web folder, find and invoke the ant script named
build.xml. The file DTICustomizationReadMe.txt is included for
quick reference.
3. Once ant has been invoked on both the ant files, restart the Windchill server.
The rest of this section discusses the alternative manual steps needed to configure
the example implementation.

Client-Side Customization
Customize the Ribbon UI
1. Locate the following file:

DTI Customization Framework 1609


<Windchill>/codebase/com/ptc/windchill/enterprise/
nativeapp/msoi/client/custom/wtCustomMenu.xml

2. Add the following text to the file:


<?xml version="1.0"?>
<groups>
<group id="ExcelActionsGroup" tag="ExcelActionsGroup"
label="Excel actions group"
screentip="Custom Excel actions group" visible="true">
<button id="SearchParts" tag="SearchParts" enabled="true"
label="Search parts" screentip="Sample custom action to search
parts on the Windchill server."
getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="sp"/>
</group>
</groups>

The next time a Windchill Desktop Integration client running Microsoft Excel
connects to this server, the updated ribbon UI definition will be downloaded to
the client cache.
3. Close Microsoft Excel and launch it again. This step is necessary because the
Windchill add-in will load in the Microsoft Office application (Excel) even
before connecting to any Windchill server. When Microsoft Excel is launched
a second time, you should be seeing a new group and an action:

Create a Custom Command


You now must implement the custom action that you introduced. Configuring a
command involves defining a set of actions that will get invoked once the ribbon
control is clicked.

1610 Customization Guide


The tag attribute for the control SearchParts should match the command
key. This is how Windchill Desktop Integration can establish an association with
the custom controls on the ribbon UI with the command.
Based on the example description, the command must do the following:
1. Read the header values from the Microsoft Excel sheet.
2. Send the property names to be sent to the server.
3. Feed the response into the sheet again.
Navigate to the following file:
<Windchill>/codebase/com/ptc/windchill/enterprise/
nativeapp/msoi/client/custom/wtCustomActions.xml
Add the following text to the file:
<?xml version="1.0"?>
<commandset>
<command key="SearchParts">
<action method="run_macro" type="CLIENT">
<defaultdata key="macro_name">GetHeaders</defaultdata>
</action>
<action serverAction="customization.DTICustomizationDemo" type="WIZARD"/>
<action method="run_macro" type="CLIENT">
<defaultdata key="macro_name">PutValues</defaultdata>
<defaultdata key="macro_args"/>
</action>
</command>
</commandset>
Now you have two client side actions with a server action in between.

Run the Macros


In this example, the cells A1-D1 are populated with the properties needed to query
the parts:

DTI Customization Framework 1611


1. Introduce a macro that simply joins the text of these four cells with a
separator.

Note
The name of the macro GetHeaders must match the action
configuration data parameter macro_name.

2. Create another macro that will subsequently pick up response from the server
and populate it in the sheet. According to the action configuration, this macro
must be called PutValues. The VBA code for the Microsoft Excel
workbook now looks like the following example:

Note that the code within the PutValues macro above will simply generate an
alert message with the custom response received from the Windchill server. In
practice, the code could do complex actions such as generating an inline
validation drop-down for certain cells.
'A reference to msxml6.dll is needed
Dim dom As New DOMDocument60
dom.LoadXML (strResponse)

'Using xpath, construct a csv list of choices for the number


Dim strNumberChoices As String
For Each elem In dom.SelectNodes("/Results/*/Number")

1612 Customization Guide


strNumberChoices = strNumberChoices & "," & elem.Text
Next
'Remove initial comma
strNumberChoices = Strings.Right(strNumberChoices, Len(strNumberChoices) - 1)

With Range("C1").Validation
'Remove previous validation (likely that user redoing a seed part search)
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=strNumberChoices

End With

Server-Side Customization
Define the Custom Action
The following file is provided out-of-the-box with Windchill. The file is empty
and can be used for this sample customization:
<Windchill>/codebase/config/actions/custom-actions.xml
Add the following XML text as a child node for the listofactions document
node.
<objecttype name="customization" class="wt.doc.WTDocument">
<action name="DTICustomizationDemo">
<command class="com.ptc.dti.customization.forms.
TICustomizationFormProcessor"
method="execute" windowType="popup"
url="/netmarkets/jsp/customization/partPicker.jsp"/>
</action>
</objecttype>
This defines the DTICustomizationDemo action, which will be called from
the DTI client side. On invocation of this action, a partPicker.jsp is
launched. On completion of this action, a response is built in
DTICustomizationFormProcessor.

Design the User Interface


For this example, you need the WTPart search and multiple part picker
capability. This is implemented in partPicker.jsp using the itemPicker
tag with WTPart as objectType.
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %>
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/dti" prefix="dti"%>
<wctags:externalFormData/>
<input type="hidden" name="fieldsToDisplay" id="fieldsToDisplay"
value="${dti:getCustomActionArg(param.externalFormData)}" />

DTI Customization Framework 1613


<input type="hidden" name="selectedParts" id="selectedParts" value=" " />
<wctags:itemPicker id="dtiPartPicker"
inline="true"
pickerCallback="partPickerCallback"
componentId="dtiPartPicker"
pickerTitle="DTI Customization Part Picker Example"
objectType="wt.part.WTPart"
multiSelect="true"
/>

<SCRIPT>
function partPickerCallback(objects) {
var selectedPartsOid = '';
var myJSONObjects=objects.pickedObject;
for(var i=0; i< myJSONObjects.length;i++) {
if(i != 0){
selectedPartsOid += ';'; //partOID separator
}
selectedPartsOid += myJSONObjects[i]["oid"];
}
$("selectedParts").value = selectedPartsOid;
window.pickerCallback = "doNothing";
}
</SCRIPT>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Note
• Use the wctags:externalFormData tag to pass DTI data in the form
of hidden field.
• Use dti:getCustomActionArg(param.externalFormData)
to capture the input argument that is send from DTI. It is passed to the
form processor as a hidden field.

In this example, the argument sent is a list of Windchill part properties to query
with ‘::’ as the separator(Name::Number::Version::State).
A pickerCallback function is defined, which will capture OIDs of selected parts
and put it in a string with ‘;’ separators, then pass that list of selected parts OIDs to
form processor through selectedParts hidden field. The following example
displays the partPicker.jsp after searching and selecting a few records:

1614 Customization Guide


Implement the Form Processor
The form processor is implemented in the
DTICustomizationFormProcessor.java file. The required data, such as
fieldsToDisplay and selectedParts is obtained from beans data.
You can format the response in any format (such as XML, TXT, CSV) and put
that in the session object in the form of a string. The same response is made
available to the DTI client side as a response. The only requirement here is to pass
DTI_CUSTOM_KEY=<dtiCustKey> as a part of
wizardResponsehandler.
Below is sample code of the setResultNextAction method:
String responseString =
“<RESULTS>
<Result0 Name="01-51231.prt" Number="WCDS0000000104"
tate="INWORK" Version="A.1"/>
<Result1 Name="01-51246_2.prt" Number="WCDS0000000150"
tate="INWORK" Version="A.5"/>
<Result2 Name="01-52100.asm" Number="WCDS0000000473"
tate="INWORK" Version="A.2"/>
<Result3 Name="01-512040.asm" Number="WCDS0000000654"

DTI Customization Framework 1615


tate="INWORK" Version="A.1"/>
<Result4 Name="01-51251a.prt" Number="WCDS0000000055"
tate="INWORK" Version="A.1"/>
<Result5 Name="01-512106a.prt" Number="WCDS0000000363"
tate="INWORK" Version="A.1"/>
</RESULTS>”;

String dtiCustkey = "DTI_CUST_DATA" + System.currentTimeMillis();


clientData.getRequest().getSession().setAttribute(dtiCustkey, responseString);
wizardResponseHandler += "&DTI_CUSTOM_KEY="+ dtiCustkey;
Here responseString is built as an XML response based upon properties to
query and parts selected.
This same response string in the same format will be available at DTI client side.
Refer to the DTICustomizationFormProcessor.java file available in
your Windchill installation for more details on implementation.

1616 Customization Guide


Customize Windchill Actions in Windows
Explorer
You can add custom actions to the right-click actions menu in Windows Explorer
when navigating under the Windchill Documents node.
You can customize actions for the following objects:
• Folders
• Documents
• Multi-document selections
In order to complete the following steps, the following prerequisites must be met:
• A Windchill server is available that supports this DTI customization
framework (Windchill 10.2 M010+).
• A DTI plugin is installed on a client machine that also supports this
customization framework.
Use the following steps to create customized actions in the right-click menu in
Windows Explorer

Server-Side Steps

Tip
Steps 1 and 2 can either be performed manually or using the Ant script located
under the src and src_web folders in the following directory:
<Windchill>/prog_examples/DTI_Customization

1. Compile DTICustomActionFormProcessor.java and ensure its class


is available in the Windchill codebase under com\ptc\dti\
customization\forms.
2. Ensure that the following JSP files are present in the codebase\
netmarkets\jsp\customization directory:
dtiCustomAction.jsp
dtiCustomActionFolder.jsp
dtiCustomActionForMulti.jsp
dtiCustomActionStep.jsp
3. Add the following lines to codebase\config\actions\custom-
actions.xml. Add the lines inside the <listofactions> node:
<objecttype name="customization" class=""

DTI Customization Framework 1617


resourceBundle="com.ptc.windchill.enterprise.nativeapp.msoi.server.serverResource">
<action name="DTICustomAction">
<command class="com.ptc.dti.customization.forms.DTICustomActionFormProcessor"
method="execute" windowType="popup"
url="/netmarkets/jsp/customization/dtiCustomAction.jsp"/>
</action>

<action name="DTICustomActionStep">
<command windowType="popup" url="/netmarkets/jsp/customization/
dtiCustomActionStep.jsp"/>
</action>

<action name="DTICustomActionForMulti">
<command class="com.ptc.dti.customization.forms.
DTICustomActionForMultiFormProcessor"
method="execute" windowType="popup"
url="/netmarkets/jsp/customization/dtiCustomActionForMulti.jsp"/>
</action>

<action name="DTICustomActionFolder">
<command class="com.ptc.dti.customization.forms.DTICustomActionFormProcessor"
method="execute" windowType="popup"
url="/netmarkets/jsp/customization/dtiCustomActionFolder.jsp"/>
</action>
</objecttype>

4. Add following lines to codebase\config\actions\custom-


actionsModels.xml. Add the lines inside the <actionModels> node.
<actionmodels>
<model name="DTI.Explorer.Document.MultiSelect.Custom.RMB">
<action name="DTICustomActionForMulti" type="customization"/>
<!-- DTI Custom Multi-Select Action -->
</model>

<model name="DTI.Explorer.Document.SingleSelect.Custom.RMB">
<action name="DTICustomAction" type="customization"/>
<!-- DTI Custom Action -->
</model>

<model name="DTI.Explorer.Folder.SingleSelect.Custom.RMB">
<action name="DTICustomActionFolder" type="customization"/>
<!-- DTI Custom Folder Action -->
</model>

</actionmodels>

5. Restart the Windchill server.

Client-Side Steps
Either manually copy wtCustomExplorerActions.xml from
<Windchill>/prog_examples/DTI_Customization/src_web/com/ptc/windchill/
enterprise/nativeapp/msoi/client/custom

1618 Customization Guide


to the following location:
<Windchill>/codebase/com/ptc/windchill/enterprise/nativeapp/msoi/client/custom

Or run the Ant script located under the src and src_web folders under
<Windchill>/prog_examples/DTI_Customization.

Implementation Example
The following example adds a New Link action to Windows Explorer.
1. Add the following lines to <Windchill>\codebase\config\
actions\custom-actionsModels.xml:
<model name="DTI.Explorer.Folder.SingleSelect.Custom.RMB">
<action name="add_link" type="bookmark" /> < !-- New Link -->
</model>
2. Add the following lines to <Windchill>\codebase\com\ptc\
windchill\enterprise\nativeapp\msoi\client\custom\
wtCustomExplorerActions.xml:
<command key="add_link">
<action serverAction="bookmark.add_link" type="WIZARD"/>
</command>
3. Restart the method server.
4. Close Windows Explorer and stop WTWindows.exe.
5. Restart Windows Explorer and connect to the Windchill server.

DTI Customization Framework 1619


Customize the DTI Document Search
Window
You can customize the Find document to download window using
pickerAttributes.xml:

The document search relies on Solr for indexing.


1. Navigate to the following file:
<Windchill>\codebase\pickerAttributes.xml
2. Locate the DTISearch component.
3. Add or remove attributes. For more information, see Configuring Pickers on
page 1006.
4. Restart the method server.

1620 Customization Guide


Using DTI with Form-Based
Authentication
If you want to use form-based authentication with your DTI implementation,
additional configuration is required.
Out-of-the-box, the DTILogin action of the connect command is defined as
HTTP. In order to use form-based authentication, it must be defined as WIZARD.
This change only needs to be done once, and should be done when you are
configuring the Windchill server for form-based authentication. All DTI clients
implement the changes when they reconnect to the Windchill server.
1. Navigate to the following directory:
<Windchill>\codebase\com\ptc\windchill\enterprise\
nativeapp\msoi\client\xml
2. Locate the following files:
• wtDesktop.xml
• wtOffice.xml
• wtWindows.xml
3. In each file, replace the following line:
<action serverAction="DTILogin" type="HTTP"></action>
with
<action serverAction="DTILogin" type="WIZARD"></
action>
For general information on form-based authentication in Windchill see the
“Authentication” section of the Windchill Advanced Deployment Guide

DTI Customization Framework 1621


38
Customizing Action Item
Attributes
Customizable Action Item Attributes........................................................................ 1624

Action items have several customizable attributes. These attributes cover a variety
of formats such as date, percentage, numbers with decimals, and strings.

Note
The following topics only apply to Windchill ProjectLink users.

1623
Customizable Action Item Attributes
Some customizable attributes are exposed in the user interface by default. These
attributes are all modeled attributes to ensure the best performance and scalability.
For more information, see the following topics:
• Attribute Customization on page 658
• Attribute Panels on page 348
You can customize action item attributes by modifying
attributeConfig.xml in the code base:
• Expose or hide attributes on page 1626
• Reorder attributes on page 1626
• Designate which attributes should be required on page 1627
• You can also create or modify the attribute display names through the
associated resource bundle. For information on modifying display names, see
Changing Displayed Text Found in RBINFO Files on page 109.
The following table describes the customizable action item attributes that are
displayed by default:

Exposed by Default

Display Name Description


Actual Effort Integer number of hours
Comments String up to 4000 characters
Cost Impact Monetary real number
Estimated Effort Integer number of hours
Impact String up to 4000 characters
Probability String up to 200 characters
Rank Integer
Resources String up to 4000 characters
Risk Enumerated value (same as for
activities):
• Unavailable
• Very High
• High
• Medium
• Low
• Very Low
Risk Description String up to 4000 characters
Risk Type String up to 200 characters

1624 Customization Guide


The following table describes the customizable action item attributes that are
hidden by default:

Hidden by Default

Display Name Description


Action Plan String up to 4000 characters
Contacts String up to 4000 characters
Contingency String up to 4000 characters
Cost Monetary real number
Customers String up to 4000 characters
Date Date
Design Cost Monetary real number
Location String up to 4000 characters
Percent %
Phase String – 200 characters
Prevention String up to 4000 characters
Production Cost Monetary real number
Quantity Integer
Schedule Impact + or – days
Size Real number
Suppliers String up to 4000 characters
Supporting Information String up to 4000 characters
Time hh:mm
Tooling Cost Monetary real number

Customizing Action Item Attributes 1625


Exposing or Hiding Customizable Attributes

Note
When performing an advanced search on action items, all attributes are
available, including those not currently exposed in the user interface.

To expose or hide a customizable attribute in the user interface:


1. Open the attributeConfig.xml file saved in the following location:
<Windchill>/codebase/wt/meeting/actionitem
Where <Windchill> is the Windchill installation directory.
2. Locate the <attribute> element you want to expose or hide.
• To expose an attribute, set the enabled value to “true”.
• To hide an attribute, set the enabled value to “false”.
The following example from attributeConfig.xml shows that the
Comments field is configured to be exposed in the user interface:
<attribute resourceKey="comments"
enabled="true"
order="40"
required="false"
resourceBundle="wt.meeting.actionitem.actionitemModelRB"
displayType="textBox"
internalName="Comments"
type="java.lang.String"/>

Reordering Customizable Attributes


To reorder customizable attributes in the user interface:
1. Open the attributeConfig.xml file saved in the following location:
<Windchill>/codebase/wt/meeting/actionitem
Where <Windchill> is the Windchill installation directory.
2. Locate the <attribute> elements you want to reorder.
3. Assign values to the order attribute of each element in the numeric order in
which you want the attributes to display.

1626 Customization Guide


Designating Customizable Attributes as Required
To designate a customizable attribute as required:
1. Open the attributeConfig.xml file saved in the following location:
<Windchill>/codebase/wt/meeting/actionitem
Where <Windchill> is the Windchill installation directory.
2. Locate the <attribute> elements you want to designate as required.
• To require an attribute, set the required value to “true”.
• To make an attribute optional, set the required value to “false”.

Customizing Action Item Attributes 1627


39
Customizations for PDM
Customizing the HTML Client Object Selection Page ............................................... 1630
Customizing Auto Associate................................................................................... 1638
Enabling Support for Custom Parts ......................................................................... 1646
Customizing the Parameters in the Download Service.............................................. 1648

This section describes customizations that apply to interactions with Creo


Elements/Pro 5.0 and other CAD applications.

1629
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.PickerSearchAttri
buteListDelegate is used. The default configured
PickerSearchAttributeListDelegate is
com.ptc.windchill.cadx.common.picker.PickerSearchAttri
buteList. 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 on page 1632.)
If this PickerSearchAttributeListDelegate implementation is not
sufficient, then you can create and configure your own
PickerSearchAttributeList to be used by the object selection page.

Note
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.PickerSearchAttri
buteListDelegate or create a class which sub-classes
com.ptc.windchill.cadx.common.picker.PickerSearchAttri
buteList.
See the javadoc for PickerSearchAttributeListDelegate and
PickerSearchAttributeList and their methods for more details.

1630 Customization Guide


Note
PickerSearchAttributeList extends SearchAttributeList;
therefore, the custom class can be used as the
SearchAttributeListDelegate and
PickerSearchAttributeListDelegate.

Note
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.pickerSearchAt
tributeList=<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>

Customizations for PDM 1631


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.

Note
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];

1632 Customization Guide


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";

Customizations for PDM 1633


// **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

1634 Customization Guide


// 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);
}
/**
*

Customizations for PDM 1635


* <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.

1636 Customization Guide


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.

Customizations for PDM 1637


Customizing Auto Associate
Auto Associate functionality can be customized in the following ways:
• Modifying the implementation of the
AutoAssociatePartFinderCreator interface
• Modifying the implementation to search for Customized parts or custom parts
• Customizing the Type of CAD documents that can be actively associated
• Preventing the creation of Parts by Auto Associate
• Controlling the default location of parts created by Auto Associate

Note
This functionality is applicable to every Windchill Workgroup Manager that
integrates with 3rd party CAD tools.

Each of these customizations is described in the following sections.

Note
Preferences that control naming and numbering of parts created during Auto
Associate are discussed in the “Preferences for Naming and Numbering” help
topic in the Windchill Help Center. Also listed in the table of Auto Associate
preferences in the “Operations Preferences” topic in the Windchill Help
Center section, along with the preferences discussed in the following sections
on Auto Associate.

1638 Customization Guide


Using and Modifying the
AutoAssociatePartFinderCreator Interface
AutoAssociate uses the implementation of the
AutoAssociatePartFinderCreator interface to perform the following
actions:
• To search a for matching part
• To create a new part
By default, the AutoAssociate action uses the default implementation of this
interface to perform the above-mentioned tasks; however, you can customize the
how they are performed using a customized implementation of
AutoAssociatePartFinderCreator interface.
The interface is located in
com.ptc.windchill.cadx.autoassociate.AutoAssociatePart
FinderCreator.
The AutoAssociatePartFinderCreator interface supports the following
methods:
• findOrCreateWTPart method used to search for matching part for a
selected EPMDocument or ModelItem
• CreateNewWTPart method used to create new part
• findWTPart method (no longer used)
• isNewPart method (no longer used)
• setIsNewPart method (no longer used)

Note
Even though some methods of the interface are deprecated and no longer used,
the implementation class should have dummy implementations of these
methods in order to compile the class.

Use the following procedure to implement a customized


AutoAssociatePartFinderCreator:
1. Derive your customized class as follows:
public class CustomFinderCreator implements
AutoAssociatePartFinderCreator

2. Override the following methods:


• public WTPart findOrCreateWTPart(EPMDocument
epmDoc, EPMWorkspace workspace)

Customizations for PDM 1639


This method is invoked for each document selected for auto-associate to
search for any matching part. You can customize the criteria used to search
the part, and the returned part is used by the action to associate to the
document.
• public WTPart findOrCreateWTPart(EPMDocument doc,
ModelItem modelItem, EPMWorkspace workspace)
This method is invoked for each document selected for auto-associate to
search for any matching part. You can customize the criteria used to search
the part, and the returned part is used by the action to associate to the
document.
• public WTPart
createNewWTPart(AssociatePartDescriptor
newPartDescriptor)
This method is invoked for each document selected for auto-associate to
create a new part. You can customize the properties of the newly created
part. The newly created part is associated to the document by the auto-
associate action.

Note
The following methods are deprecated and not currently used by the
action; however, you need to provide a dummy implementation of these
methods to compile the class properly.

• public boolean isIsNewPart()


• public void setIsNewPart(boolean a_IsNewPart)
• public WTPart findWTPart(EPMDocument epmDoc)
• public WTPart findWTPart(EPMDocument epmDoc,
ModelItem modelItem)
Compile the file and place the class in any appropriate location
3. Set the preference Operation ▶ Auto Associate ▶ Custom Class for Auto
Associate Part to specify the name of the class that implements
AutoAssociatePartFinderCreator interface.
4. Restart the method server

1640 Customization Guide


Modifying the Implementation to Search for
Customized Parts or Custom Parts
When performing searches, the default implementation is to search for a WTPart.

Note
When you create a customized part, its master must be WTPartMaster or a
subclass of WTPartMaster. The customized part itself must be a WTPart
or a subclass of WTPart.

To customize the implementation to search for a customized part that has been
implemented in the codebase (for example,
wt.part.MyCustomPartMaster), set the preference, Operation ▶ Auto
Associate ▶ Custom Class for Auto Associate Part to
wt.part.MyCustomPartMaster.

Customizations for PDM 1641


Controlling the Associations Formed by Auto
Associate
Several preferences affect the type of associations formed during Auto Associate
and the type of CAD documents that are allowed to form them.

Note
1. Model items with .prt and .asm extensions are not subject to the following
preferences. If you want to add or remove a model item type that is valid for
association, then you need to explicitly identify all types or sub-types that
should associate.

The preference, Operation ▶ Auto Associate ▶ Disallow Product Structure Links for
CAD Document Types, allows you to specify the CAD document types which
cannot form an Owner association. These are comma-separated values. The
default is <no value>.
The preference, Operation ▶ Auto Associate ▶ Disallow Product Structure Links for
CAD Document Sub-Types, allows you to specify the CAD document sub-types
which cannot form an Owner association. These are comma-separated values. The
default is <no value>.

Note
The allowable values for the preferences, Disallow Product Structure Links by
Document Types and Disallow Product Structure Links by Document Sub-
Types, are listed in the table of Auto Associate preferences in the “Operations
Preferences” section of the Windchill Help Center.

The preference, Operation ▶ Auto Associate ▶ Create Alternate Link On Check In,
when set to "Yes," allows a CAD-document-to-part association of the next
available type (that is, Content) to be created if the matching part found during
Auto Associate already has an Owner association, and allows the checkin to
continue. The default is "No" (no Content association is formed and the check in
fails with an overridable conflict).

1642 Customization Guide


Controlling the Creation of Parts by Auto Associate
The preference, Operation ▶ Auto Associate ▶ Create Associate New Part, specifies
whether a new part should be created if a matching part is not found by Auto
Associate. The default is "Owner Only" for all CAD tools. ECAD authoring
applications default to "All".
Possible values are:
• Owner Only: If a matching part is not found, a new part is created when the
CAD document would associate to a part with an "Owner" association.
• Owner and Contributing Image: If a matching part is not found, a new part is
created when the CAD document would associate to a part with either an
"Owner" or "Contributing Image" association.
• All: If a matching part is not found, a new part is created when the CAD
document would associate to a part with any product structure association
("Owner", "Contributing Image", and "Image").
• Never: A new part is not created if an existing part is not found, even if it
contributes to product structure. Auto associate does not fail, the CAD
document is skipped, and other selected CAD documents will try to associate.

Controlling the Default Location of Parts Created by


Auto Associate
The preference, Operation ▶ Auto Associate ▶ Store New Parts with CAD
Documents, when set to "Yes," specifies that the storage location of new part
created during Auto Associate be the same as its associated CAD document. By
default, the preference is set to "No."

Customizations for PDM 1643


Auto Associate Example
Create and compile <WT_HOME>src\com\ptcts\autoassociate\
CustomizedAutoAssociatePartFinderCreator.java with the
following source.
// package com.ptc.windchill.uwgm.cadx.autoassociate;
package com.ptcts;

import java.lang.String;
import wt.epm.EPMDocument;
import wt.epm.workspaces.EPMWorkspace;
import wt.part.WTPart;
import wt.pom.UniquenessException;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.VersionControlException;
// import com.ptc.windchill.uwgm.task.autoassociate.
efaultAutoAssociatePartFinderCreator;
import com.ptc.windchill.uwgm.common.autoassociate.
efaultAutoAssociatePartFinderCreator;
// import com.ptc.windchill.cadx.autoassociate.
utoAssociatePartFinderCreator;
import com.ptc.windchill.uwgm.common.autoassociate.
utoAssociatePartFinderCreator;
import wt.type.TypedUtilityServiceHelper;
import com.ptc.windchill.uwgm.common.associate.
ssociatePartDescriptor;
import wt.inf.container.WTContainer;
import java.rmi.RemoteException;

public class CustomizedAutoAssociatePartFinderCreator extends


DefaultAutoAssociatePartFinderCreator implements AutoAssociatePartFinderCreator
{

public boolean isIsNewPart()


{
System.out.println("Invoked CustomizedAutoAssociatePartFinderCreator
:: isIsNewPart()");
return super.isIsNewPart();
}

public void setIsNewPart( boolean a_IsNewPart ) throws WTPropertyVetoException


{
System.out.println("Invoked CustomizedAutoAssociatePartFinderCreator
:: setIsNewPart()");
super.setIsNewPart(a_IsNewPart);
}

public WTPart findOrCreateWTPart(EPMDocument epmDoc, EPMWorkspace workspace)


throws WTException, WTPropertyVetoException,
VersionControlException, UniquenessException

1644 Customization Guide


{
System.out.println("Invoked CustomizedAutoAssociatePartFinderCreator
:: findOrCreateWTPart()");
return super.findOrCreateWTPart(epmDoc, workspace);
}

public WTPart findWTPart(EPMDocument epmDoc) throws WTException


{
System.out.println("Invoked CustomizedAutoAssociatePartFinderCreator
:: findWTPart()");
return super.findWTPart(epmDoc);
}

public WTPart createNewWTPart(AssociatePartDescriptor newPartDescriptor)


throws WTException, WTPropertyVetoException {

System.out.println("Invoked CustomizedAutoAssociatePartFinderCreator
:: createNewWTPart()");

// get epmdoc
EPMDocument epmDoc = newPartDescriptor.getSourceDoc();

// get workspace
EPMWorkspace ws = newPartDescriptor.getEPMWorkspace();

// get workspace container


WTContainer container = ws.getContainer();

// create wtpart with super class


WTPart newpart = super.createNewWTPart(newPartDescriptor);

// manipulate new part, e.g. set attributes

// return modified new part


return newpart;
}

Customizations for PDM 1645


Enabling Support for Custom Parts
In the Creo Parametric HTML client, you can enable support for custom parts,
which extend wt.part.WTPart; however, a custom part must be modeled
before any changes are made to the Creo Parametric HTML client. (For more
information on extending the Windchill object model, see the Windchill
Specialized Administration Guide.)
The Creo Parametric HTML client permits use of custom parts in most operations,
including download, check out, check in, associate, disassociate, and so on;
however, the operations used to create parts, New ▶ Part and Auto Associate Part,
are specific to WTPart. Additionally, when you view the properties of a custom
part, any global attributes you may have added to the custom part can be seen;
however, newly modeled information is not displayed.

Note
This functionality is applicable to all Windchill Workgroup Managers
integrating with 3rd party CAD tools

Whenever "Part" is available in the object type list on the Creo Parametric HTML
client object selection page, if "Part" or "All" is selected, both WTPart objects
and custom part objects are listed in the page’s results table.
Automatic part generation is supported through the “Auto Associate Part” action
available on the workspace properties page. To enable automatic custom part
generation when using this command, however, you must either create or modify
your automatic part creator. For more information, see Customizing Auto
Associate on page 1638.

Modifying the Properties Page


To configure a custom part-specific properties page you have to create a properties
page and/or template processor. For details on how to do this, see theWindchill
Specialized Administration Guide.

Modifying the HTML Client Object Selection Page


To enable recognition of custom parts as a sub-class of WTPart and not just the
supported type in the Creo Parametric HTML client object selection page’s default
implementation, you must add support for the custom part in the configured
wt.query.SearchAttributeListDelegate. (For more information see
Customizing the HTML Client Object Selection Page on page 1630.)

1646 Customization Guide


In addition you must modify the Creo Parametric HTML files that use the object
selection page, and use the xconfmanager modify or override the type list ID
entries in com\ptc\windchill\cadx\propfiles\
picker.properties.

Note
For wt.query.SearchAttributeList, which is the default
configured search attribute list, the type ID is referred to as the query value.
(For more information, see Customizing the HTML Client Object Selection
Page on page 1630).

Replacing WTPart
If you want your site to only use custom part and not WTParts, then do the
following:
1. Add custom part support to HTML Search.
2. In picker.properties, use the xconfmanager to change the type list
entries that contain a type ID for WTPart to the custom part type ID you
created in Step 1.
3. Restart the method server.

Supporting WTPart and Custom Part


If your site will be using both WTParts and custom parts, then do the following:
1. Add custom part support to HTML Search.
2. In picker.properties, use the xconfmanager to add to the type list
entries that contain a type ID for WTPart the custom part type ID you created
in step 1.
3. To add an “All” type list entry for a type list, add an entry with the ALL type
ID used by the configured search attribute list.
4. Restart the method server.

Customizations for PDM 1647


Customizing the Parameters in the
Download Service
Windchill provides a server-side delegate that can be used to insert parameters
into a Creo Parametric model upon download. This mechanism can be used to
pass information from the server down to Creo Parametric, where it can be used
like any other Creo Parametric parameter (for example, to place information on
drawing forms). Parameters beginning with “PTC” or “PROI” are regarded as
reserved system parameters and cannot be propagated by the customization. If
they are added in the customization, they are ignored by the download service.

Note
This functionality is applicable to all Windchill Workgroup Managers
integrating with 3rd party CAD tools

Note
The customized parameters are provided to the client upon download and,
unlike system parameters such as PTC_WM_ITERATION, are not updated in
the Creo Parametric session or the local cache after a Windchill operation (for
example, check in).

For example, if a customized parameter is assigned the value of the CAD


document number, its value is provided to the client upon model download. If the
CAD document is later renumbered, the value in the Creo Parametric session or
the client cache will not be automatically updated.
The Windchill service delegate mechanism is used to allow the customization.
The following steps explain the customization process:
1. Create a Java class that implements the interface
ModeledAttributesDelegate. The interface definition is as follows:
package com.ptc.windchill.uwgm.proesrv.c11n;
import java.util.Collection;
import java.util.HashMap;
import wt.util.WTException;
public interface ModeledAttributesDelegate
{
/*
Implement this API to return list of parameters added by
customization along with it's type (customization profile of the
server). For example "WT_CADDOC_NUMBER" custom parameter will
be of type "String.class" (the java class)

1648 Customization Guide


*/
// getAvailableAttributes() returns
// HashMap<String, Object> which contains
// HashMap<Attribute name, Attribute type>
HashMap getAvailableAttributes();
/*
This is the API, invoked by the download service on download, to
be implemented for the customization. Create and return a
HashMap where key is input object and value is HashMap of
parameter name - value pairs that must be propagated to Pro/E
part represented by the EPMDocument (input object). Use the
getCADName() API on the EPMDocument to identify the Pro/E part
*/
// getModeledAttributes(Collection docs) returns
// HashMap<input object, HashMap<Attribute name, Attribute
value> HashMap getModeledAttributes(Collection docs) throws
WTException;
}
2. Edit site.xconf file (found in <Windchill>) to add following property
to indicate availability of customization service on the server:
<Service context="default"
name="com.ptc.windchill.uwgm.proesrv.c11n.ModeledAttributesDele
gate" targetFile=codebase/service.properties">

<Option cardinality="singleton"
requestor="java.lang.Object"
serviceClass="com.ptc.windchill.uwgm.proesrv.c11n.DefaultModele
dAttributesDelegate"/>

</Service>

Then use the xconfmanager tool to apply the changes to


service.properties file (run xconfmanager -p)
Use the path of your class in place of value of serviceClass (that is,
replace
com.ptc.windchill.uwgm.proesrv.c11n.DefaultModeledAt
tributesDelegate with the path to your class).
3. Restart the method server.

Customizations for PDM 1649


40
Reservation Service
Reservation Service APIs ...................................................................................... 1655
Using the Reservation Service................................................................................ 1655
Using the Reservation Client Tools ......................................................................... 1657
Using the Update Count Client Tools....................................................................... 1658
Adding the Undo Reservation Action to a Menu ....................................................... 1659
Sample Code: Reservation Service ........................................................................ 1660

The reservation service prevents users from simultaneously editing an object.


Use this service to restrict concurrent modification on an object by two or more
users without employing the Check Out and Check In actions or other locking
mechanism that modifies the object itself.
The reservation service consists of these primary components:
• A Windchill service that manages reservations for persisted objects.
• Client tools for adding reservation control to an edit window.
• Client tools for adding object update count control to an edit window.

Background
The reservation service was originally created to support concurrency control
when editing change management objects (for example, problem reports, change
requests, and change notices).
Change objects do not support the Check Out and Check In actions. As a result, it
was possible for two users to simultaneously initiate the Edit action on the same
object. When this happened, the system would save the updates of whichever user
saved their changes first. The other user would receive an error message and lose
all updates.

1651
With the reservation service implemented, change objects are reserved for a single
user as soon as they launch the Edit action. If another user attempts to edit the
object, they are immediately presented with an error message similar to the
following:

While originally created for change objects, the reservation service was designed
as a general purpose tool that can be used for a variety of other concurrent
modification scenarios.

Scope and Applicability


• Use the reservation service to manage concurrent updates of the same object
by two or more users.
• The reservation service is limited to Windchill objects that implement the
wt.reservation.Reservable interface.
• Site and organization administrators can release a reserved object for
modification by a different user.

Limitations
• Objects are reserved for a user, not for a session or a thread. This allows for
simultaneous modification of an object from multiple sessions or threads
running for the same user.
• When using the reservation service, the following enforcements are made:
○ Updates to a reserved object are detected and vetoed by a
PersistenceManagerEvent.UPDATE listener.
○ Deletions of a reserved object are detected and vetoed by a
PersistenceManagerEvent.PRE_DELETE listener.
If this level of enforcement is not appropriate for your application, then the

1652 Customization Guide


reservation service enforcement option should be disabled. Instead, you should
create an application-specific service to provide the required enforcement.
• Objects are reserved for only a limited time and are released to allow
modification by a different user when a reservation expires. The default is two
hours. This time limit is controlled by the following property:
Name ReservationService.expiresAfter
Location <Windchill>\codebase\wt.properties
Default 120
Synopsis The number of minutes before a reservation expires.
Description A reservation is placed when a user modifies a non-version
controlled object (for example, a change object).
The reservation is held until the user completes their
changes, cancels their changes, or a set amount of time has
passed. This property controls the number of minutes until a
reservation is automatically released.

Intended Outcome
Prevent unintentional concurrent modifications of a reservable object by two or
more users in a predictable and user-friendly manner.
For example, when a user attempts to edit a problem report that is already being
edited by a user named “Jane Smith,” the following message appears:

When the user clicks OK, the message and edit window closes. The user can try
again later.

Reservation Service 1653


As another example, if the user attempts to perform a Set State action on a
problem report currently being edited by a user named “Jane Smith,” the
following message appears:

The reservation service can also be used to prevent simultaneous modification of


an object when no user interface is presented (for example, by another Windchill
service).

1654 Customization Guide


Reservation Service APIs
Reservation service APIs require the following Java interfaces and classes located
in the wt.reservation package:
Name Description
Reservable Interface
Tags a Windchill object for use by the
reservation service.
Reservation Class
Instances of this class describe a reservation for a
Reservable object.
ReservationHelper Class
Methods in this class are used to access
reservation information.
ReservationService Interface
Defines the reservation service APIs.
ReservationType Type
Enumerated type describing the reservation types
available.

Note
Currently the only supported type available is
Modify, but other types might be added in
the future.
For more information, including all supported methods and elements, see the
Windchill Javadoc.

Using the Reservation Service


Creating a Reservation Object
Many of the reservation service APIs use a Reservation object to contain the
parameters that describe a desired reservation.
When creating a Reservation object you must always specify a reference to a
Reservable object. Other parameters are optional:
• Reservation type (Default—ReservationType.MODIFY)
• The user reserving the object (Default—Current user)
• Number of minutes to hold the reservation before it expires (Default—120
minutes)

Reservation Service 1655


• Enable or disable reservation enforcement by the reservation service (Default
—Disabled)
• Enable or disable administrator override of reservation enforcement (Default
—Disabled)
• Enable or disable workflow process override of reservation enforcement
(Default—Disabled)
For more information, see the Windchill Javadoc description of the
Reservation class.

Typical Reservation Service Implementation Steps


1. Reserve the object:
a. Call
ReservationHelper.getService().requestReserva
tion(…) to reserve the object.
b. Call the isGranted() method on the returned Reservation object to
determine if the reservation was successful.
If not, then the getErrorMessage() method can be called to obtain a
localizable message describing why the request failed.
For example, this step is performed when the change management Edit action
is initialized.
2. If a reservation is granted, then the action can proceed. Otherwise, take
appropriate steps to either wait and try again or inform the user that the action
cannot proceed.
For example, the change management Edit action either allows the user to
proceed with their modifications, or displays an error message:

1656 Customization Guide


3. If the action completes successfully:
a. To verify that the reservation still exists (for example, if the action has not
expired or been revoked by an administrator), call the following:
ReservationHelper.getService().checkGranted(…)
If the reservation no longer exists, then it can be requested again or the
action can be aborted. In order to prevent concurrent modifications, the
object should not be modified without a granted reservation.
b. Make database updates for the reserved object.
c. To free the object for modification by another user, call the following:
ReservationHelper.getService().releaseReserva
tion(…)
This call can be included in the same transaction used for the previous step
(3b), and the reservation is not released until the transaction is fully
committed. If the transaction fails to commit, then the reservation must be
released separately.
For example, this step is performed when the user clicks Finish.
4. If the action is canceled or does not complete successfully:
a. To free the object for modification by another user, call the following:
ReservationHelper.getService().releaseReserva
tion(…)
For example, this step is performed when the user clicks Cancel.

Using the Reservation Client Tools


Reservation client tools are available to simplify the implementation of
reservations in the Windchill user interface.
Simple additions to an action window JSP file automatically include the
implementation steps described in Typical Reservation Service Implementation
Steps on page 1656.
To include reservations in an action window, add the following lines to the JSP
file:
• Declare the reservation tag library:
<%@ taglib prefix="rwiz" uri="http://www.ptc.com/windchill/taglib/reservation"%>
• Use the configureReservation tag:
<rwiz:configureReservation reservationType="modify" enforcedByService="<true|false>"
adminOverride="<true|false>" workflowOverride="<true|false>"/>

Reservation Service 1657


The reservationType parameter is required and currently must be set to
modify. The remaining parameters are optional and can be set to true or
false (the default is false).
For more information, see the Windchill Javadoc description of the
Reservation class.
For an example of how the reservation client tool is used, see Sample Code:
Reservation Service on page 1660.

Using the Update Count Client Tools


In addition to reserving an object, another form of concurrency control is
validation of an object’s update count.
Every Windchill object stored in the database has an update count value that is
incremented whenever the object is updated. Validating that an object’s update
count remains the same from the start to the end of an action guarantees that a
concurrent update has not occurred.
If an object’s update count increases between the time an action starts and just
before it attempts to save its changes, then a concurrent update has occurred and
any attempt to save the object either fails or overwrites the concurrent updates.
Update count client tools provide a simple way to implement update count
validation in a Windchill action. These can be used separately or jointly with
reservation client tools.
When an update count validation error occurs the following informative message
is given:

1658 Customization Guide


To include update counts in an action window, add the following lines to the JSP
file:
• Declare the reservation tag library:
<%@ taglib prefix="rwiz" uri="http://www.ptc.com/windchill/taglib/reservation"%>
• Use the handleUpdateCount tag:
<rwiz:handleUpdateCount/>

For an example of how the update count client tool is used, see Sample Code:
Reservation Service on page 1660.

Adding the Undo Reservation Action to a


Menu
An Undo Reservation action is provided for site and organization administrators to
immediately release a reserved object for modification by a different user.
This action is available in object menus for out-of-the-box Windchill objects that
use the reservation service.
For example, the change request information page includes this action:

The undoReservation action can be added to the action model of any object
that implements the wt.reservation.Reservable interface. For example,
the change request action model file includes the following undoReservation
entry:
<model name="more change request row actions" menufor="wt.change2.WTChangeRequest2">
:
:
<action name="undoReservation" type="reservation"/>
:
:
</model>

Reservation Service 1659


Sample Code: Reservation Service
The following example shows the lines added to the change request edit action
window. The code requires a reservation for the object being edited and performs
update count validation when editing is complete:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib prefix="cwiz" uri="http://www.ptc.com/windchill/taglib/changeWizards"%>
<%@ taglib prefix="rwiz" uri="http://www.ptc.com/windchill/taglib/reservation"%>
<%@ taglib uri="http://www.ptc.com/windchill/taglib/attachments" prefix="attachments"%>
<%@include file="/netmarkets/jsp/components/beginWizard.jspf"%>

<%@include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

<jca:initializeItem operation="${createBean.edit}"/>

<%@include file="/netmarkets/jsp/change/changeWizardConfig.jspf" %>


<%@include file="/netmarkets/jsp/annotation/wizardConfig.jspf" %>
<%@include file="/netmarkets/jsp/attachments/initAttachments.jspf"%>

<cwiz:initializeChangeWizard changeMode="EDIT"
varianceEffectivity="false" annotationUIContext="change"
changeItemClass="wt.change2.ChangeRequestIfc" />

<jca:wizard helpSelectorKey="change_editChangeRequest"
buttonList="DefaultWizardButtonsWithSubmitPrompt"
formProcessorController=
"com.ptc.windchill.enterprise.change2.forms.controllers.ChangeItemFormProcessorController">
<jca:wizardStep action="editAttributesWizStep" type="object" />
<jca:wizardStep action="affectedEndItemsStep" type="change" />
<jca:wizardStep action="affectedDataStep" type="change" />
<jca:wizardStep action="attachments_step" type="attachments" />
<jca:wizardStep action="associatedChangeIssuesStep" type="changeRequest" />
<jca:wizardStep action="associatedChangeItemsStep" type="change" />
</jca:wizard>

<rwiz:handleUpdateCount/>
<rwiz:configureReservation reservationType="modify"
nforcedByService="true" workflowOverride="true"/>
<attachments:fileSelectionAndUploadApplet/>

<script language='Javascript'>
change_postLoad();
</script>

<%@ include file="/netmarkets/jsp/util/end.jspf"%>

1660 Customization Guide


41
Data Exchange using Standards in
Windchill
Product Lifecycle Management Services, Version 2.0............................................... 1662
STEP Data Exchange using EXPRESS .................................................................. 1699

This section contains information on supported customizations for STEP.

1661
Product Lifecycle Management Services,
Version 2.0
Overview
The import and export functionality in Windchill is based on default Windchill
format. This functionality also supports the PLM Services 2.0 format. The PLM
Services import and export leverages the same infrastructure. In order to transform
the data from and to Windchill format to and from PLM service format, a standard
mapping file (<Windchill>\codebase\wt\ixb\impl\jaxb\plm\
mapping.xml) is created. This mapping file defines the element and attribute
mapping for all the elements. The out-of-the-box version of this mapping file is a
sample mapping provided by PTC that must be customized by end users for their
own business needs.

Additional Resources
For more information on Product Lifecycle Management Services Version 2.0, see
the Object Management Group’s website at:
• http://www.omg.org/spec/PLM/2.0/
For specific information on the InformationalModel.xsd schema, see:
• http://schema.omg.org/specs/PLM/2.0/schema/InformationalModel.xsd

1662 Customization Guide


PLM Message Format
The PLM message format is contained in the assembly.jar file. It contains the
following elements:
• CONTENTS (folder): Contains all the content files. These are not required
because sometimes content is not provided.
• manifest : This file contains the properties used during export, including
Windchill version and format. These are not required and you can set the
format type during call import function. However, if you want to import the jar
through the import/export manager UI, this is required.
• plm.xml : Contains all the business object information by PLM format,
which is required.
• importList.txt: Contains the exported object id, which is not required.
You can import without this file.

Data Exchange using Standards in Windchill 1663


PLM Mapping Information
This section contains details on the PLM Services support in Windchill 10.0. The
details of the mapping includes the list of supported objects, the data models,
sample mappings, and information on extending schemas.

Windchill Objects Supported for PLM Services 2.0


The import and export framework which is used to exchange data in Windchill
schema supports the import and export in PLM Services 2.0 format. Current
support is limited to the following Windchill objects:
• WTPart
• EPMDocument
• EPMMemberLink
• EPMDescribeLink
• EPMBuildHistory
• EPMBuildRule
• WTPartUsageLink
All required Windchill attributes are mapped for supported objects; if any other
optional attributes are to be mapped, this can be achieved through customization.
Customization to the out-of-the-box mapping is also possible and is discussed
later in this documentation.
If you want to use subtypes of any of the objects listed above (wherever
applicable), the subtypes will be automatically supported for PLM Services 2.0
format.

Windchill Data Model Supported for PLM Services 2.0


Note: Only objects highlighted with a green rectangle ( ) are supported.

Part Structure (WTPart and WTPartUsageLink)

1664 Customization Guide


EPMMemberLink

EPMDescribeLink

Data Exchange using Standards in Windchill 1665


mapping.xml file
A mapping file (mapping.xml) that defines the elements and attribute mapping
is used to convert Windchill native format (<Windchill>\loadXMLFiles\
standardx20.dtd) to PLM Services format (<Windchill>\codebase\
wt\ixb\schema\plm\informationalModel.xsd).
There are three types of mapping:
• alias_mapping
• value_reference_mapping
• element_mapping

Sample Mapping Name Patterns


We have used following conventions to represent mapped element name and
required attributes:
• Relative path, such as Template_instance/Name/value, get/set values by it.
• Absolute path for single element, such as /Digital_file, which means this
element is stored in the same level as current element instead of sub element.
• Alias path, such as alias_uid_for_item_version, which will be defined in alias_
mapping section as following:
<alias name="alias_uid_for_item_version" path="Item_version" attribute="uid"/>

This will be same as Item_version/uid, we can use alias to reduce duplicated


mapped name.
• Value reference path one, such as value_reference_classification_name, which
will be defined in value_reference_mapping section as following:
<value_reference name="value_reference_classification_name"
mapped_name="/Specific_item_classification"
path="Classification_name" ref_attribute="Associated_item"/>

This means to create a Specific_item_classification element in the same level


as current element and store value to Classification_name, also Specific_item_
classification will hold a reference of current element by Associated_item, we
can use value reference to reduce duplicated mapped name.
• Value reference path two, such as value_reference_File_format_path, which
will be defined in value_reference_mapping section as following:
<value_reference name="value_reference_File_format_path"
attribute_name="File_format"
ref_type="/Document_format_property">
<sub_value_reference attribute_name="Data_format"/>
</value_reference>

1666 Customization Guide


We will create a Document_format_property element, store the value to Data_
format also set the element to current element by File_format, we can use
value reference to reduce duplicated mapped name.

Tips
The following variables can be used in required_attributes:
• {ROOT} – Use the root object of this element
• {UUID} – Create a random UUID
• {KEY} – Use the name of the current attribute
• {VALUE} –Use the string representation of the current attribute’s value

Data Exchange using Standards in Windchill 1667


Details of the Mapping between Windchill and PLM Services
Alias Mapping
Defines alias for mapping path which can be used in mapped name and required
attributes in element mapping section, we will use this to reduce duplicated
mappings. This will be only relative path.
Parent Name Type Data Type Required? Descrip-
Name tion
alias_ exceptions element element no Sub alias
mapping/ mapping,
alias used with
type
attribute to
provide
different
alias
mapping by
different
attribute
values.
name attribute ID yes Unique
name of
alias
element.
path attribute string no Related
path to
store/
retrieve
value.
attribute attribute string no Attribute
name for
store/
retrieve
value, used
with path
together.

1668 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
type attribute string no Windchill
attribute
name to be
used to
identify a
different
alias.
The following mapping will be mapping for exceptions:
Parent Name Type Data Type Required? Descrip-
Name tion
exceptions value attribute string yes The value
of defined
type
attributes.
path attribute string no Related
path to
store/
retrieve
value.
attribute attribute string no Attribute
name for
store/
retrieve
value, used
with path
together.

Value Reference Mapping


Defines alias for mapping path which can be used in mapped name and required
attributes in element mapping section, we will use this to reduce duplicated
mappings. This will contain two kinds of path:
1. Element which hold a reference of current element, as following:
<Specific_item_classification uid="uid">
<Associated_item>ref_uid</Associated_item>
<Classification_name>assembly</Classification_name>
</Specific_item_classification>
<Item uid="ref_uid">

Data Exchange using Standards in Windchill 1669


</Item>

2. Element which will be reference by current element, as following:


<Document_file uid="uid">
<File_format>ref_uid</File_format>
</Document_file>
<Document_format_property uid="ref_uid">
<Data_format>ApplicationData</Data_format>
</Document_format_property>

Parent Name Type Data Type Required? Descrip-


Name tion
value_ exceptions element element no Used with
reference_ type
mapping/ attribute in
value_ element
reference mapping to
define
different
value
reference
mapping for
different
attribute
value.
sub_value_ element element no Sub value
reference reference
mapping,
used for
path No. 2
only.
name attribute ID yes Unique
name of
value
reference
element.
path attribute string no Related
path to
store/
retrieve
value, used
for path
No.1 only.
condition attribute string no Condition
to filter the

1670 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
element,
used for
path No.1
only,
support
following
pattern
only:
<key>=
<value>
mapped_ attribute string no Parent
name element
name for
the path,
used for
path No.1
only.
type attribute string no For path
No.1:The
relative path
to check if
current
element is a
supported
windchill
tag. for
example,
Item_shape
will also be
used to
represent
representa-
tion and
EPMDescri-
beLink.For
path No.2:
The element
name which
will be
create as

Data Exchange using Standards in Windchill 1671


Parent Name Type Data Type Required? Descrip-
Name tion
reference,
this should
be sub
element.
ref_attribute attribute string no The relative
path which
keeps the
object
reference,
used for
path No.1
only.
connect_ attribute string no The sub
reference element
which will
be used as
reference.
reuse attribute boolean no Defines if
this element
is reusable,
work with
locate_by
attribute
together to
find
previous
created
element
instead of
create new
one all the
time.
locate_by attribute string no Defines the
attribute list
of a
reusable
element,
separated
by a comma
(,).

1672 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
ref_type attribute string no The element
name which
will be
create as
reference,
this should
be root
element,
used for
path No.2
only.
required_ attribute string no Attributes
attributes which are
required for
current
element,
separated
by a comma
(,).It can be
relative path
and alias
path.
attribute_ attribute string no The relative
name path which
will be used
to hold
reference or
attribute
value, used
for path
No.2 only.
If identifier
is
configured,
it will be
used to
store the
name of
attribute.

Data Exchange using Standards in Windchill 1673


Parent Name Type Data Type Required? Descrip-
Name tion
identifier attribute string no The relative
path which
will be used
to hold
attribute
value,
works with
attribute_
name
together to
store
attribute
name and
value.
The following mapping will be mapping for exceptions:
Parent Name Type Data Type Required? Descrip-
Name tion
exceptions sub_value_ element element no Sub value
reference reference
mapping,
used for
path No. 2
only.
attribute_ attribute string no The relative
name path which
will be used
to hold
reference or
attribute
value, used
for path
No.2 only.
value attribute string no The
attribute
value to
choose
current
exception

1674 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
configura-
tion.
ref_type attribute string no The element
name which
will be
create as
reference,
this should
be sub
element,
used for
path No.2
only.
type attribute string no The element
name which
will be
create as
reference,
this should
be root
element,
used for
path No.2
only.
required_ attribute string no Attributes
attributes which are
required for
current
element,
separated
by a comma
(,).It can be
relative path
and alias
path.

The following mapping will be mapping for sub_value_reference_type

Data Exchange using Standards in Windchill 1675


Parent Name Type Data Type Required? Descrip-
Name tion
sub_value_ add_to_ element element no Element
reference_ element mapping
type which
current
element will
be added to.
reference_to element element no Element
mapping
which
current
element will
reference it.
attribute_ attribute string no The relative
name path which
will be used
to hold
reference or
attribute
value, used
for path
No.2 only.
If identifier
is
configured,
it will be
used to
store the
name of
attribute.
required_ attribute string no Attributes
attributes which are
required for
current
element,
separated
by a comma
(,).It can be
relative path
and alias
path.

1676 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
connect_ attribute string no The sub
reference element
which will
be used as
reference.
ref_type attribute string no The element
name which
will be
create as
reference,
this should
be root
element,
used for
path No.2
only.
unit_ attribute string no The relative
attribute_ path which
name will be used
to hold unit
attribute
value. Used
for path
No.2 and
global
attribute
only.
reuse attribute boolean no Defines if
this element
is reusable,
work with
locate_by
attribute
together to
find
previous
created
element
instead of
create new

Data Exchange using Standards in Windchill 1677


Parent Name Type Data Type Required? Descrip-
Name tion
one all the
time.
locate_by attribute string no Defines the
attribute list
of a
reusable
element,
separated
by a comma
(,).
identifier attribute string no The relative
path which
will be used
to hold
attribute
value,
works with
attribute_
name
together to
store
attribute
name and
value.
The following mapping will be mapping for add_to_element and reference_to:
Parent Name Type Data Type Required? Descrip-
Name tion
add_to_ name attribute string yes Path which
element is used to
add current
element to
another
element. It
can be
relative path
and alias
path.
value attribute string yes The value
which will

1678 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
be used to
find parent
element.
reference_to name attribute string yes Path which
is used to
reference
another
element. It
can be
relative path
and alias
path.
value attribute string yes The value
which will
be used to
find another
element.
connect_ attribute string yes The sub
reference element
which will
be used as
reference

Note
Use following pattern to define value attribute:
{ROOT}/usedBy/ObjectReference/ufid, this means to get value of attribute
named ‘usedBy/ObjectReference/ufid’ from current element.

Element Mapping
Define the mapping from Windchill native element (or attribute) to other formats.
There are two kinds of mappings: element and attribute. Element mapping can
contain element_mapping or attribute mapping as sub elements.
Parent Name Type Data Type Required? Descrip-
Name tion
element_ element element element yes Root
mapping element
mapping

Data Exchange using Standards in Windchill 1679


Parent Name Type Data Type Required? Descrip-
Name tion
root_tag_ attribute string yes Local name
name of the root
element.
id_tag attribute string no Attribute
name whose
type is xsd:
ID.
ref_tag attribute string no Attribute
name whose
type is xsd:
IDREF,
which is
used
globally.
required_ attribute string no Required
attributes attributes of
the root
element,
separated
by comma
(,).

The following will be mapping for element:


Parent Name Type Data Type Required? Descrip-
Name tion
element element element element no Sub element
mapping
attribute element element no Attributes
mapping
under
current
element
name attribute string yes Element
name of
windchill
native
format.
mapped_ attribute string yes Mapped
name element
name

1680 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
reuse attribute boolean no Defines
whether the
element
should be
retrieved
from
previous
exported
ones instead
of creating
new one,
used with
use_for_
reuse in
attribute
mapping
together to
find
exported
element
default_ attribute string no Mapped
mapped_ element
name_for_ name (with
attributes attribute
element
name and
value
element
name)
which is
used to
store the
attributes
which do
not have
explicit
mappings.
This should
be the name
of a value

Data Exchange using Standards in Windchill 1681


Parent Name Type Data Type Required? Descrip-
Name tion
reference
mapping.
required_ attribute string no Attributes
attributes of the
element
which are
required but
cannot be
set during
export,
separated
by a comma
(,). It can
hold
relative
path, alias
path and
value
reference
path.
type attribute string no Windchill
attribute
name to be
used to
identify a
different
alias or
value
reference.
mapped_ attribute string no Element
tag_name name and
value to
identify
current
windchill
element. It
is used if
one PLM
element is
used to

1682 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
represent
multiple
windchill
elements.
import_ attribute string no Decide
context windchill
element
name by
value of
parent
element,
mapping
between
element
name and
value of
parent
element
should be
one-one.
add_ attribute string no The path
current_ used to add
element_to_ current
parent_by element to
parent one.
It can hold
relative
path, alias
path and
value
reference
path. This
will be used
for sub
element
only.

Data Exchange using Standards in Windchill 1683


Parent Name Type Data Type Required? Descrip-
Name tion
connect_ attribute string no The sub
reference element
which will
be used to
be added to
parent
element,
used with
add_
current_
element_to_
parent_by
together .

The fllowing will be mapping for attribute:


Parent Name Type Data Type Required? Descrip-
Name tion
attribute exceptions element element no Used to
hold
different
attribute
mapping by
different
attribute
value.
name attribute string yes Element
name of
windchill
native
format.
mapped_ attribute string yes Mapped
name element
name. It can
be relative
path, alias
path and
value
reference
path.
Separated

1684 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
by a comma
(,).
append attribute boolean no Defines
whether to
append to
the existing
value with
defined
separator,
default
value is
false. For
example,
this can be
used to
append the
iteration
number to
the version
(A.5, where
the value 5
is appended
to A with a
period [.]
separator).
seperator attribute string no Separator
for append.
For
example,
this can be
used to
concatenate
the iteration
number to
version
(A.5, where
the value 5
is appended
to A with a
period [.]

Data Exchange using Standards in Windchill 1685


Parent Name Type Data Type Required? Descrip-
Name tion
separator).
add_to_ attribute string no Define the
element path which
current
element
should be
added after
finding a
previously
exported
element.It
can be
relative
path, alias
path and
value
reference
path.Used
for link
element
only.
use_for_ attribute boolean no Defines
reuse whether the
attribute
should be
used to find
previously
exported
element,
used with
reuse in
element
mapping
together.
connect_ attribute string no The sub
reference element
which will
be used to
be added to
parent

1686 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
element,
used with
add_
current_
element_to_
parent_by
together.
reference_to attribute string no Defines the
sub element
used as
reference.
Used for
link element
only.
Default
value is
false.
identifier attribute string no Attribute
name which
is used to
retrieve
value from
default_
mapped_
name_for_
attributes
configura-
tion. If this
is
configured,
mapped_
name will
not be used
during
import.
reuse attribute boolean no Define
whether the
attribute
value can be
multiple. If

Data Exchange using Standards in Windchill 1687


Parent Name Type Data Type Required? Descrip-
Name tion
set to false,
multiple
values can
be retrieved
during
import.
Must be
used when
mapped_
name is not
configured.
Default
value is
false.
value attribute string no This is used
to represent
a constant
value,
which will
be set
during
export and
can be
fetched
during
import
required_ attribute string no Attributes
attributes which are
required for
current
element,
separated
by a comma
(,).It can be
relative
path, alias
path and
value
reference
path.

1688 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
add_ attribute string no The path
current_ used to add
element_to_ current
parent_by element to
parent one.
It can hold
relative
path, alias
path and
value
reference
path. This
will be used
for sub
element
only.

required_ attribute string no Attributes


attributes_ which are
for_parent required for
parent
element,
separated
by a comma
(,).It can be
relative
path, alias
path and
value
reference
path.
Worked
with add_
current_
element_to_
parent_by
together to
set
attributes
basing on

Data Exchange using Standards in Windchill 1689


Parent Name Type Data Type Required? Descrip-
Name tion
different
attribute
value
use_parent_ attribute boolean no Define
object whether to
use parent
element as
reference to
find related
element and
store/
retrieve
attribute
value.
Default
value is
false.
index attribute int no Define the
index to get
value from
a list value.
Following will be mapping for attribute exceptions:
Parent Name Type Data Type Required? Descrip-
Name tion
exceptions value attribute string yes Value of
parent
attribute.
mapped_ attribute string no Mapped
value value for
original
value, it
should be
one-one
mapping.
attribute_ attribute string no Element
name name which
is used to
store the
attribute
value. It can

1690 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
be relative
path, alias
path and
value
reference
path. Will
not set
attribute
when
mapped_
element_
name is
configured
mapped_ attribute string no Element
element_ name which
name is used to
identify
original
value, it
should be
one to one
mapping,
used for
import only.
required_ attribute string no Attributes
attributes which are
required for
current
element,
separated
by a comma
(,).It can be
relative
path, alias
path and
value
reference
path.
add_ attribute string no The path
current_ used to add

Data Exchange using Standards in Windchill 1691


Parent Name Type Data Type Required? Descrip-
Name tion
element_to_ current
parent_by element to
parent one.
It can hold
relative
path, alias
path and
value
reference
path. This
will be used
for sub
element
only.
required_ attribute string no Attributes
attributes_ which are
for_parent required for
parent
element,
separated
by a comma
(,).It can be
relative
path, alias
path and
value
reference
path.
Worked
with add_
current_
element_to_
parent_by
together to
set
attributes
basing on
different
attribute
value

1692 Customization Guide


Parent Name Type Data Type Required? Descrip-
Name tion
connect_ attribute string no The sub
reference element
which will
be used to
be added to
parent
element,
used with
add_
current_
element_to_
parent_by
together
use_parent_ attribute boolean no Define
object whether to
use parent
element as
reference to
find related
element and
store/
retrieve
attribute
value.
Default
value is
false.

Data Exchange using Standards in Windchill 1693


Windchill Elements and Attributes Mapping for Supported Windchill Objects
The tables below explains the mapping between elements and attributes for some
of the key Windchill objects which are supported.

WTPart
Object Type = WTPart
PLM Root Element = Item
Windchill Attribute PLM Element Description
Name
number Id
ObjectID/ufid Item_version/uid original value will be
stored as key-value pair
masterUfid uid original value will be
stored as key-value pair
name Name
versionInfo/versionId Item_version/Id concatenate as A.2
versionInfo/iterationId
BusinessFields/ String_value or See BusinessFields /
BusinessField Numerical_value BusinessField on page
1698 for element specific
mapping for exact
mapping.
Use Item_version/
Design_discipline_item_
definition/Simple_
property_association/
Specified_value to build
relationship with String_
Value/Numeric_Value

1694 Customization Guide


Windchill Attribute PLM Element Description
Name
contentItem Digital_file Use Document_
assignment to build
relationship with Item
endItem String_value Use Item_version/
defaultTraceCode Design_discipline_item_
definition/Simple_
genericType property_association/
partType Specified_value to build
folderPath relationship with item.
The value is stored as a
lifecycleInfo/ key-value pair, as
lifecycleTemplateName
following:
versionInfo/versionLevel <Property_value
xsi:type="String_value">
domainName <Value_name>
lifecycleInfo/ endItem</Value_name>
<Value_specification>false
lifecycleState
</Value_specification>
externalTypeId </Property_value>

EPMDocument
Object Type = EPMDocument
PLM Root Element = Item
Windchill Attribute PLM Element Description
Name
number Id
ObjectID/ufid Item_version/uid orginal value will be
stored as key-value pair
name Name
CADName Item_version/Design_
discipline_item_
definition/Item_instance/
Id
versionInfo/versionId Item_version/Id concat as A.2
versionInfo/iterationId
BusinessFields/ String_value or See BusinessFields /
BusinessField Numerical_value BusinessField on page
1698 for element specific
mapping for exact
mapping.

Data Exchange using Standards in Windchill 1695


Windchill Attribute PLM Element Description
Name
Use Item_version/
Design_discipline_item_
definition/Simple_
property_association/
Specified_value to build
relationship with String_
Value/Numeric_Value
contentItem Digital_file Use Item_version/
Design_discipline_item_
definition/Document_
assignment to build
relationship with item for
secondary content. Use
Item_shape to build
relationship with item for
primary content.
masterUfid String_ value Use Item_version/
authoringApplication Design_discipline_item_
definition/Simple_
epmDocType property_association/
derived Specified_value to build
domainName relationship with item.
The value is stored as a
folderPath key-value pair, as
lifecycleInfo/ following:
lifecycleTemplateName <Property_value
xsi:type="String_value">
lifecycleInfo/
<Value_name>
lifecycleState derived
</Value_name>
versionInfo/versionLevel
<Value_specification>
epmDocSubType false
</Value_specification>
externalTypeId </Property_value>

EPMMemberLink
Object Type = EPMMemberLink
PLM Root Element = Next_higher_assembly

1696 Customization Guide


Windchill Attribute PLM Element Description
Name
BusinessFields/ String_value or See BusinessFields /
BusinessField Numerical_value BusinessField on page
1698 for element specific
mapping for exact
mapping.
Use Simple_property_
association/Specified_
value to build relationship
with String_Value/
Numeric_Value
ObjectID/localId uid Original value will be
stored as key-value pair
uses/ObjectReference/ Related
ufid
transform/matrix4d/m0* Direction Use Placement/Model_
placement/Axis1 to build
relationship with Next_
higher_assembly.
transform/matrix4d/m0* Direction Use Placement/Model_
placement/Axis2 to build
relationship with Next_
higher_assembly.
transform/matrix4d/m2* Direction Use Placement/Model_
placement/Axis3 to build
relationship with Next_
higher_assembly.

Data Exchange using Standards in Windchill 1697


Windchill Attribute PLM Element Description
Name
transform/matrix4d/m3* Cartesian_point Use Placement/Model_
placement/Local_origin
to build relationship with
Next_higher_assembly.
occurences/attribute String_value Use Simple_property_
name association/Specified_
value to build relationship
isAnnotated with item. The value is
asStoredChildName stored as a key-value pair,
depType as following:
<Property_value
isPlaced xsi:type="String_value">
<Value_name>
isRequired isAnnotated
externalTypeId </Value_name>
<Value_specification>
false<
/Value_specification>
</Property_value>

BusinessFields / BusinessField
Object Type = BusinessFields/BusinessField
PLM Root Element = String_Value / Numeric_Value depending upon datatype
Windchill Attribute PLM Element Description
Name
datatype General_property/ Creates an element
Property_type Genaral_Property and
datatypeQualifier General_property/ associates respective
Description values. Use Property_
value_representation/
Definition to build
relationship with
General_property.
value Value_component, Gets split into value, unit
Significant_digits, Unit_ and significant digits and
component/ Unit_name gets assigned to Value_
component, Significant_
digits, Unit_component
respectively.

1698 Customization Guide


STEP Data Exchange using EXPRESS
The Windchill STEP (Standard for Exchange of Protocol Data) connector allows
for the exchange of product data that is managed in Windchill in ISO 10303 STEP
format. The STEP connector has closely ingrained EXPRESS schema support.
EXPRESS is an information data modeling language that is used to define the
schema for all the ISO10303 STEP application protocols. The connector supports
the ASCII (P21) or XML (P28) file formats. The connectors provide support for
AP214 and PLCS standards.
• The AP214 connector supports processing of CAD, part structure, and related
documents including reusable attributes and content.
• The PLCS connector supports processing of parts and related documents along
with reusable attributes and file content. The connector provides support for
numerous templates that are used by A&D DEX1 and DEX3 (refer to
S3000L). There is also support to augment reference data definitions that
would be used in an exchange. The mapping between the reference data
definition and the part or document properties is configurable.

Data Exchange using Standards in Windchill 1699


STEP Foundation

Introduction to EXPRESS
EXPRESS is the modeling language used by STEP for defining the information
model for the data exchange. To support STEP-based data exchange using
EXPRESS Data Manager (EDM), Windchill provides EXPRESS schema-specific
definitions for its proprietary information model for data exchange. This model
represented in the form of DTD schema describes the information being
exchanged for various business objects (concepts) represented and managed in
Windchill.
This section details out the various constructs used to generate EXPRESS schema
from DTDs. This lets you see how to convert a Windchill DTD-specific object
model to an EXPRESS-specific object model using the EXPRESS Schema
Generator.

DTD — EXPRESS Schema Conversion


This section provides information on the differences between the DTD and the
EXPRESS schema.

Element Specifications
Elements in the DTD are specified as:
-- <!ELEMENT part (name, (number | ufid)*, item, (sun | mon | tue)+)>
The same elements are represented in the EXPRESS Schema Representation as:
ENTITY e_part;

name : STRING;

r_number : OPTIONAL LIST OF STRING;

ufid : OPTIONAL LIST OF STRING;

item : e_item;

sun : OPTIONAL LIST [1:?] OF STRING;

mon : OPTIONAL LIST [1:?] OF STRING;

tue : OPTIONAL LIST [1:?] OF STRING;

WHERE

wr1: (EXISTS ( sun ) OR EXISTS ( mon ) OR EXISTS ( tue ));

1700 Customization Guide


END_ENTITY;

Note
In the above example, the number is prefixed with r_. This is because
number is reserve word in EXPRESS schema language. All attributes from
DTD which match with reserve words in Express language are prefixed with
r_.

Enumerated List Specification in EXPRESS


An enumerated list is specified in the DTD using the following definition:
<!ELEMENT permissionKey EMPTY>

<!ATTLIST permissionKey value (-1|0|1|2|3|4|5|6|7) #REQUIRED>

An enumerated list is specified in the EXPRESS Schema Representation using the


following definition:
ENTITY e_permissionKey;

attr_value : STRING;

WHERE

check_attr_value: SELF.attr_value IN ['-1','0','1','2','3','4','5','6','7'];

END_ENTITY;

Note
For a sample DTD to EXPRESS entity conversion, see DTD to EXPRESS
Mapping on page 1733.

EXPRESS-X Mapping
The EXPRESS-X based mapping is used to convert a model/file specific from one
EXPRESS Schema into another. In a typical scenario, Windchill business objects
are represented in the Windchill EXPRESS Schema. The same is being converted
to an STEP AP Schema using WNCTOAPXXX EXPRESS-X Converter. This

Data Exchange using Standards in Windchill 1701


process is referred as the export process. The reverse conversion process that is,
from STEP AP schema to Windchill Schema, is being converted using
APXXXTOWNC EXPRESS Schema and is referred to as an import process.
STEP-based data exchange uses the EDMexpressXΤΜ mapping language to
convert data complying to one express schema to a data complying to other
express schema (for example, WC Express Schema to AP214 Schema or AP239
Schema to WC Schema).
For information on various mappings and underlying features see the EDMassist
website. This is the website of the EXPRESS Data Manager, which is a third-party
product that supports STEP.

STEP Import and Export Process


The following information details of how the standard IX framework that is
already part of Windchill core capabilities is used to facilitate product data
exchange using STEP standards

Export
This represents the typical flow of an
export operation
1. Collect: Identify what needs to be
exchanged. This step is out of scope
of STEP data exchange.
2. Establish source model confirming
to Windchill Express schema
Windchill Information Exchange
Model using Export Handlers
3. Validate the source model against
the Windchill Express schema
(Optional)
4. Convert to a target model
confirming to a specific application
protocol schema
5. Validate the target model against
the application protocol schema
(Optional)
6. Output to a file.

1702 Customization Guide


Import
This represents the typical flow of an
import operation
1. Read the input in specified AP
format
2. Create a source model populated
with the data from the step file
confirming to a specific application
protocol schema
3. Validate the source model against
the application protocol-specific
schema (Optional)
4. Convert to target model confirming
to the Windchill Express Schema
5. Validate the target model against
the Windchill Express Schema
(Optional)
6. Import the product data into
Windchill using the import handlers

AP214 Object Mapping


The following business objects are mapped to the AP214 information model:
• WTPart
• WTPartUsageLink
• WTDocument
• WTPartDescibeLink
• WTPartRefereneLink
• EPMDocument
• EPMMemberLink
• EPMReferenceLink
• EPMDescribeLink
• Representation Objects specific to WTPart and EPMDocument
For details, see the .

Data Exchange using Standards in Windchill 1703


Business Field Mapping

Business Field Attribute Mapping


Business Field attributes are classified into following types based on the data type
of the attribute values:
• String Value
• Boolean Value
• URL Value
• Integer Value
• Floating point Value
• Floating point With Unit Value
• Date And Time Value
• Reference Type

Note
Reference Type specific attributes are not supported in STEP-based data
exchange.

Apart from the data type based classification; these attributes can be classified into
following attribute types based on the way these are associated with the various
Windchill business objects.
• Typed
• Ad-hoc
• Classification

Note
Only Type Specific business fields are supported.

Note
For more information on attribute types see the Working with the Type and
Attribute Management Utility topic in the Windchill Help Center.

1704 Customization Guide


Representation in Windchill XML Format
A sample business field representation is represented in the following way in
XML-based data representation
<businessField>

<businessFieldID>

<solution>WINDCHILL</solution>

<namespace>

<category>type</category>

<name>org.rnd.TestPart</name>

</namespace>

<name>accAttr</name>

</businessFieldID>

<datatype>wt.units.FloatingPointWithUnits</datatype>

<datatypeQualifier>QOM=Acceleration,BASE_UNITS=m/s**2</datatypeQualifier>

<value>23.21|4|m/s**2</value>

<value>12.12|6|m/s**2</value>

<value>33.31|8|m/s**2</value>

<value>56.63|10|m/s**2</value>

</businessField>

Supported Types
Objects types for business fields attributes exchange have to be registered in
stepdex.properties. The property
wt.stepdex.suppported.businessfield.exchange.types must
be set. Comma-separated values need to be provided for the property. You have to
provide the qualified names for each soft type.
For example, if you want to support business field import for object types such as
WCTYPE|wt.part.WTPart|com.ptc.MyPart and
WCTYPE|wt.part.WTPart|com.ptc.computerPart then you have to
make following entries in the stepdex.properties:
wt.stepdex.suppported.businessfield.exchange.types=
com.ptc.MyPart, com.ptc.computerPart

Data Exchange using Standards in Windchill 1705


EDM Installation and Configuration
Configuring EXPRESS Data Manager (EDM) requires an EDM database (EDM_
DB), provided by EPM Jotne is encapsulated in the solution, to facilitate the
STEP-based data exchange.
Once the EDM_DB has been created, source and target schemas, STEP-specific
schemas, exchange-specific exchange specific EXPRESS-X mappings, and
certain query schemas are loaded along with some models. Once all the
configuration has been completed, the EDM_DB is stored as a master copy and a
single working copy of the database is created to be used by STEP data exchange
for staging process.

Caution
If any corruption takes place in the working copy of EDM_DB, then it needs
to be replaced with the master copy.

Multiple Method Server and EDM Configuration


Only a single instance of an EDM Database can be accessed from a Method
Server. But in multiple Method Server environments, the limitation becomes an
overhead. To overcome this, you can configure multiple EDM database-based data
exchange.
This configuration requires manually copying the master copy of EDM_DB into
the working EDM_DBs. The number of copies of EDM_DB to be made is
equivalent to the number of MS.
For instance, if you have configured n number of Method Servers for a Windchill,
then “n” working copies of EDM_DB have to be created at the same EDM
location. Once this is done, then only requests related to EDM-based data
exchange can be served by any of these “n” configured working copies of EDM_
DB.
For example, if Windchill has three for ground method servers then make copies
of <WT_HOME>/edm-home/edm_database/user as user_2 and user_
3 in the same location.

Business Field Specific Configuration


For more information, see the “Supported Types” section in Business Field
Mapping on page 1704.

1706 Customization Guide


Multiformat Properties
The Import Export framework is a standard XML based Windchill specific
import/export data representation can be represented in various other neutral
standards (such as PLM, STEP and so forth). To perform these operations, you
have to specify various details related to standard schema along with the mapping
infrastructure
Various data formats as supported by Import Export framework can be found from
the multiformat.xml file.
The multiformat.xml and stepformat.xml files contains all the
mapping-specific entries. These files contains details about the application
handlers, supported protocols, and protocol-specific mapping files used for import
export operation. PLMServices format is contained in multiformat.xml.
AP214 and and AP239 are contained in stepformat.xml.

Configuring STEP Based Data Exchange


These are the common properties used for configuring STEP-based data exchange
Name Required Default Value Description
wt.stepdex. Yes <WT_HOME>/ EDM database
database.location edm-home/edm_ folder location
database/ The actual value
honored in run
time is location +
suffix of
<protocol> used
during import/
export.
wt.stepdex. Yes user Name of EDM
database.name database
wt.stepdex.login. Yes superuser User name to
user access EDM
database
wt.stepdex.login. Yes user Password to access
password EDM database.
It can be either a
plain string or can
have encrypted
value. To
configure
encrypted
password refer to
installation guide
for more details.

Data Exchange using Standards in Windchill 1707


Name Required Default Value Description
wt.stepdex. No - Selector to pick the
converter.selector user-specific step
converter
implementation.
User can perform
some pre/post
conversion
operation on
source as well as
target EDM model
through a delegate
implementation. In
such cases user can
specify the
delegate selector
entry here.
A selector is
required. No
default value is
defined as no pre/
post converter are
available OOTB.
See the
customization
section for more
information.
wt.stepdex. No false Property to enable
validate.model or disable express
schema-specific
validation for
source and target
EDM models.

1708 Customization Guide


Name Required Default Value Description
wt.stepdex. No WCTYPE|wt.part. Identifies the types
suppported. WTPart, (soft/model) for
businessfield. WCTYPE|wt.part. which business
exchange.types WTPartMaster, field-related data
WCTYPE|wt.part. exchanges take
WTPartUsageLink, place.
WCTYPE|wt. User has to specify
occurrence. the complete type
UsesOccurrenceU- information here
serIBAs,
WCTYPE|wt.doc.
WTDocument,
WCTYPE|wt.epm.
structure.
EPMMemberLink
wt.stepdex. No FULL_ Enable logs related
validation.log.level VALIDATION to validation
process. See Log
Levels on page
1761 for
information on
various supported
values.

EDM Database Tuning


These are the configuration properties specific to EDM_DB tuning.
Property Required Default Recom- Description
Name Value mended
Value
edm_implicit_ No true true This property
instance_ can be set
creation before EDM
Database
creation.
edm_instance_ No true false Set true if your
containers application use
containers for
access control
to group of
instances.

Data Exchange using Standards in Windchill 1709


Property Required Default Recom- Description
Name Value mended
Value
Must be set
before creating
the EDM
database.
edm_ No false false Will not allow
mandatory_ writing to the
write_ EDM database
transactions without
starting a write
transaction
first.
edm_max_ No 5000 5000 The maximum
dirty_ number of
memory_ changed
blocks_in_ memory
model blocks that
may be held
open by the
system. Set in
the process
scope
edm_memory_ No 25000 More than Specifies the
blocks 75000 cache size.
Set in the
process scope.
edm_min_ No 1000 1000 Lower
memory_ threshold
blocks value for edm_
memory_
blocks.
Process will
not start with
edm_memory_
blocks less
than this. Set
in the process
scope.
edm_shrink_ No false false garbage
database_on_ control

1710 Customization Guide


Property Required Default Recom- Description
Name Value mended
Value
close_database
edm_step_ No 0 0 Specifies max
file_line_ line length in
length P21 files
generated by
EDMstepWrit-
er. 0 means no
line breaks.
Set in the
process scope.
edm_ No false false If true, EDM
unpacked_ will not reuse
models database
memory.
Causes
fragmenting
but may in
some cases
increase
performance.
edm_user_ No 15 15 Increase in
defined_ case of "too
complex_ many complex
entities entities in
model" (15 =
15%). Must be
set before
creating the
EDMdatabase.
edm_xpx_ No 1024 1024 Hash width in
integer_hash_ virtual
width machine. Set
in the process
scope.
edms_tmp_dir No Users default set as It is the path to
Windows convenient the Directory
Temp folder where
EXPRESS
Data Manager

Data Exchange using Standards in Windchill 1711


Property Required Default Recom- Description
Name Value mended
Value
stores its
temporary
files. As
Default EDM
uses the
default
Windows
Temp
Directory. Set
in the process
Scope.
edms_file_root No set as set as required This parameter
convenient is optionally
used for
running
EDMsupervi-
sor scripts. It is
a root folder
that may be
used to specify
relative file
paths in the
supervisor
scripts. It is set
in the process
Scope.
edm_real_ No 1.00E-09 set as required Specifies the
tolerance floating point
number
precision. May
be set any time
before
invoking
EDMstepWrit-
er.

1712 Customization Guide


Property Required Default Recom- Description
Name Value mended
Value
edm_db_ No 2048 4096 Legal values
block_size (in bytes):
1024, 2048,
4096, 8192
and 16384.
Use 4096 for
64 bits. Must
be set before
creating the
EDMdatabase
edm_evm_ No 750 750 Decrease when
max_mem_ out of memory
usage for virtual
machine. Set
in the process
scope.

Data Exchange using Standards in Windchill 1713


EXPRESS Customizations
This section describes how customization is performed for STEP-based data
Exchange. The following flowchart details the customization steps that need to be
followed to provide mapping for an object. It is recommended that you maintain
protocol specific EDM databases.

Note
Before you start the customization make a backup of the following:
• <WT_HOME>/edm-home/edm_database/<protocol>/user

Note
The <protocol> directory name should be same protocol name used
in stepformat.xml.

• <WT_HOME>/codebase/registry/stepdex

1714 Customization Guide


Data Exchange using Standards in Windchill 1715
OOTB Windchill only supports the mapping of ten objects. For a complete list of
mapped objects, see AP214 Object Mapping on page 1703. Individual mapping
files exist for each of these objects.
Mapping information specific to these objects can found in: <Windchill>/
codebase/registry/stepdex/<protocol> (where <protocol>
refers to Windchill supported STEP application protocols).
In this folder, you can find converters for both export as well as import operations.
Converters that are available in these locations can be treated as a reference
implementation for custom mapping.
Apart from these OOTB implementations, you can customize to update existing
mapping, add new mapping, or add customer-specific mapping. This section
describes the various customization aspects of EDM-based STEP data exchange.
The two general categories of customizations are:
• Update an existing converter
• Add new converters
Apart from these basic customizations, if you want to have specific mapping or to
write your set of mapping without modifying OOTB mapping, then refer to
Adding a New Project / Adding a New Protocol on page 1723.

Note
In each case, you need to write new or update existing object-specific
converters. For more information on writing converters, see EXPRESS-X
Mapping on page 1701.

Updating Existing Converters


Usually this type of customization is useful when the OOTB converter does not
take care of mapping all the attributes associated with an object or there are some
custom-specific mapping updates. Since it is an object-specific converter change;
you have to identify the object-specific converter file (.inn file). Once the
converter is identified, various converters need to be updated based on basic user
scenarios such as ADD or UPDATE or DELETE of attribute mapping.
Following section defines the steps to be taken in each of these use cases
• ADD : Adding mapping for an unmapped attribute.
○ Ensure that attribute is not yet mapped. (check resulting exported step file)
○ Add new EXPRESS X Mapping in converter file
• UPDATE : Updating mapping of an already mapped attribute.
○ Identify the attribute-specific mapping section.

1716 Customization Guide


○ Add desired mapping updates in the converter file.
• DELETE : Removing mapping of an already mapped attribute.
○ Identify the attribute-specific mapping section.
○ Remove the attribute-specific inn file and save it.
Once the converter files have been updated, you must overwrite the existing
converter-specific schemas from the EDM database. For information on updating
the specific conversion schema, see Load Schema on page 1728 and Load
Conversion (EXPRESS-X) Schema on page 1729.
Since update of the converters usually takes place in master replica of EDM™
Database. One has to follow the Configuration steps again to copy the working
replicas for same. For details on configuration, please see EDM Installation and
Configuration on page 1706.
For details on OOTB AP214 Object mapping, please refer .

Add a New Converter


This section describes how to add EXPRESS-X converters for any new object for
which IX-specific handlers are already available. Before writing any new handlers
verify that no mapping has already been defined for the handlers.
In this section, as an example a change request object named
WTChangeRequest is used to show how to add converters.
Since WTChangeRequest2 specific IX Handlers are available, you can use the
entity definition for it in the Windchill Schema file located in: <Windchill>/
loadXMLFiles/windchill_express_schema.exp.
The following steps must be followed to customize such objects:
• Writing an Export Converter on page 1717
• Writing an Import Converter on page 1719
• Configuring the EDM Database on page 1722

Writing an Export Converter


1. Determine how entity or attributes in Windchill Schema is mapped to an
Automotive Design (AP214) Schema.
2. Create a new converter file with name
ExportWTChangeRequest2.innand place it under the
<Windchill>/codebase/registry/stepdex/ap214/export/
includes directory.
3. Add mapping for the object and attributes in inn file created in step 2.

Data Exchange using Standards in Windchill 1717


• Map WTChangeRequest2 entity in Windchill Schema to
Versioned_Action_Request entity AP214 Schema
• Map r_number attribute associated with WTChangeRequest2 entity
to its counterpart Id attribute in Versioned_Action_Request.
“number” is a reserved word in EXPRESS modeling language. Hence it has
been renamed to “r_number”
The following code sample depicts how to map these attributes
MAP xpxmWTChangeRequest2 FOR ver_act:aim :: versioned_action_request;

FROM (wt_chnage: wnc::e_WTChangeRequest2)

WHEN TRUE;

BEGIN_MAP

LOCAL

--Local variable

END_LOCAL;

ver_act.id :=wt_change.r_number;

END_MAP;

Attribute mapping goes with the ver_act.id :=wt_change.r_


number; segment.

Note
For more information on the EXPRESS Data Manager see EDMassist.

4. Register/Include the converter file in the export-specific project file


(WNCTOAP214.xpxprj) as shown in the code below..
SOURCE_FILES

"WNCTOAP214.xpx" --Main file

1718 Customization Guide


"includes/ExportWRPart.inn"

"includes/EportEMPDocument.inn"

"includes/ExportEPMMemberLink.inn"

"includes/EportEPMDescribeLink.inn"

"includes/ExportWTChangeRequest2.inn"

"includes/ExportRepresentation.inn"

"includes/ExportWRPartDescribe.inn"

"includes/ExportWTPartReferenceLink.inn"

"includes/ExportWTPartUsageLink.inn"

"includes/ExportEPMReferenceLink.inn"

"includes/ExportContentItem.inn"

"includes/AP214UnitValueProcessor.inn"

"includes/ExportOrganizationName.inn"

"includes/ExportHandlePropertyDefinition.inn"

"includes/ExportGlobalInstanceFunctions.inn"

"./../../common/includes/export/ExportBusinessFields.inn"

"./../../common/includes/StringUtils.inn"

"./../../common/includes/AggregateUtils.inn"

"./../../common/includes/DateTimeUtil.inn"

"./../../common/includes/MesurableUnitsUtil.inn"

END_SOURCE_FILES

Writing an Import Converter


This is the reverse process of the Export operation.

Data Exchange using Standards in Windchill 1719


1. Understand how entity or attributes in Automotive Design (AP214) Schema is
mapped to Windchill Schema.
2. Create a new converter file with name
“ImportWTChangeRequest2.inn” and place it under <WINDCHILL_
HOME>/codebase/registry/stepdex/ap214/importxpx/
includes” directory
3. Add mapping for the object and attributes in inn file created in Step 2.
• Map Versioned_Action_Request entity AP214 Schema to
WTChangeRequest2 entity in Windchill Schema
• Invoke updateRootTag function and pass the Windchill entity name.
(This helps in identifying list objects to be imported.)
• Map Id attribute in Versioned_Action_Request to its counterpart
r_number attribute associated with WTChangeRequest2 entity.
Following figure depicts how to map these attributes
(*

Maps versioned_action_request to e_WTChangeRequest2.

*)

MAP xpxmChange FOR wtChange:wnc::e_WTChangeRequest2;

FROM (ver_act:aim::versioned_action_request)

WHEN TRUE;

BEGIN_MAP

LOCAL

--Local variables

END_LOCAL

-- Update roor tag in importList.

updateRootTag('e_WTChangeRequest2;);

wt_change.r_number := ver_act.id;

1720 Customization Guide


END MAP;
4. Register/Include the converter file in the export-specific project file
(AP214TOWNC.xpxprj) as shown in the code below.
(*

XPX Project file for AP214 to Windchill import mapping. This should contain

source?_files definition one Main file followed by all includes files source.

*)

SOURCE FILES

"AP214TOWNC.xpx" --Main file

"includes/ImportWTPart.inn"

"includes/ImportWTDocument.inn"

"includes/ImportEPMDocument.inn"

"includes/ImportWTChangeRequest2.inn"

"includes/ImportHandlePropertyDefinition.inn"

"includes/ProcessAppliedDocumentReference.inn"

"includes/ImportRepresentation.inn"

"includes/ImportWTPartUsageLink.inn"

"includes/ImportWTPartDescribeLink.inn"

"includes/ImportWTPartReferenceLink.inn"

"includes/ImportEPMMemberLink.inn"

"includes/ImportEPMDescribeLink.inn"

"includes/ImportEPMReferenceLink.inn"

"includes/ImportContentItem.inn"

"includes/ImportGlobalFunctions.inn"

Data Exchange using Standards in Windchill 1721


"includes/ImportOrganization.inn"

"includes/ImportBusinessFields.inn"

"includes/ImportUnitUtils.inn"

"./../../common/includes/StringUtils.inn"

"./../../common/includes/AggregateUtils.inn"

"./../../common/includes/DateTimeUtil.inn"

"./../../common/includes/import/ImportUtil.inn"

"./../../common/includes/import/ImportWTPartAttributes.inn"

"./../../common/includes/import/ImportVersionObject.inn"

"./../../common/includes/import/ImportLifeCycleObject.inn"

"./../../common/includes/import/ImportBusinessFields.inn"

"./../../common/includes/import/ImportContentItemAttributes.inn"

"./../../common/includes/import/ImportWTDocumentAttributes.inn"

"./../../common/includes/import/ImportWTPartDescribeLink.inn"

"./../../common/includes/import/ImportRepresentation.inn"

END_SOURCE_FILES

Configuring the EDM Database


Once converter files have been updated one has to overwrite the existing
converter-specific schemas from EDM Database. For more information on
updating the specific conversion, see Load Schema on page 1728 and Load
Conversion (EXPRESS-X) Schema on page 1729.
Since updates of the converters usually take place in master replica of EDM™
Database. One has to follow the Configuration steps again to copy the working
replicas for same. For details on configuration see EDM Installation and
Configuration on page 1706.

1722 Customization Guide


Adding a New Project / Adding a New Protocol
If you have customized express schema or adopt a new schema or adopt different
standards for different customers for a single AP or you want to write your own
set of mapping apart from the OOTB mapping; then the following approach needs
to be followed.
1. Add a new protocol entry in stepformat.xml located in <Windchill>\
codebase\registry\ixb\multiformat directory.
<protocol>

<name>AP214_CUSTOMIZED</name>

<default>false</default>

<specification>

<definition>

<file>stepdex/ap214/schema/10303-214e2-aim-long.exp</file>

<schemaName>AUTOMOTIVE_DESIGN</schemaName>

</definition>

</specification>

<configuration>

<exportConfiguration>

<mappingFile>stepdex/ap214/export/WNCTOAP2141.xpxprj</mappingFile>

<schemaName>WNCTOAP214NEW</schemaName>

<!-- PART_21 | PART_28 -->

<defaultDataExchangeForm>PART_28</defaultDataExchangeForm>

</exportConfiguration>

<importConfiguration>

<mappingFile>stepdex/ap214/importxpx/AP214TOWNC1.xpxprj</mappingFile>

<schemaName>AP214TOWNCNEW</schemaName>

</importConfiguration>

</configuration>

Data Exchange using Standards in Windchill 1723


</protocol>

Note
AP214TOWNCNEW should be unique throughout the project. This is a
requirement of the Import/Exprt Framework.

2. Add a new value to the enumerator IXFormatProtocolTypeRB


AP214_CUSTOMIZED.value=STEP AP214 protocol (customized)

AP214_CUSTOMIZED.comment=ISO 10303 Standard format


or Application Interpreted Model

(AIM) Part 21/28 (customized)

AP214_CUSTOMIZED.shortDescription=STEP Foundation P 21/28


ith XPX (customized)

AP214_CUSTOMIZED.order=80

Note: - Ensure that key matches with the value of <name> element in protocol
entry newly added
3. Configure IXBDocumentDelegate for the new protocol by adding entry
in IXBDocumentDelagetSTEP-service.properties.xconf and
propagating the same.
<Service context="default" name="wt.ixb.publicforapps.IXDocumentDelegate">

<Option serviceClass="wt.ixb.impl.step.IxbSTEPDocumentDelegate"

requestor="java.lang.Object"

selector="AP214_CUSTOMIZED " cardinality="duplicate"/>

</Service>
4. Use
IXFormatType.setProtocol(IXFormatTypeProtocolType)
method to set up the protocol.

1724 Customization Guide


Advanced Customization — Implementing Post and Pre Converters

When to Write Pre or Post Converters


• When you need to override behavior before the conversion or after the
conversion.
• When you need to modify the source and target model before or after, the
conversion from one format to another.
• Doing this can be considered as data tuning.

Extend wt.ixb.step.STEPConverter interface


• Source model and target model are passed to pre and post converters APIs.
• Implementation of the interface can change the models that are used in
converters.
• Use EDM SDK APIs to change the source model and target model.
• For more information on APIs, see the EDMassist website.

Adding the service.properties entry for the delegate


In IXDocumentDelegateSTEP-service.properties.xconf :
<Service context="default" name="="wt.ixb.step.STEPConverter">

<Option serviceClass=“<your implementation>" requestor="="java.lang.Object"

selector=“<selector name>" cardinality="duplicate"/>

</Service>

• Update the following property in stepdex.xconf to change converter


selector: wt.stepdex.converter.selector=<selector>

Data Exchange using Standards in Windchill 1725


EXPRESS Tools
• EXPRESS Schema Generator on page 1726
• EXPRESS Database Tools on page 1727
○ Create EDM Database on page 1727
○ Load Schema on page 1728
○ Load EXPRESS Schema on page 1729
○ Load Conversion (EXPRESS-X) Schema on page 1729
○ Load Query Schema on page 1730
○ Delete Schema on page 1730
○ Load Model on page 1730

EXPRESS Schema Generator


EXPRESS is the modeling language used by STEP for defining information
model for data exchange. To support STEP-based Data exchange, Windchill
should provide EXPRESS schema-specific definitions for its business objects.
Since Windchill object model is represented through DTD Schema. You need to
convert the same in EXPRESS schema model. For this purpose EXPRESS
Schema Generator tool has been developed. The generated EXPRESS schema can
be used for subsequent STEP-based Data Exchange.

Command Usage
For a given release DTD, following command can be executed to convert DTD to
.exp file (EXPRESS schema file).
java wt.stepdex.schemagenerator.GenerateExpressSchema
<Windchill> <DTD file name> <Output directory>
Where:
• WT_HOME : Windchill Home
• DTD file name: Name of the DTD file. This file should be located in
<Windchill>/loadXMLFiles.
• Output directory: Optional. The default value is the directory where DTD file
name is present.
For example, release specific Windchill EXPRESS schema can be generated using
following command: $> java
wt.stepdex.schemagenerator.GenerateExpressSchema /user/
windchill standardx24.dtd

1726 Customization Guide


EXPRESS Database Tools
The EDMdatabase is Jotne EPM Technology’s proprietary storage technology. It
is designed to store and process all information defined in EXPRESS and
EXPRESS-X schemas (dictionary data) and Populations thereof (application
data). Data are stored as Instances in a Model. A Model is stored in a Repository.
This new tool facilitates users to create EDMDB and load or delete various EDM-
specific schemas and models. This is a common tool which takes care of all such
operation specified above. Currently this tool restricts the database context user
name to “superuser”.
Using these tools you can:
• Create an EDM database or open existing database; see Create EDM Database
on page 1727
• Load the EDM database; see Load Schema on page 1728
• Delete EXPRESS/EXPRESS-X mappings; see Delete Schema on page 1730
• Load Model on page 1730

Note
For information on various mappings and underlying features see the
EDMassist website. This is the website of the EXPRESS Data Manager, which
is a third-party product that supports STEP.

Notes on Command Syntax


If you do not specify any database details, then values are retrieved from the
stepdex.properties file. You can either provide all values from Windchill
shell or from property file:

Create EDM Database


Use this command to create and overwrite the EDM database.

Command Syntax
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-createdb [-overwrite] [-dbname (-d) <DBName> -user(-u)
<DBContextLoginName> -password(-p) DBPassword
-location(-l) DBLocation]
Where:
• -createdb : Option to create a new EDM database
• -overwrite : Option to overwrite on an existing database

Data Exchange using Standards in Windchill 1727


• DBName : Specify database name
• DBContextLoginName : Specify database context login name
• DBPassword : Specify the database password
• DBLocation : Specify path to database file. This must have the <protocol>
suffix in the directory path. For example: <WT_HOME>/edm-home/edm-
database/AP214 for AP214 specific command execution.

Examples
• Create a new Express DB named “db1” at location “D:/temp/edm”
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-createdb -d db1 -u superuser -p pwd -l D:\temp\edm
• Overwrite an existing DB named “db1” located at “D:/temp/edm”
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-createdb -overwrite -d db1 -u superuser -p pwd -l D:\
temp\edm
• Create DB based on stepdex.properties
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-createdb [-overwrite]

Load Schema
STEP-based data exchange requires various schemas to be loaded in EDMDB
prior to actual data exchange process. Based on the nature or behavior, schemas
are divided into following categories.
• Load EXPRESS Schema on page 1729
• Load Conversion (EXPRESS-X) Schema on page 1729
• Load Query Schema on page 1730
These schemas are loaded with the help of EDM EXPRESS Compiler. This tool
has been developed to facilitate the customizers to load various schemas into
EDMDB.
Following command is being used to load the schema into the EDMDB

Command Syntax
$>java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-loadschema [-overwrite] -type (-t) -e|-x|-q -s

1728 Customization Guide


(schemafile) SchemaAbsolutePath [-dbname (-d) <DBName>
-user(-u) <DBContextLoginName> -password(-p) DBPassword
-location(-l) DBLocation]
Where
• -loadSchema: Option for loading a new schema
• -overwrite: Option to overwrite on an existing schema
• -t: Type of the schema. Could be of following 3 options
○ -x: Option to load an EXPRESS-X schema
○ -e Option to load EXPRESS schema
○ -q Option to load Query schema
• SchemaAbsolutePath: Specify absolute path to schema
• DBName : Specify database name
• DBContextLoginName: Specify database context login name
• DBPassword: Specify the database password
• DBLocation: Specify path to database

Example
Here is the simple command which loads Windchill express schema into EDMDB
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-loadschema -t -e -s [WT_HOME]/loadXMLFiles/windchill_
express_schema.exp

Note
If Database details are not present in command, then the tool reads default
database details from the stepdex.properties file.

Load EXPRESS Schema


Use -t -e option in the above command as type to load Query schema.

Load Conversion (EXPRESS-X) Schema


EXPRESS-X is a conversion schema which helps in data conversion from one
EXPRESS Schema to Other EXPRESS schema. This tool helps to load
conversion-specific schema in EDM environment.
Use -t -x option in the above command as type to load Query converter.

Data Exchange using Standards in Windchill 1729


Load Query Schema
Query schema is the one which are being used to query entities available in the
EDM Model. This is being extensively used in PLCS-specific data exchange. This
tool facilitates the Query Schema loading mechanism in an EDM environment.
Use -t -q option in the above command as type to load Query schema.

Delete Schema
Use this command to delete express and express-x conversion schemas from the
EDM database.

Command Syntax
$>java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-deleteschema -type(-t) -e|-x -schemaname(-n) SchemaName
[-dbname (-d) <DBName> -user(-u) <DBContextLoginName>
-password(-p) DBPassword -location(-l) DBLocation]
Where:
• -deleteSchema : Option to delete a schema
• -t : Type of the schema. Could be of following 2 options
• -x : Option to load an EXPRESS-X schema
• -e : Option to load EXPRESS schema
• SchemaName : Specify the name of schema
• DBName : Specify database name
• DBContextLoginName : Specify database context login name
• DBPassword : Specify the database password
• DBLocation : Specify path to database file

Load Model
Various STEP or XML files gets loaded into EDMDB as a Model. This tool will
help you to load model for an existing EXPRESS Schema.

Command Syntax
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-loadmodel [-overwrite] -modelname(-m) modelName
-stepfile(-f) stepFilePath [-dbname(-d) DBName -user(-u)
DBContextLoginName -password(-p) DBPassword
-dblocation(-l) DBLocation]

1730 Customization Guide


Where:
• -loadmodel: Option for loading a model for the given schema
• -overwrite: Option to overwrite on an existing model
• modelname: Name of the model
• stepFilePath: Absolute path of STEP file. Can be either P28 or P21 file
• DBName: Specify database name
• DBContextLoginName: Specify database context login name
• DBPassword: Specify the database password
• DBLocation: Specify path to database

Example
• Command To load a STEP file named “stepAP214.stp” at “%WT_HOME/
temp/p21
$> java
wt.stepdex.expressschemautil.ExpressDbSchemaManager
-loadmodel -m plcsrdl -f “%WT_HOME/temp/p21/
stepAP214.stp

Data Exchange using Standards in Windchill 1731


Mapping Information
This section contains the following mapping information:
• DTD to EXPRESS Mapping on page 1733
• IBA Mapping on page 1741
• WTDocument Mapping on page 1745
• EPMDocument Mapping on page 1748
• WTPart Mapping on page 1752
• Representation Mapping on page 1754
• WTPartUsageLink on page 1756
• EPMReferenceLink on page 1758
• EPMMemberLink on page 1759

1732 Customization Guide


DTD to EXPRESS Mapping
Following table depicts the Sample DTD Schema to EXPRESS Entity
Representation.
DTD Format EXPRESS Entity Format
<!ELEMENT bar (name, – <!ELEMENT bar (name,
number?, phantom*, number?, phantom*,
collapsible+)> collapsible+)>
<!ELEMENT name (#PCDATA)> ENTITY e_bar;
<!ELEMENT number (#PCDATA)> name : STRING;
<!ELEMENT phantom r_number : OPTIONAL STRING;
(#PCDATA)>
phantom : OPTIONAL LIST OF
<!ELEMENT collapsible STRING;
(#PCDATA)> collapsible : LIST [1:?] OF
STRING;
END_ENTITY;
<!ELEMENT part (name, – <!ELEMENT part (name,
(number | ufid) )> (number | ufid))>
<!ELEMENT name (#PCDATA)> ENTITY e_part;
<!ELEMENT number (#PCDATA)> name : STRING;
<!ELEMENT ufid (#PCDATA)> r_number : OPTIONAL STRING;
ufid : OPTIONAL STRING;
WHERE
wr1: ((EXISTS ( r_number )
AND NOT EXISTS ( ufid )) OR
(NOT EXISTS ( r_number ) AND
EXISTS ( ufid )));
END_ENTITY;
<!ELEMENT part (name, – <!ELEMENT part (name,
(number | ufid)+, masterufid (number | ufid)+,
)> masterufid)>
<!ELEMENT name (#PCDATA)> ENTITY e_part;
<!ELEMENT number (#PCDATA)> name : STRING;
<!ELEMENT ufid (#PCDATA)> r_number : OPTIONAL LIST
<!ELEMENT masterufid [1:?] OF STRING;
(#PCDATA)> ufid : OPTIONAL LIST [1:?] OF
STRING;

Data Exchange using Standards in Windchill 1733


DTD Format EXPRESS Entity Format
masterufid : STRING;
WHERE
wr1: (EXISTS ( r_number ) OR
EXISTS ( ufid ));
END_ENTITY;
<!ELEMENT part ((name, – <!ELEMENT part ((name,
((number, ufid)+)))> ((number, ufid)+)))>
<!ELEMENT name (#PCDATA)> ENTITY e_part;
<!ELEMENT number (#PCDATA)> name : STRING;
<!ELEMENT ufid (#PCDATA)> r_number : LIST [1:?] OF
STRING;
ufid : LIST [1:?] OF STRING;
END_ENTITY;
<!ELEMENT dtd (#PCDATA)> – <!ELEMENT EPMDocument
<!ELEMENT EPMDocument (dtd?, ObjectID*, ((number,
(dtd?, ObjectID*, ((number, masterUfid?),
masterUfid?), objectContainerPath,
objectContainerPath,com complexEntity)+)>
plexEntity)+)> ENTITY e_EPMDocument;
<!ELEMENT complexEntity dtd : OPTIONAL STRING;
(#PCDATA)>
ObjectID : OPTIONAL LIST OF
<!ELEMENT ObjectID STRING;
(#PCDATA)>
r_number : LIST [1:?] OF
<!ELEMENT number (#PCDATA)> STRING;
<!ELEMENT masterUfid masterUfid : OPTIONAL LIST
(#PCDATA)> [1:?] OF STRING;
<!ELEMENT objectContainerPath : LIST
objectContainerPath [1:?] OF STRING;
(#PCDATA)>
complexEntity : LIST [1:?] OF
STRING;
END_ENTITY;
<!ELEMENT groupName – <!ELEMENT
(#PCDATA)> WTPrincipalReference (ufid
<!ELEMENT groupType | name | (ufid, name) |
(#PCDATA)> (groupName, groupType))>

1734 Customization Guide


DTD Format EXPRESS Entity Format
<!ELEMENT ENTITY e_
WTPrincipalReference WTPrincipalReference;
(ufid|name|(ufid,name)|( ufid : OPTIONAL STRING;
groupName,groupType))>
name : OPTIONAL STRING;
<!ELEMENT ufid (#PCDATA)>
groupName : OPTIONAL STRING;
<!ELEMENT name (#PCDATA)>
groupType : OPTIONAL STRING;
WHERE
wr1: ((EXISTS ( ufid ) AND NOT
EXISTS ( name ) AND NOT EXISTS
( groupName ) AND NOT EXISTS (
groupType )) OR (NOT EXISTS (
ufid ) AND EXISTS ( name ) AND
NOT EXISTS ( groupName ) AND
NOT EXISTS ( groupType )) OR
(((EXISTS ( ufid ) AND EXISTS
( name ))) AND NOT EXISTS (
groupName ) AND NOT EXISTS (
groupType )) OR (((EXISTS (
groupName ) AND EXISTS (
groupType ))) AND NOT EXISTS
( ufid ) AND NOT EXISTS ( name
)));
END_ENTITY;

Data Exchange using Standards in Windchill 1735


DTD Format EXPRESS Entity Format
<!ELEMENT part (name, – <!ELEMENT part (name,
(number | ufid)*, item, (sun (number | ufid)*, item, (sun
| mon | tue)+)> | mon | tue)+)>
<!ELEMENT name (#PCDATA)> ENTITY e_part;
<!ELEMENT item (#PCDATA)> name : STRING;
<!ELEMENT sun (#PCDATA)> r_number : OPTIONAL LIST OF
<!ELEMENT mon (#PCDATA)> STRING;

<!ELEMENT tue (#PCDATA)> ufid : OPTIONAL LIST OF


STRING;
<!ELEMENT number (#PCDATA)>
item : STRING;
<!ELEMENT ufid (#PCDATA)>
sun : OPTIONAL LIST [1:?] OF
STRING;
mon : OPTIONAL LIST [1:?] OF
STRING;
tue : OPTIONAL LIST [1:?] OF
STRING;
WHERE
wr1: (EXISTS ( sun ) OR EXISTS
( mon ) OR EXISTS ( tue ));
END_ENTITY
<!ELEMENT combination ( wed, – <!ELEMENT combination
thu, ((sat, sun*) | (sun*, (wed, thu, ((sat, sun*) |
mon+) | (fri, sat*) | (mon?, (sun*, mon+) | (fri, sat*) |
tue)))> (mon?, tue)))>
<!ELEMENT sun (#PCDATA)> ENTITY e_combination;
<!ELEMENT mon (#PCDATA)> wed : STRING;
<!ELEMENT tue (#PCDATA)> thu : STRING;
<!ELEMENT wed (#PCDATA)> sat : OPTIONAL LIST OF
STRING;
<!ELEMENT thu (#PCDATA)>
<!ELEMENT fri (#PCDATA)> sun : OPTIONAL LIST OF
STRING;
<!ELEMENT sat (#PCDATA)>
mon : OPTIONAL LIST [1:?] OF
STRING;
fri : OPTIONAL STRING;
tue : OPTIONAL STRING;

1736 Customization Guide


DTD Format EXPRESS Entity Format
WHERE
wr1: ((((EXISTS ( sat ) AND
(EXISTS ( sun ) OR NOT EXISTS
( sun )))) AND NOT EXISTS (
mon ) AND NOT EXISTS ( fri )
AND NOT EXISTS ( tue )) OR
((((EXISTS ( sun ) OR NOT
EXISTS ( sun )) AND EXISTS (
mon ))) AND NOT EXISTS ( sat )
AND NOT EXISTS ( fri ) AND NOT
EXISTS ( tue )) OR (((EXISTS (
fri ) AND (EXISTS ( sat ) OR
NOT EXISTS ( sat )))) AND NOT
EXISTS ( sun ) AND NOT EXISTS
( mon ) AND NOT EXISTS ( tue ))
OR ((((EXISTS ( mon ) OR NOT
EXISTS ( mon )) AND EXISTS (
tue ))) AND NOT EXISTS ( sat )
AND NOT EXISTS ( sun ) AND NOT
EXISTS ( fri )));
END_ENTITY;

Data Exchange using Standards in Windchill 1737


DTD Format EXPRESS Entity Format
<!ELEMENT – <!ELEMENT permissionField
AccessPermissionSet EMPTY>
((permissionField|permis ENTITY e_permissionField;
sionKey)+)>
attr_name : STRING;
<!ELEMENT permissionField
EMPTY> WHERE
<!ATTLIST permissionField check_attr_name: SELF.attr_
name (ALL|READ|MODIFY) name IN
#REQUIRED> ['ALL','READ','MODIFY'];
<!ELEMENT permissionKey END_ENTITY;
EMPTY> – <!ELEMENT permissionKey
<!ATTLIST permissionKey EMPTY>
value (-1|0|1|2|3|4|5|6|7) ENTITY e_permissionKey;
#REQUIRED>
attr_value : STRING;
WHERE
check_attr_value:
SELF.attr_value IN
['-1','0','1','2','3','4',
'5','6','7'];
END_ENTITY;
– <!ELEMENT
AccessPermissionSet
((permissionField |
permissionKey)+)>
ENTITY e_
AccessPermissionSet;
permissionField : OPTIONAL
LIST [1:?] OF e_
permissionField;
permissionKey : OPTIONAL
LIST [1:?] OF e_
permissionKey;
WHERE
wr1: (EXISTS (
permissionField ) OR EXISTS (
permissionKey ));
END_ENTITY;

1738 Customization Guide


DTD Format EXPRESS Entity Format
<!ELEMENT part (name)> – <!ELEMENT lifecycleInfo
<!ELEMENT name (#PCDATA)> (lifecycleTemplateName)>
<!ELEMENT lifecycleInfo ENTITY e_lifecycleInfo;
(lifecycleTemplateName)> lifecycleTemplateName :
<!ELEMENT STRING;
lifecycleTemplateName END_ENTITY;
(#PCDATA)>
– <!ELEMENT part (name)>
<!ELEMENT objectHistory
(lifeCycleHistory*)> ENTITY e_part;

<!ELEMENT lifeCycleHistory name : STRING;


(#PCDATA)> END_ENTITY;
<!ELEMENT changeVersionInfo – <!ELEMENT
(changeVersionId)> changeVersionInfo
<!ELEMENT changeVersionId (changeVersionId)>
(#PCDATA)> ENTITY e_changeVersionInfo;
<!ELEMENT content changeVersionId : STRING;
((part*|lifecycleInfo*|ob
END_ENTITY;
jectHistory*|changeVersio
nInfo?)*)> – <!ELEMENT objectHistory
(lifeCycleHistory*)>
ENTITY e_objectHistory;
lifeCycleHistory : OPTIONAL
LIST OF STRING;
END_ENTITY;
– <!ELEMENT content ((part* |
lifecycleInfo* |
objectHistory* |
changeVersionInfo?)*)>
ENTITY e_content;
part : OPTIONAL LIST OF e_
part;
lifecycleInfo : OPTIONAL
LIST OF e_lifecycleInfo;
objectHistory : OPTIONAL
LIST OF e_objectHistory;

Data Exchange using Standards in Windchill 1739


DTD Format EXPRESS Entity Format
changeVersionInfo :
OPTIONAL LIST OF e_
changeVersionInfo;
END_ENTITY;

1740 Customization Guide


IBA Mapping
This section contains details out how IBAs are mapped in AP214 standard.
WINDCNHILL IBA Type AP214 IBA Representation
StringValue IBA #71= PROPERTY_DEFINITION
('StringValue','IBA',#1);
#72= PROPERTY_DEFINITION_
REPRESENTATION(#71,#73);
#73= REPRESENTATION($,(#74),$);
#74= DESCRIPTIVE_
REPRESENTATION_ITEM
('MyStringAttr','StringAttrValue');
Boolean IBA #16= PROPERTY_DEFINITION
('BooleanValue','IBA',#1);
#17= PROPERTY_DEFINITION_
REPRESENTATION(#16,#18);
#18= REPRESENTATION($,(#19),$);
#19= DESCRIPTIVE_
REPRESENTATION_ITEM
('MyBooleanAttr1','true');
IntegerValue #26= PROPERTY_DEFINITION
('IntegerValue','IBA',#1);
#27= PROPERTY_DEFINITION_
REPRESENTATION(#26,#28);
#28= REPRESENTATION($,(#29),$);
#29= VALUE_REPRESENTATION_
ITEM('MyIntegerAttr',NUMERIC_
MEASURE(23.));
FloatValue #212= PROPERTY_DEFINITION
('FloatValue','IBA',#1);
#213= PROPERTY_DEFINITION_
REPRESENTATION(#212,#214);
#214= REPRESENTATION($,(#215,
#217),$);
#215=VALUE_REPRESENTATION_
ITEM('MyRealNumberAttr1',
NUMERIC_MEASURE(2536.16));
#217= QUALIFIED_
REPRESENTATION_ITEM($,(#218));

Data Exchange using Standards in Windchill 1741


WINDCNHILL IBA Type AP214 IBA Representation
#218= PRECISION_QUALIFIER(16);
Unit Value (Ampere) #103= PROPERTY_DEFINITION
SI Base units like m, g, s, A, K, mol, ('UnitValue','IBA',#1);
cd, r, sr are represented in this format #104= PROPERTY_DEFINITION_
REPRESENTATION(#103,#105);
#105= REPRESENTATION($,(#106,
#109),$);
#106= MEASURE_
REPRESENTATION_ITEM
('MyRealNumberWithUnitAttr08',
ELECTRIC_CURRENT_MEASURE
(2508.16),#107);
#107= /* ELECTRIC_CURRENT_
UNIT+SI_UNIT */(ELECTRIC_
CURRENT_UNIT()NAMED_UNIT(*)
SI_UNIT($,.AMPERE.));
#109= QUALIFIED_
REPRESENTATION_ITEM($,(#110));
#110= PRECISION_QUALIFIER(5);
Unit Value (Unit kg*m**2/s**2) #196= PROPERTY_DEFINITION
Units in multiple of above units are ('UnitValue','IBA',#1);
treated in derived unit #197= PROPERTY_DEFINITION_
REPRESENTATION(#196,#198);
#198= REPRESENTATION($,(#199,
#209),$);
#199= MEASURE_
REPRESENTATION_ITEM
('MyRealNumberWithUnitAttr16',
NUMERIC_MEASURE(2516.16),
#200);
#200= DERIVED_UNIT((#201,#204,
#206));
#201= DERIVED_UNIT_ELEMENT
(#202,$);
#202= /* MASS_UNIT+SI_UNIT
*/(MASS_UNIT()NAMED_UNIT(*)
SI_UNIT(.KILO.,.GRAM.));

1742 Customization Guide


WINDCNHILL IBA Type AP214 IBA Representation
#204= DERIVED_UNIT_ELEMENT
(#205,2.);
#205= /* LENGTH_UNIT+SI_UNIT
*/(LENGTH_UNIT()NAMED_UNIT
(*)SI_UNIT($,.METRE.));
#206= DERIVED_UNIT_ELEMENT
(#207,-2.);
#207= /* SI_UNIT+TIME_UNIT
*/(NAMED_UNIT(*)SI_UNIT($,.
SECOND.)TIME_UNIT());
#209= QUALIFIED_
REPRESENTATION_ITEM($,(#210));
#210= PRECISION_QUALIFIER(5);
Unit Values are mostly mapped using the mappings specified above two rows.
For special cases like volume where we have some separate mapping altogether,
user needs to write the mapping for such case as per their customization.
Unit Value (volume) #148= PROPERTY_DEFINITION
Represented as conversion-based unit. ('UnitValue','IBA',#1);
Such representation is only specified #149= PROPERTY_DEFINITION_
for volume. REPRESENTATION(#148,#150);
#150= REPRESENTATION($,(#151,
#159),$);
#151= MEASURE_
REPRESENTATION_ITEM
('MyRealNumberWithUnitAttr13',
VOLUME_MEASURE(2513.16),
#152);
#152= /* CONVERSION_BASED_
UNIT+VOLUME_UNIT
*/(CONVERSION_BASED_UNIT
('LITER',#153)NAMED_UNIT($)
VOLUME_UNIT());
#153= LENGTH_MEASURE_WITH_
UNIT(VOLUME_MEASURE(0.001),
#154);
#154= DERIVED_UNIT((#155));
#155= DERIVED_UNIT_ELEMENT
(#156,3.);

Data Exchange using Standards in Windchill 1743


WINDCNHILL IBA Type AP214 IBA Representation
#156= /* LENGTH_UNIT+SI_UNIT
*/(LENGTH_UNIT()NAMED_UNIT
(*)SI_UNIT($,.METRE.));
#159= QUALIFIED_
REPRESENTATION_ITEM($,(#160));
#160= PRECISION_QUALIFIER(5);
URL Value #31= PROPERTY_DEFINITION
('URLValue','IBA',#1);
#32= PROPERTY_DEFINITION_
REPRESENTATION(#31,#33);
#33= REPRESENTATION($,(#34),$);
#34= DESCRIPTIVE_
REPRESENTATION_ITEM
('MyURLAttr','http://www.ptc.com
(PTC)');
TimeStamp Value #9= PROPERTY_DEFINITION
('TimestampValue','MyDateTimeAttr',
#1);
#10= APPLIED_DATE_AND_TIME_
ASSIGNMENT(#14,#12,(#9));
#12= DATE_TIME_ROLE('IBA');
#13= CALENDAR_DATE(2011,29,7);
#14= DATE_AND_TIME(#13,#15);
#15= LOCAL_TIME(18,30,$,$);

1744 Customization Guide


WTDocument Mapping
This section contains details out how WTDocument is mapped in AP214 standard.
WTDocument Type AP214 Product Definition
WTDocument #1=PRODUCT_DEFINITION
('Design',$,#2,#6);
#2=PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3=PRODUCT('0000000001','SPR
2098596 Description',$,(#4));
#4=PRODUCT_CONTEXT('digital
document definition',#5,$);
#5=APPLICATION_CONTEXT
('digital document');
#6=PRODUCT_DEFINITION_
CONTEXT('digital document
definition',#5,'Design');
Number #2=PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3=PRODUCT('0000000001','SPR
2098596 Description',$,(#4));
#4=PRODUCT_CONTEXT('digital
document definition',#5,$);
#5=APPLICATION_CONTEXT
('digital document');
#16=APPLICATION_PROTOCOL_
DEFINITION('international
standard','automotive_design',2009,#5);
Name #2=PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3=PRODUCT('0000000001','SPR
2098596 Description',$,(#4));
#4=PRODUCT_CONTEXT('digital
document definition',#5,$);
#5=APPLICATION_CONTEXT
('digital document');
#21=DOCUMENT_PRODUCT_
ASSOCIATION($,$,#22,#3);

Data Exchange using Standards in Windchill 1745


WTDocument Type AP214 Product Definition
#22=DOCUMENT('SPR 2098596
Description',$,$,$);
versionInfo/versionId #2=PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3=PRODUCT('0000000001','SPR
2098596 Description',$,(#4));
#4=PRODUCT_CONTEXT('digital
document definition',#5,$);
#5=APPLICATION_CONTEXT
('digital document');
versionInfo/iterationId #2=PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3=PRODUCT('0000000001','SPR
2098596 Description',$,(#4));
#4=PRODUCT_CONTEXT('digital
document definition',#5,$);
#5=APPLICATION_CONTEXT
('digital document');

1746 Customization Guide


WTDocument Type AP214 Product Definition
ObjectID/ufid #18= DESCRIPTIVE_
masterUfid REPRESENTATION_ITEM('key’,
‘value');
docType
#19= REPRESENTATION('property
docTitle value',(#18),#21);
description #21= REPRESENTATION_CONTEXT
department ('','');
domainName #24= PROPERTY_DEFINITION('key',
$,#1); #25=PROPERTY_
folderPath DEFINITION_REPRESENTATION
lifecycleInfo/lifecycleTemplateName (#24,#19);
lifecycleInfo/lifecycleState
versionInfo/versionLevel
externalTypeId
actionInfo/action
OrganizationName #70= APPLIED_ORGANIZATION_
ASSIGNMENT(#71,#72,(#5));
#71= ORGANIZATION($,'Demo
Organization',$);
#72= ORGANIZATION_ROLE('Id
owner');

Data Exchange using Standards in Windchill 1747


EPMDocument Mapping
This section contains details out how EPMDocument is mapped in AP214
standard.
EPMDocument Type AP214 Product Definition
EPMDocument #1= PRODUCT_DEFINITION
('Design',$,#2,#4);
#2= PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3= PRODUCT('ASM01.ASM','asm01.
asm',$,(#5));
#5= PRODUCT_CONTEXT('part
definition',#6,'mechanical');
#4= PRODUCT_DEFINITION_
CONTEXT('part definition',
#6,'Design');
#6= APPLICATION_CONTEXT
(Digital Mockup');
#7= APPLICATION_PROTOCOL_
DEFINITION('international
standard','automotive_design',2009,#6);
#8= PRODUCT_RELATED_
PRODUCT_CATEGORY('part',$,(#3));
#9= PRODUCT_RELATED_
PRODUCT_CATEGORY('assembly',$,
(#3));
#10= PRODUCT_CATEGORY_
RELATIONSHIP('',$,#8,#9);
#70= APPLIED_ORGANIZATION_
ASSIGNMENT(#71,#72,(#3));
#71= ORGANIZATION($,'Demo
Organization',$);
#72= ORGANIZATION_ROLE('Id
owner');
Number #3= PRODUCT('ASM01.ASM','asm01.
asm',$,(#5));
Name #3= PRODUCT('ASM01.ASM','asm01.
asm',$,(#5));
versionInfo = #2=PRODUCT_DEFINITION_

1748 Customization Guide


EPMDocument Type AP214 Product Definition
versionInfo/versionId + FORMATION('A.1',$,#3);

versionInfo/iterationId

Data Exchange using Standards in Windchill 1749


EPMDocument Type AP214 Product Definition
ObjectID/ufid #18= DESCRIPTIVE_
masterUfid REPRESENTATION_ITEM
('key','value');
CADName
#19= REPRESENTATION('property
authoringApplication value',(#18),#21);
derived #21= REPRESENTATION_CONTEXT
domainName ('','');
folderPath #24= PROPERTY_DEFINITION('key',
$,#1);
lifecycleInfo/lifecycleTemplateName
#25= PROPERTY_DEFINITION_
ifecycleInfo/lifecycleState REPRESENTATION(#24,#19);
versionInfo/versionLevel e.g:
epmDocSubType Key is ‘domainName’
externalTypeId Value is ‘/Default’
epmDocType #8= PRODUCT_RELATED_
PRODUCT_CATEGORY('part',$,(#3));
#9= PRODUCT_RELATED_
PRODUCT_CATEGORY('assembly',$,
(#3));
#10= PRODUCT_CATEGORY_
RELATIONSHIP('',$,#8,#9);
If epmDocType = CADASSEMBLY
THEN that product will be added to
both the PRODUCT_RELATED_
PRODUCT_CATEGORY with ‘part’
and ‘assembly’ and there will be a
PRODUCT_CATEGORY_
RELATIONSHIP between them.
Else if epmDocType =
CADCOMPONENT THEN that
product will be added to PRODUCT_
RELATED_PRODUCT_CATEGORY
with ‘part’ value.
organizationName #70= APPLIED_ORGANIZATION_
ASSIGNMENT(#71,#72,(#3));
#71= ORGANIZATION($,'Demo
Organization',$);

1750 Customization Guide


EPMDocument Type AP214 Product Definition
#72= ORGANIZATION_ROLE('Id
owner');

Data Exchange using Standards in Windchill 1751


WTPart Mapping
Details out how WTPARTs are mapped in AP214 standard
WTPart Type AP214 Product Definition
WTPart #1= PRODUCT_DEFINITION
('Design',$,#2,#4);
#2= PRODUCT_DEFINITION_
FORMATION('A.1',$,#3);
#3= PRODUCT('0000000061','part',$,
(#5));
#5= PRODUCT_CONTEXT('part
definition',#6,'');
#4= PRODUCT_DEFINITION_
CONTEXT('part definition',
#6,'Design');
#6= APPLICATION_CONTEXT
('Mechanical Design');
#7= APPLICATION_PROTOCOL_
DEFINITION('international
standard','automotive_design',2009,#6);
#8= PRODUCT_RELATED_
PRODUCT_CATEGORY('part',$,(#3));
#70= APPLIED_ORGANIZATION_
ASSIGNMENT(#71,#72,(#3));
#71= ORGANIZATION($,'Demo
Organization',$);
#72= ORGANIZATION_ROLE('Id
owner');
Number #3= PRODUCT('0000000061','part',$,
(#5));
Name #3= PRODUCT('0000000061','part',$,
(#5));
versionInfo = #2=PRODUCT_DEFINITION_
versionInfo/versionId + FORMATION('A.1',$,#3);

versionInfo/iterationId
ObjectID/ufid #18= DESCRIPTIVE_
masterUfid REPRESENTATION_ITEM('key’,
‘value');
endItem

1752 Customization Guide


WTPart Type AP214 Product Definition
defaultTraceCode #19= REPRESENTATION('property
value',(#18),#21);
genericType
partType #21= REPRESENTATION_CONTEXT
('','');
partSource
#24= PROPERTY_DEFINITION('key',
DomainName $,#1); #25=PROPERTY_
folderPath DEFINITION_REPRESENTATION
(#24,#19);
lifecycleInfo/lifecycleTemplateName
lifecycleInfo/lifecycleState
versionInfo/versionLevel
externalTypeId
view #1= PRODUCT_DEFINITION
('Design',$,#2,#4);
OrganizationName #70= APPLIED_ORGANIZATION_
ASSIGNMENT(#71,#72,(#5));
#71= ORGANIZATION($,'Demo
Organization',$);
#72= ORGANIZATION_ROLE('Id
owner');

Data Exchange using Standards in Windchill 1753


Representation Mapping
Details out how Representation is mapped in AP214 standard
Representation Type AP214 Shape Definition
Representation
Representation #213= SHAPE_DEFINITION_
REPRESENTATION(#214,#215);
#214= PRODUCT_DEFINITION_
SHAPE('idealized representation','
((null))',#1);
#215= SHAPE_REPRESENTATION
('Representation',(),#216);
#216= GEOMETRIC_
REPRESENTATION_CONTEXT
('','external',3);
#217= SHAPE_ASPECT('NewRep',$,
#214,.F.);
#218= NAME_ATTRIBUTE('idealized
representation',#213);
WTPartRef/ EPMDocRef #214= PRODUCT_DEFINITION_
SHAPE('idealized representation','
((null))',#1);
Set as Product_Definition on
PRODUCT_DEFINITION_SHAPE.
definition
Name #217= SHAPE_ASPECT('NewRep',$,
#214,.F.);
description #214= PRODUCT_DEFINITION_
SHAPE('idealized representation','
((null))',#1);

1754 Customization Guide


Representation Type AP214 Shape Definition
Representation
ClassName #18= DESCRIPTIVE_
ObjectID/localId REPRESENTATION_ITEM
('key','value');
default
#19= REPRESENTATION('property
republishable value',(#18),#21);
domain #21= REPRESENTATION_CONTEXT
hasBoundingBox ('','');
boundingBox #24= PROPERTY_DEFINITION('key',
$,#214);
hasOctree
#25= PROPERTY_DEFINITION_
octree REPRESENTATION(#24,#19);
e.g:
Key is ‘ClassName’
Value is ‘wt.part.WTPart’
repContent/id #226= PROPERTY_DEFINITION_
REPRESENTATION(#227,#215);
#227= PROPERTY_DEFINITION
('external definition',$,#228);
#228= DOCUMENT_FILE
('CONTENTS/NewRep.pvz','',$,#229,'',
$);
#229= DOCUMENT_TYPE('digital');
#230= DOCUMENT_
REPRESENTATION_TYPE('digital',
#228);

Data Exchange using Standards in Windchill 1755


WTPartUsageLink
Details out how WTPARTUSAGELINKs are mapped in AP214 standard
WTPartUsageLink Type AP214 Next Assembly Usage
Occurrence
WTPartUsageLink #156= QUANTIFIED_ASSEMBLY_
COMPONENT_USAGE ('101','',$,#1,
#85, #24);
(Refers two product_defintion having
application context as “Mechanical
Design”)
usedBy #1= PRODUCT_DEFINITION
('Design',$,#2,#4);
(QACU entities relating_product_
definition reference)
uses #85= PRODUCT_DEFINITION
('Design',$,#86,#88);
(QACU entities related_product_
definition reference)
quantity #24=MEASURE_WITH_UNIT
(NUMERIC_MEASURE(4.),#300);
ObjectID/localId #18= DESCRIPTIVE_
quantityAmount REPRESENTATION_ITEM
('key','value');
quantityUnit
#19= REPRESENTATION('property
traceCode value',(#18),#21);
externalTypeId #21= REPRESENTATION_CONTEXT
('','');
#24= PROPERTY_DEFINITION('key',
$,#214);
#25= PROPERTY_DEFINITION_
REPRESENTATION(#24,#19);
e.g:
Key is ‘ClassName’
Value is ‘wt.part.WTPart’

1756 Customization Guide


WTPartUsageLink Type AP214 Next Assembly Usage
Occurrence
Occurrence #352= NEXT_ASSEMBLY_USAGE_
OCCURRENCE($,'single instance
usage',$,#227,
#156,'rd4');
#227= PRODUCT_DEFINITION
('Design',$,#228,#230);
#156= PRODUCT_DEFINITION
('Design',$,#157,#159);
(all other common attributes of
occurrence will map as default
mapping)
iba For details see IBA Mapping on page
1741.

Data Exchange using Standards in Windchill 1757


EPMReferenceLink
Details out how EPMREFERENCELINKs are mapped in AP214 standard
EPMReferenceLink Type AP214 Product Definition
Relationship
EPMReferenceLink #3195= PRODUCT_DEFINITION_
RELATIONSHIP('140','',$,#1,#129);
referenced_by 1= PRODUCT_DEFINITION('Design',
$,#2,#5);
references #214= PRODUCT_DEFINITION_
SHAPE('idealized representation','
((null))',#1);
ObjectID/localId #18= DESCRIPTIVE_
referenceType REPRESENTATION_ITEM
('key','value');
depType
#19= REPRESENTATION('property
asStoredChildName value',(#18),#21);
uniqueNDId #21= REPRESENTATION_CONTEXT
isRequired ('','');
externalTypeId #24= PROPERTY_DEFINITION('key',
$,#214);
#25= PROPERTY_DEFINITION_
REPRESENTATION(#24,#19);
e.g:
Key is ‘quantityAmount’
Value is ‘wt.part.WTPart’

1758 Customization Guide


EPMMemberLink
Details out how EPMMEMBERLINKs are mapped in AP214 standard
EPMMemberLink Type AP214 Product Definition
Relationship
EPMMemberLink #185= NEXT_ASSEMBLY_USAGE_
OCCURRENCE('1201','',$,#101,#1,$);
used_by #101= PRODUCT_DEFINITION
('Design',$,#102,#105);
uses #1= PRODUCT_DEFINITION
('Design',$,#2,#5);
occurences/attribute #18= DESCRIPTIVE_
ObjectID/localId REPRESENTATION_ITEM
('key','value');
isAnnotated
#19= REPRESENTATION('property
name value',(#18),#21);
asStoredChildName #21= REPRESENTATION_CONTEXT
depType ('','');
isPlaced #24= PROPERTY_DEFINITION('key',
$,#214);
isRequired
#25= PROPERTY_DEFINITION_
externalTypeId REPRESENTATION(#24,#19);
identifierSpaceName e.g:
compLayerIdx Key is ‘quantityAmount’
compRevNumber Value is ‘wt.part.WTPart’
identifier
Note
uniqueNDId Export occurences/attribute : Merge
isFixed all attributes specific to an
compNumber occurrence with a colon (:). And
add as a single attribute value to
occurences/attribute occurrence/attribute. Repeat this
hasTransform process for all occurrence elements.
transform/matrix4d/m03
transform/matrix4d/m13
transform/matrix4d/m23
transform/matrix4d/m33

Data Exchange using Standards in Windchill 1759


EPMMemberLink Type AP214 Product Definition
Relationship
#213= CONTEXT_DEPENDENT_
transform/matrix4d/m00 SHAPE_REPRESENTATION(#215,
#214);
transform/matrix4d/m01
#214= PRODUCT_DEFINITION_
transform/matrix4d/m02
SHAPE($,$,#185);
transform/matrix4d/m20
#215= (REPRESENTATION_
transform/matrix4d/m21 RELATIONSHIP('','',#90,#177)
transform/matrix4d/m22 REPRESENTATION_
transform/matrix4d/m30 RELATIONSHIP_WITH_
TRANSFORMATION(#186)
transform/matrix4d/m31
SHAPE_REPRESENTATION_
transform/matrix4d/m32 RELATIONSHIP());
#90= SHAPE_REPRESENTATION
('Design',(#94),#96);
#177= SHAPE_REPRESENTATION
('Design',(#94),#96);
#186= CARTESIAN_
TRANSFORMATION_OPERATOR_
3D('','',$,#188,#189,#187,$,#190);
#188= DIRECTION('',(1.,0.,0.));
#189= DIRECTION('',(0.,1.,0.));
#187= CARTESIAN_POINT('',
(0.,0.,0.));
#190= DIRECTION('',(0.,0.,1.));
Note: Process Transformation attributes
only when attribute hasTransform
exists.
iba For details see IBA Mapping on page
1741.

1760 Customization Guide


Log Levels
The following table details the possible log levels for validation used by the
wt.stepdex.validation.log.level property.
Log Level Description
AGGREGATE_DATA_TYPE Validate aggregate types
AGGREGATE_SIZE Validate aggregate sizes
AGGREGATE_UNIQUENESS Validate aggregate uniqueness
ARRAY_REQUIRED_ELEMENTS Validate aggregate content: mandatory/
optional membership
DETAILED_OUTPUT Produce detailed validation report
FULL_OUTPUT Produce full validation report
FULL_VALIDATION Validate all constraints.
GLOBAL_RULES Validate global rules
INVERSE_RULES Validate INVERSE rules
LOCAL_RULES Validate domain rules
NO_PRINT_OUTPUT Do not produce any printout
OUTPUT_STEPID Write step id to validation report in
addition to instance id
REQUIRED_ATTRIBUTES Validate mandatory/optional attributes
spec.
STOP_ON_FIRST_ERROR Stop validation of first error
SUBTYPES Validate subtypes of selected instance
(if validating an instance type)
UNIQUENESS_RULES Validate uniqueness rules

Data Exchange using Standards in Windchill 1761


Configuring Metadata Mapping
Metadata mapping is a critical component of data exchange if you are exchanging
product data between two systems that are configured differently. Configuring this
mapping prior to starting the data exchange cycles in a production environment is
an important step of setting up the environment. You must thoroughly assess the
data being exchanged and how the receiving system is setup. A complete
understanding between the two entities exchanging data of the nature of the data
and possible values of the configurable metadata is essential.
This section contains the following information:
• Tools Required on page 1762
• Identify Metadata to be Mapped on page 1763
• Establish a Source system to define the mapping rules on page 1763
• Enabling Collaboration Source ID on page 1763
• Configuring the Mapping Definitions on page 1764
• Populate Preference Definition on page 1766
• Populating Multi-Value Preference Instances on page 1769
• Configuration and Preference Instances – Examples on page 1771
• Deleting Preference Definitions on page 1772
• Enabling the use of Metadata Mapping on page 1772
• Default Value Provisioning for the Metadata on page 1773
• Logging on page 1775

Tools Required
1. A utility to define a source in a target system to identify a system that sends a
data to be imported. The source system is the one for which different mapping
rules are getting established. This utility creates
CollaborationSourceInfor, Repository and
PreferenceClient objects in the target system.
2. An import utility to populate PreferenceDefinition and
MultiValuePreference instances.
3. Optional. A Mapping Converter Utility provided as a reference
implementation (which can be custom created for specific business) that
converts mapping data in CSV format (usually populated using MS Excel like
spreadsheet editing tools) to an XML format that can be readily loaded as
Multi Value Preference Instances using the Import Utility described in
requirement 1. Otherwise, you would be required to manually create the files
that can be loaded using the tool described in requirement 1.

1762 Customization Guide


Identify Metadata to be Mapped
It is absolutely critical to identify the metadata that is used during import which
requires mapping, because it cannot be represented directly in the target system.
This mapping is an an iterative process that may take several cycles to perfect. As
a first test, you could try to import the product data as received. If it fails to
import, that would be an indication that you need to start preparing your target
system with the mapping rules.
The Method Server log4j properties could be updated with the entry
wt.ixb.step=TRACE that allows you to preserve the Windchill data model
that gets generated during the import in the form of P21 or P28 format. The files
could be located in the directory <Windchill>/temp/IXBExpImp/
stepdex. The P21/P28 file specific to the Windchill model then could be
inspected manually or using JOTNE’s EDM Supervisor to specifically establish
the data that requires mapping. Once the data is identified, you need to identify the
XPATH in IXB DTD of the tag for that data using the EXPRESS schema
definition file located at <Windchill>}/loadXMLFiles/windchill_
express_schema.exp for the Windchill data model. This definition file
includes the definitions in EXPRESS form along with the IXB DTD definitions
provided in the comment section. The XPATH of tags in IXB DTD form is the one
that is used to define the mapping rules. The reason for this is to make the
mapping feature applicable to all the applications that leverage the Windchill I/X
framework.

Establish a Source system to define the mapping rules


Use the MetadataMappingUtility to create a preference client and
repository in the system. The usage of the tool is as follows if invoked from a
windchill shell.
windchill
wt.fedInfra.collaboration.MetadataMappingUtility
-create test-system1 536416322-1456322554305-2141932519-
203-136-220-10 test-system1.test.com
• -create|update : flag to suggest creation or update of the
CollaborationSourceInfo
• <Source Name> (e.g. test-system1 : name for the collaboration source.
• <Source Id> (e.g. 536416322-1456322554305-2141932519-203-136-220-
10) : Universal ID of the source, typically a GUID.
• <source domain> (e.g. test-system1.test.com ): Domain of the source.

Enabling Collaboration Source ID


You can obtain the source GUID from the header of the STEP file and use it to
evaluate the mapping rules (including default value provisioning) by enabling a
property. Enabling this property means that the collaboration source ID

Data Exchange using Standards in Windchill 1763


(lastKnownRepository value from the header section of the schema in the
manifest) is read from the jar manifest instead of the in the
MetadataMappingUtility application.
To enable this functionality you must set the
wt.stepdex.create.manifest property in the stepdex.properties
file to true (wt.stepdex.create.manifest=true). The property is set
to false by default.

Configuring the Mapping Definitions


You need to configure the mappings by identifying what IXB DTD tags would
contribute to the condition and what to the value mapping. All these
configurations need to go in <WindchillE>\codebase\registry\ixb\
mapping\IXMappingConfiguration.xml.
<Mapping preferenceDefinition="R_objectContainerPath"
mappingProcessor="wt.ixb.publicforapps.extendedmapping.processor.
SingleTagMappingProcessor">

<!-This configuration relates to preference definition


‘R_objectContainerPath’ and uses a mapping processor for single tag -!>

<Tag value="objectContainerPath" regex="true" replaceFull="true" />

<!-objectContainerPath is the tag in IX DTD that would be used to apply


the mappings defined by the preference definition. And, regular expressions
would be utilized for this mapping with full replacement of the
value by the value in the preference instance -!>

</Mapping>
This is an example configuration for handling the lifecycle attribute mapping.
<Mapping preferenceDefinition="R_lifecycle" separator=";"
mappingProcessor="wt.ixb.publicforapps.extendedmapping.
processor.MultiTagMappingProcessor">

<!-R_lifecycle is the preference definition that provides


the mapping value and the mapping processor suggests the use
of multiple tags for the mapping values-!>

<Tag value="externalTypeId" condition="true" regex="true"/>


<!-externalTypeId is the tag that sets the condition, unless the
condition is fulfilled the mapping would not be applicable.
RegEx match is applicable here -!>

<!-You can have multiple elements mapped simultaneously-!>

<Tag value="lifecycleInfo/lifecycleTemplateName"/>
<!-this is the element that is mapped -!>

1764 Customization Guide


<Tag value="lifecycleInfo/lifecycleState"/>
<!-This is another element that is mapped -!>

</Mapping>

Note
A sample file resides in the system at the following location: ..\IX_LOAD\
prog_examples\Mappings\src\
IXMappingConfiguration.xml

You are required to populate all the Mapping elements from this file into
IXMappingConfiguration.xml to be able to use the Mapping Converter
utility.
As seen in the Mapping structure, multiple Mappings can be defined. Each
Mapping element is associated with one preferenceDefinition and one
mappingProcessor. An optional applicableXApplications attribute
can be provided to limit the Mapping configuration only to those IX applications.
applicableXApplications is a comma separated list of applicable
applications. If not specified, the Mapping is applicable to all applications.
Each Mapping element can have one or multiple tags defined under it. Tags can be
of type condition (defined by condition=”true” attribute) or Mappable type
(non-condition). These mappable tags would be implicitly have "condition=
false". The tags of type condition can specify an attribute “multi=true” to
define that the specific element referred to by the value attribute can have multiple
instances and each instance would be picked up to evaluate the condition.
Only mappable Tags are considered for returning the mapped value. One tag of
Mappable type can have only one applicable mappingProcessor and one
preferenceDefinition associated with it. In case there are multiple
Mapping definition for the same Tag, the first applicable Mapping definition in
this config file would be picked up for a mappable tag. Multiple tags of type
condition for a mapping will be AND condition.
Multiple Tags mean the mapping data would have parse-able (through attribute
separator) mapping in source mapping data and target data. Source values in
mapping data should follow the same sequence, separated by the separator, as
define for this Mapping element. Similarly, target values should follow the same
sequence of mappable tags defined for the Mapping. Tags can also be defined to
support regex through attribute regex="true”. Default is non-regex tag
(“false”). Regex supports replacement based on regular expression. If regex is
true for mappable tags, additionally attribute replaceFull="true" can be
specified (default false) to indicate the mapped value should replace the full value
when there is a match. All such defined expressions would be sorted in natural
order and a first match would be attempted going through all such mappings

Data Exchange using Standards in Windchill 1765


defined. Be careful to avoid unnecessary use of it to avoid bad performance. Tags
mentioned as condition may or may not have value specified in mapping data, but
it should still maintain the sequence through proper separator with blank condition
value.
OOTB, only two mapping processor implementation would be provided.
• wt.ixb.publicforapps.extendedmapping.processor.Sin
gleTagMappingProcessor would handle single tag mapping including
support for regex.
• wt.ixb.publicforapps.extendedmapping.processor.Multi
TagMappingProcessor would handle mappings with more than one tag
(including condition tags). This processor would also support regex in both
condition and mappable tags.
The above two OOTB mapping processors work on the concept of simple String
manipulation. If any business logic is required to be attached to those string values
under consideration from mapping data, you need to write their customized
mapping processor/Mapper based on the guideline (as described in Customizing
Mapping Behavior on page 1776) to extend these two processors.

Populate Preference Definition


There are two possible approaches here.
1. You need to populate a distinct Preference Definition for every mapping that is
configured in the <Windchill>\codebase\registry\ixb\
mapping IXMappingConfiguration.xml file. All such Preference
Definitions could be combined and loaded using the Preferences Import utility.
Each loadable Preference Definition would be populated in the importable file
as below
<PreferenceDefinition>
<name>R_objectContainerPath</name>
<!-identifier of the preference definition,
unique in the system-->
<visibility>HIDDEN</visibility>
<!-should be HIDDEN to avoid it showing up in the UI -->
<categoryName>FederationMapping</categoryName>
<!- it would be always FederationMapping -->
<displayName>R_objectContainerPath</displayName>
<description>Mapping for the containerPath </description>
<fullDescription> Mapping for the containerPath
</fullDescription>
<defaultValue></defaultValue>
<!-can have no value, but schema needs this element
to be specified -->
<handler>com.ptc.windchill.enterprise.preference.handler.
MultiValueMapPreferenceHandler:</handler>
<!-always MultiValuePreferenceHandler -->
<defaultComments>Mapping Test for

1766 Customization Guide


objectContainerPath</defaultComments>
<clientOverride>true</clientOverride>
<!-if true, implies one can override the value -->
</PreferenceDefinition>

And would confirm to the schema


<!ELEMENT PreferenceDefinition ( name, ObjectID?, BACInfo?, visibility,
categoryName, displayName, description, fullDescription, defaultValue,
handler, defaultComments?, clientOverride?, clientDelegate?, clientData?)>

Note
A sample file resides in the system at the following location: ..\IX_
LOAD\prog_examples\Mappings\src\mappings-pref.xml

• It is then required that the Preference Definition be linked to a specific


Preference Client. This is achieved by adding the following entry to the
same loader file. Refer to ‘renault-preference-
definition.xml’ included above.
<LinkPreferenceClientDefinition>
<name>R_objectContainerPath</name>
<!-identifier of the preference definition to be linked -->

<clientName>
536416322-1456322554305-2141932519-203-136-220-10
</clientName>

<!-name of the preference client to link to. This preference


client is implicitly created by the same utility that creates
the CollaborationSourceInfo and usually has the same name as
‘guid’ parameter provided to that utility.
This client name identifies the source system for which mappings
have been defined. One can relate the definition to multiple
client names and hence multiple source systems -->

</LinkPreferenceClientDefinition>
2. You can populate all the mappings in the CSV format as in the sample. And,
then a Mapping converter utility as follows to generate a Preference Definition
file that can be imported.

Note
A sample file resides in the system at the following location: ..\IX_
LOAD\prog_examples\Mappings\src\mappings.csv

Data Exchange using Standards in Windchill 1767


windchill
wt.ixb.publicforapps.extendedmapping.tools.Metadat
aMappingConverter -csvtoxml "e:\ptc\mapping-test\
mappings.csv" null mappings-pref true
mappings-pref is the output XML file name to be latter imported.
And, here is the command to import the preference definitions into the system.
windchill wt.preference.ImportPreferences
-importfile=e:\ptc\mapping-test\mappings-pref.xml
-overwriteValueConflicts -user=wcadmin -password=
wcadmin

Note
Find more on this utility using the ‘-usage’ option.
windchill wt.preference.ImportPreferences -usage

1768 Customization Guide


Populating Multi-Value Preference Instances
• For every Preference Definition you have created, you would populate multi
value preference instances that defines the mapping. These instances are in the
form of a key and value pair and are as well associated to the Preference
Client implying that you can have multiple instances (mapping) for multiple
source systems. The key can optionally include conditions along with the
value(s) to be mapped. The conditions and values can support regular
expressions. In case of RegEx support for the values, you can control if the
resulting value should replace the matching patterns or fully replace the whole
string.
<BeginMVPreferenceInstance>
<name>R_objectContainerPath</name>
<!-identifier of the preference definition -->
<comments>Just a test</comments>
<clientName>536416322-1456322554305-2141932519-203-136-220-10</clientName>
<!- the preference client (indirectly a source system) for which these
instances/mappings are defined
<locked>false</locked> <!-are these instances mutable -->
</BeginMVPreferenceInstance>
<MVPreferenceInstance> <!-every instance -->
<valuekey>/NULL</valuekey>
<!-- Default for objectContainerPath . If there is no objectContainerPath
element present or no value specified, the following default value
would be used then-->
<value>/wt.inf.container.OrgContainer=Demo Organization/
wt.pdmlink.PDMLinkProduct=GOLF_CART</value>
<locked>false</locked> <!-Is this instance mutable -->
</MVPreferenceInstance>
<MVPreferenceInstance> <!-every instance -->
<valuekey>/wt.inf.container.OrgContainer=Demo
Organization/wt.pdmlink.PDMLinkProduct=CART1</valuekey>
<!-a specific value is mapped -->
<value>/wt.inf.container.OrgContainer=Demo
Organization/wt.pdmlink.PDMLinkProduct=GOLF_CART</value>
<locked>false</locked> <!-Is this instance mutable -->
</MVPreferenceInstance>
<MVPreferenceInstance> <!-every instance -->
<valuekey>>.*CART2.*</valuekey>
<!-if the source containerPath has CART2 word in it, it
would be mapped to GOLF_CART always-->
<value>/wt.inf.container.OrgContainer=Demo
Organization/wt.pdmlink.PDMLinkProduct=GOLF_CART</value>
<locked>false</locked> <!-Is this instance mutable -->
</MVPreferenceInstance>
<EndMVPreferenceInstance/>

Data Exchange using Standards in Windchill 1769


Note
A sample file resides in the system at the following location: ..\IX_LOAD\
prog_examples\Mappings\src\mappings-instances.xml

• You can also use the mapping converter utility to create the XML file for the
preference instances that can be imported by using the same CSV file as
described in the Preference Definition section through the following
command: windchill
wt.ixb.publicforapps.extendedmapping.tools.Metadata
MappingConverter -csvtoxml "e:\ptc\mapping-test\
mappings.csv" null mappings-instances
○ mappings-instances is the name of xml file that can be imported to
populate multi-value preference instances.
• Here is the command to import preference instances into the system:
windchill wt.preference.ImportPreferences
-importfile=e:\ptc\mapping-test\mappings-
instances.xml -overwriteValueConflicts -user=wcadmin
-password=wcadmin -importSiteLevel -applyToSiteLevel

1770 Customization Guide


Configuration and Preference Instances – Examples
• folderPath based on externalTypeID

<Mapping preferenceDefinition="R_folderPath" separator=";"


mappingProcessor="wt.ixb.publicforapps.extendedmapping.
processor.MultiTagMappingProcessor">
<Tag value="externalTypeId" condition="true" regex="true"/>
<Tag value="folderPath"/>
</Mapping>
<BeginMVPreferenceInstance>
<name>R_folderPath</name>
<comments>Just a test</comments>
<clientName>536416322-1456322554305-2141932519-203-136-220-10
</clientName>
<locked>false</locked>
</BeginMVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>/NULL;/NULL</valuekey>
<!-- if externalTypeID and folderPath not specified, always set it
to a specific value à
<value>/Default/Unspecified</value>
<locked>false</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>wt.doc.WTDocument;/NULL</valuekey>
<!-default folderPath for externalTypeID that contains a string
‘wt.doc.WTDocument’ à
<value>/Default/WTDocument</value>
<locked>false</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>wt.part.WTPart;/NULL</valuekey>
<value>/Default/WTPart</value>
<locked>false</locked>
</MVPreferenceInstance>
<EndMVPreferenceInstance/>
• versionInfo mapping

<Mapping preferenceDefinition="R_versionInfo" separator=";"


mappingProcessor="wt.ixb.publicforapps.extendedmapping.
processor.MultiTagMappingProcessor">
<Tag value="externalTypeId" condition="true" regex="true"/>
<Tag value="versionInfo/versionId"/>
<Tag value="versionInfo/iterationId"/>
</Mapping>
<BeginMVPreferenceInstance>
<name>R_versionInfo</name>
<comments>Just a test</comments>
<clientName>536416322-1456322554305-2141932519-203-136-220-10
</clientName>

Data Exchange using Standards in Windchill 1771


<locked>false</locked>
</BeginMVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>wt.doc.WTDocument.*3DR,001,/NULL</valuekey>
<value>A,1</value>
<locked>false</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>wt.doc.WTDocument.*3DR,002,/NULL</valuekey>
<value>B,1</value>
<locked>false</locked>
</MVPreferenceInstance>
….
<EndMVPreferenceInstance/>

Deleting Preference Definitions


Preference Definitions and all the associated multi value preference instances
could be deleted using the LoadFromFile utility.

Note
A sample file resides in the system at the following location: ..\IX_LOAD\
prog_examples\Mappings\src\delete_preferenceDef_
NmLoader.xml

<csvDeletePreferenceDefinition handler="wt.preference.
LoadPreference.deletePreferenceDefinition">
<csvname>R_folderPath</csvname>
</csvDeletePreferenceDefinition>
This is the command to delete the preference definition and related multi-value
instances: Windchill wt.load.LoadFromFile e:\ptc\mapping-
test\deletePreferenceDef_NmLoader -u wcadmin -p wcadmin

Note
Preserve the CSV data for subsequent updates. As there is no easy way to
extract information from the system into CSV format

Enabling the use of Metadata Mapping


This metadata mapping feature is not enabled through any of the UI based
application that make use of I/X. You must programmatically enable it by setting
the flag on the ImportConextData.

1772 Customization Guide


ObjectImportParameters objectimportparameters =
new ObjectImportParameters();
ImportContextData importcontextdata = (ImportContextData)
objectimportparameters.getContextData();
importcontextdata.setUseExtendedMapping(true);
//By default, the extended mapping is always disabled
Once the metadata mapping is enabled as extended mapping, the
lastKnownDomainRepository is needed to be set to identify the Preference
Client to be used for the candidate mapping rules (defined as
MultiValuePreferenceInstances) to be evaluated for a given metadata
(hence XML tags in the form of XPATH) target value. There is a precedence in
how the lastKnownDomainRepository could be set.
• Set in the manifest file that is included in the bundle that contains the STEP
file to be imported. An example of the manifest file is as follows.

jar-in-jar=false

windchill-version=11.0.10.00.235

standard-dtd=standardX26.dtd

format=STEP

multiple=true

lastKnownRepository=536416322-1456322554305-2141932519
-203-136-220-10|mapping-test.ptcnet.ptc.com
• If it cannot be determined from the manifest file, the
lastKnownDomainRepository can be set on the
ImportContextData.
importcontextdata. setLastKnownDomainRepository
(‘536416322-1456322554305-2141932519-203-136-220-10|
mapping-test.ptcnet.ptc.com’);
• If it still cannot be determined, the OriginatingSystem from the header
in the STEP file is used to set the lastKnownDomainRepository.
• Otherwise, extended mapping is as good as disabled as the Preference Client is
in-deterministic.

Default Value Provisioning for the Metadata


At times, the incoming data may fail to provide a value for certain metadata in
Windchill. In such scenario, the extended mapping framework could be leveraged
to provide a default value. The mapping rule where the tags that are mappable is
set with a source value ‘/NULL’ implying that the source data does not provide
any value for the element specified by the value attribute of that tag and hence

Data Exchange using Standards in Windchill 1773


whatever value specified for the target in the rule is to be picked up. If such rule
includes tags of condition type, conditions would be determined before the target
value is arrived at. Below are some examples of such rules where a default value
for the folderpath is assigned based on the externalTypeId of the data
along with PreferenceDefinition and mapping configuration details.
<PreferenceDefinition>
<name>R_folderPath</name>
<visibility>HIDDEN</visibility>
<categoryName>FederationMapping</categoryName>
<displayName>R_folderPath</displayName>
<description>R_folderPath</description>
<fullDescription>R_folderPath</fullDescription>
<defaultValue></defaultValue>
<handler>com.ptc.windchill.enterprise.preference.handler.
MultiValueMapPreferenceHandler:</handler>
<defaultComments></defaultComments>
<clientOverride>false</clientOverride>
</PreferenceDefinition>
<LinkPreferenceClientDefinition>
<name>R_folderPath</name>
<clientName>536416322-1456322554305-2141932519-203-136-220-10</
clientName>
</LinkPreferenceClientDefinition>

<Mapping preferenceDefinition="R_folderPath" separator=";"


mappingProcessor="wt.ixb.publicforapps.extendedmapping.processor.
MultiTagMappingProcessor">
<Tag value="externalTypeId" condition="true" regex="true"/>
<Tag value="folderPath"/>
</Mapping>
<MVPreferenceInstance>
<valuekey>/NULL;/NULL</valuekey>
<value>/Default/Unspecified</value> <!-Default folderPath if
externaltypeId is not specified -->
<locked>FALSE</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>^(?=.*wt.doc.WTDocument).*$;/NULL</valuekey>
<value>/Default/WTDocument</value>
<!-Default folderPath for all data that has externalTypeId suggesting it is a
WTDocument or it’s subtype -->
<locked>FALSE</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>^(?!.*wt.part.WTPartUsageLink)(?=.*wt.part.WTPart).
*$;/NULL</valuekey>
<value>/Default/WTPart</value>
<!-Default folderPath for all data that has externalTypeId suggesting
it is a WTPart or it’s subtype -->

1774 Customization Guide


<locked>FALSE</locked>
</MVPreferenceInstance>
<MVPreferenceInstance>
<valuekey>^(?=.*wt.epm.EPMDocument).*$;/NULL</valuekey>
<value>/Default/EPMDocument</value>
<!-Default folderPath for all data that has externalTypeId suggesting
it is a EPMDocument or it’s subtype
<locked>FALSE</locked>
</MVPreferenceInstance>

Logging
You can use the following log4j flags to enable the logging in the Method
Server.
• log4j.logger.wt.ixb.publicforapps.extendedmapping
=DEBUG or TRACE
• log4j.logger.wt.ixb.publicforapps.extendedmapping
=DEBUG or TRACE
The DEBUG level would identify the exact mapping rule that has come into effect
while the TRACE level would provide you additional details on what different
candidate mapping rules were evaluated.

Data Exchange using Standards in Windchill 1775


Customizing Mapping Behavior

Class Diagram

1776 Customization Guide


Customization

Note
Please refer to the class diagram and data structure table in the previous
section for reference.

OOTB, only two mapping processor implementations are provided.


• wt.ixb.publicforapps.extendedmapping.processor.Sin
gleTagMappingProcessor would handle single tag mapping including
support for regex.
• wt.ixb.publicforapps.extendedmapping.processor.Multi
TagMappingProcessor would handle mappings with more than one tag
(including condition tags). This processor would also support regex in both
condition and non condition tags.

The above two OOTB mapping processors work on the concept of simple String
matching. For most of the cases, those two classes should be sufficient to provide
desired mapping behavior.
If any business logic is required to be added to those string values under
consideration from mapping data and object data to be imported, customer would
need to write their customized mapping processor/Mapper based on this guideline
below.
To customize the behavior of the above two mapping processors, extend
SingleTagMappingProcessor or MultiTagMappingProcessor as
per the use case and override postprocessMappedValue method. The
details of the method parameters are as follows.
/** Customization point to process Mapped value as per business logic.
* OOTB implementation returns the mapped value as-is
* @param tag The Tag to be evaluated for Mapping
* @param parentTags Parent Tags separated by <code>TAG_SEPARATOR</code>.
* This would be null if tagValue represents the full Tag as defined in
* IXMappingConfiguration.xml
* @param value The source value for the Tag
* @param mappedValue The mapped value of the source value for the Tag
* @param srcElement The IXBElement representation of the object
* data to be imported
* @return The Mapped value
* @throws WTException
*/

protected String postprocessMappedValue(String tag, String parentTags,


String value, String mappedValue,
IxbElement srcElement) throws WTException

Data Exchange using Standards in Windchill 1777


For Mapping definition with multiple Tags with conditions and regular
expressions in IXMappingConfiguration.xml, matching mapping can be
more than one. In those cases, OOTB implementation uses the logic to return the
match with maximum conditions met (there can be some mappings in multiple
matches without all conditions provided in the mapping). Also in case of multiple
regular expressions defined in the Mapping matches the source object values, the
natural sort order as implemented by java.util.TreeMap is used and the
first match is used for mapping value.
The above behavior to pick the matching key can be customized.
Extend
wt.ixb.publicforapps.extendedmapping.mapper.MultiTagCom
plexMapper class and override getBestMatchKey method as per the below
details.
/** Get the best matching key to be used to get the mapped values
* OOTB implementation returns the first matching key.
* This api can be overridden to return any other matching key from
* @param matchingKeys
* All matching keys satisfying the Mapping conditions
* @return The first key out of all matching keys
*/

protected List<String> getBestMatchKey(List<List<String>> matchingKeys)


Then extend SingleTagMappingProcessor or
MultiTagMappingProcessor as per the use case and override protected
Mapper getMapper() method to return the above mapper as per the use case.
In both the customization cases mentioned above, the extended Mapping
processor needs to be added to the appropriate Mapping element attribute
“mappingProcessor” in <Windchill Home>/codebase/registry/
ixb/mapping/IXMappingConfiguration.xml. For example, if the
extended class from MultiTagMappingProcessor is
mycustomizationpackage.MyMultiTagMappingProcessor, the
mappingProcessor attribute should assigned
mycustomizationpackage.MyMultiTagMappingProcessor. All
values in the example are for example only and needs to be as per the customer
defined Mapping
<Mapping preferenceDefinition="ExtendedLifecycleMapping" separator=";"
mappingProcessor="mycustomizationpackage.MyMultiTagMappingProcessor">
<Tag value="externalTypeId" condition="true" regex="true"/>
<Tag value="lifecycleInfo/lifecycleTemplateName"/>
<Tag value="lifecycleInfo/lifecycleState"/>
</Mapping>

1778 Customization Guide


AP214 AIM Mapping
There is a mapping file (mapping.xml) that defines the elements and attribute
mapping used to convert the Windchill native format (<Windchill>\
loadXMLFiles\standardx20.dtd) to the AP214 AIM Part 21 format
(<Windchill>\codebase\wt\ixb\schema\aim\automotive_
design.xsd).
There are three types of mapping:
• Alias Mapping on page 1780
• Value Reference Mapping on page 1781
• Element Mapping on page 1788

Sample Mapping Name Patterns


The following convention represents mapped element name and required_
attributes:
• A relative path, such as Template_instance/Name/value, get/set
values by it.
• An absolute path for a single element, such as /Application_context,
which means this element is stored in the same level as the current element
instead of a sub element.
An alias path, can use an alias to reduce duplicated mapped names. The AIM
format does not use alias mapping
• A value reference path, such as value_reference_product_
related_product_category, which will be defined in the value_
reference_mapping section as follows:
<value_reference name="value_reference_product_related_product_category"
mapped_name="/Product_related_product_category"
ref_attribute="Products/Product"
connect_reference="Formation/Product_definition_formation/ref/Of_product/
Product/ref" path="name" multiple_instances="true" />

This creates a Product_related_product_category element in the


same level as the current element and stores the value to name. Product_
related_product_category also contains a reference of current
elements by product, which can be used as a value reference to reduce
duplicated mapped names.
• A second value reference path (sometimes referred to as “value reference path
two”), such as value_reference_describe_link_product_
definition_shape, which will be defined in value_reference_
mapping section as follows:
<value_reference name="value_reference_describe_link_product_definition

Data Exchange using Standards in Windchill 1779


_shape" ref_type="/Product_definition_shape" attribute_name=
"Definition/Product_definition_shape/ref">
<sub_value_reference attribute_name="" identifier=""
required_attributes="expId={UUID}" />
</value_reference>

A Product_definition_shape element is created to store the ID, keep


the name as empty and set the element to current element by Definition/
Product_definition_shape/ref. You can also use a value reference
to reduce duplicated mapped names.

Tips
• The following variables can be used in required_attributes:
• {ROOT} : Use the root object of this element
• {UUID} : Create a random UUID
• {KEY} : Use the name of the current attribute
• {VALUE} : Use the string representation of the current attribute’s value

Alias Mapping
Defines an alias for the mapping path which can be used in mapped name and
required attributes in element mapping section. This will reduce duplicated
mappings. This will be only a relative path.

Parent Name : alias_mapping/alias


Name Type Data Type Req? Description
exceptions Element Element No Sub alias mapping,
used with type attribute
to provide different
alias mapping by
different attribute
values.
name Attribute ID Yes Unique name of alias
element
path Attribute String No Related path to store/
retrieve value.

1780 Customization Guide


Name Type Data Type Req? Description
attribute Attribute String No Attribute name for
store/retrieve value,
used with path
together.
type Attribute String No Windchill attribute
name to be used to
identify a different
alias.

Parent Name : exceptions


Name Type Data Type Req? Description
value Attribute String Yes The value of defined
type attributes.
path Attribute String No Related path to store/
retrieve value.
attribute Attribute String No Attribute name for
store/retrieve value,
used with path
together.

Value Reference Mapping


Defines alias for mapping path which can be used in mapped name and required
attributes in element mapping section, we will use this to reduce duplicated
mappings. This will contain two kinds of paths:
• Path No. 01: Element which holds a reference to the current element, as
follows:
<Specific_item_classification uid="uid">
<Associated_item>ref_uid</Associated_item>
<Classification_name>assembly</Classification_name>
</Specific_item_classification>
<Item uid="ref_uid">
</Item>

• Path No. 2: Element which is referenced by current element, as follows:


<Document_file uid="uid">
<File_format>ref_uid</File_format>
</Document_file>
<Document_format_property uid="ref_uid">
<Data_format>ApplicationData</Data_format>
</Document_format_property>

Data Exchange using Standards in Windchill 1781


Parent Name : value_reference_mapping/value_reference
Name Type Data Type Req? Description
exceptions Element Element No Used with type
attribute in element
mapping to define
different value
reference mapping for
different attribute
value.
reference_to Element Element No Element mapping
which current element
will reference
sub_value_ Element Element No Sub value reference
reference mapping, used for Path
No. 2 only
name Attribute ID Yes Unique name of value
reference element
path Attribute String No Related path to store/
retrieve value, used for
Path No. 1 only. Path
also supports value
references and comma
separated values. Refer
to mapping.xsd for
more details.
condition Attribute String No Condition to filter the
element, used for Path
No. 1 only, support
following pattern only:
<key=<value>
mapped_name Attribute String No Parent element name
for the path, used for
Path No. 1 only.
type Attribute String No For Path No. 1: The
relative path to check if
current element is a
supported Windchill
tag. for example, Item_
shape will also be used
to represent
representation and

1782 Customization Guide


Name Type Data Type Req? Description
EPMDescribeLink .
For Path No .2: The
element name which
will be create as
reference, this should
be sub element.
ref_attribute Attribute String No The relative path which
keeps the object
reference, used for Path
No. 1 only.
connect_ Attribute String No The sub element which
reference will be used as
reference.
multiple_ Attribute String No To maintain the
instances multiple instances of
the describe elements
(i.e. that has ‘mapped_
name’ and ‘ref_
attribute’) associated
with root element or
current element. This is
needed when the root
element has no direct
link with the described
element.
reuse Attribute Boolean No Defines if this element
is reusable, work with
locate_by attribute
together to find
previous created
element instead of
create new one all the
time.
locate_by Attribute String No Defines the attribute
list of a reusable
element, separated by a
comma (,).
ref_type Attribute String No The element name
which will be create as
reference, this should
be root element, used

Data Exchange using Standards in Windchill 1783


Name Type Data Type Req? Description
for Path No. 2 only.
required_ Attribute String No Attributes which are
attributes required for current
element, separated by a
comma (,).It can be
relative path and alias
path.
attribute_name Attribute String No The relative path which
will be used to hold
reference or attribute
value, used for Path
No. 2 only. If identifier
is configured, it will be
used to store the name
of attribute.
identifier Attribute String No The relative path which
will be used to hold
attribute value, works
with attribute_name
together to store
attribute name and
value.
Separator Attribute String No Splits the value
associated with this
attribute based on the
given separator value.
Assigns each part of
this value to the
various sections as
specified in the path
Attribute.

Parent Name : exceptions


Name Type Data Type Req? Description
sub_value_ element element No Sub value reference
reference mapping, used for Path
No. 2 only
attribute_name attribute string No The relative path which
will be used to hold
reference or attribute

1784 Customization Guide


Name Type Data Type Req? Description
value, used for Path
No. 2 only.
value attribute string No The attribute value to
choose current
exception
configuration.
ref_type attribute string No The element name
which will be create as
reference, this should
be sub element, used
for Path No. 2 only.
type attribute string No The element name
which will be create as
reference, this should
be root element, used
for Path No. 2 only.
required_ attribute string No Attributes which are
attributes required for current
element, separated by a
comma (,).It can be
relative path and alias
path.

Parent Name : sub_value_reference_type


Name Type Data Type Req? Description
add_to_ element element No Element mapping
element which current element
will be added to.
reference_to element element No Element mapping
which current element
will reference it.
attribute_name attribute string No The relative path which
will be used to hold
reference or attribute
value, used for Path
No. 2 only. If identifier
is configured, it will be
used to store the name
of attribute.

Data Exchange using Standards in Windchill 1785


Name Type Data Type Req? Description
required_ attribute string No Attributes which are
attributes required for current
element, separated by a
comma (,).It can be
relative path and alias
path.
connect_ attribute string No The sub element which
reference will be used as
reference
ref_type attribute string No The element name
which will be create as
reference, this should
be root element, used
for Path No. 2 only.
unit_attribute_ attribute string No The relative path which
name will be used to hold
unit attribute value.
Used for Path No. 2
and iba only.
reuse attribute boolean No Defines if this element
is reusable, work with
locate_by attribute
together to find
previous created
element instead of
create new one all the
time.
locate_by attribute string No Defines the attribute
list of a reusable
element, separated by a
comma (,).

1786 Customization Guide


Name Type Data Type Req? Description
identifier attribute string No The relative path which
will be used to hold
attribute value, works
with attribute_name
together to store
attribute name and
value.
format Attribute String No Format Numeric values
as per requirement. For
instance in dates, days,
months, hours &
minutes should be
displayed in format '00'
though the actual date
is less then 10.
Applicable only for
numeric values

Parent Name : add_to_element


Name Type Data Type Req? Description
name attribute string Yes Path which is used to
add current element to
another element. It can
be relative path and
alias path.
value attribute string Yes The value which will
be used to find parent
element.

Parent Name : reference_to


Name Type Data Type Req? Description
name attribute string Yes Path which is used to
reference another
element. It can be
relative path and alias
path.
value attribute string Yes The value which will
be used to find another
element.

Data Exchange using Standards in Windchill 1787


Name Type Data Type Req? Description
connect_ attribute string Yes The sub element which
reference will be used as
reference
parent_ attribute string No The attribute is created
reference_ to cater very special
attribute condition. when the
current element unable
to identify the correct
root element. The
attribute is used to
identify the
intermediates objects
from the parent
element. The
intermediate object is
then compared with the
‘name’ object.
Example: Next_
assembly_usage_
occurence is linked to
product_deifnitions
and Transformation is
linked with shape_
representation of the
products. While import
to compare the correct
shape representation,
one has to traverse
from instance product_
definition to shape_
representation.

Tips
Use the following pattern to define value attribute:
{ROOT}/usedBy/ObjectReference/ufid, this means to get the value of
attribute named usedBy/ObjectReference/ufid from the current element.

Element Mapping
Defines the mapping from Windchill native element (or attribute) to other formats.
There are two kinds of mappings: element and attribute. Element mapping
can contain element_mapping or attribute mapping as sub elements.

1788 Customization Guide


Parent Name : element_mapping
Name Type Data Type Req? Description
element element element Yes Root element mapping
root_tag_name attribute string Yes Local name of the root
element.
id_tag attribute string No Attribute name whose
type is xsd:ID.
ref_tag attribute string No Attribute name whose
type is xsd:IDREF,
which is used globally.
required_ attribute string No Required attributes of
attributes the root element,
separated by comma
(,).

Parent Name : element


Name Type Data Type Req? Description
element element element No Sub element mapping
attribute element element No Attributes mapping
under current element
name attribute string Yes Element name of
Windchill native
format.

mapped_name attribute string Yes Mapped element name.


reuse attribute boolean No Defines whether the
element should be
retrieved from previous
exported ones instead
of creating new one,
used with use_for_
reuse in attribute
mapping together to
find exported element
default_ attribute string No Mapped element name
mapped_ (with attribute element
name_for_ name and value
attributes element name) which
is used to store the
attributes which do not

Data Exchange using Standards in Windchill 1789


Name Type Data Type Req? Description
have explicit
mappings. This should
be the name of a value
reference mapping.
required_ attribute string No Attributes of the
attributes element which are
required but cannot be
set during export,
separated by a comma
(,). It can hold relative
path, alias path and
value reference path.
type attribute string No Windchill attribute
name to be used to
identify a different
alias or value
reference.
mapped_tag_ attribute string No Element name and
name value to identify
current Windchill
element. It is used if
one AP214 AIM
element is used to
represent multiple
Windchill elements.
import_context attribute string No Decide Windchill
element name by value
of parent element,
mapping between
element name and
value of parent element
should be one-one.

1790 Customization Guide


Name Type Data Type Req? Description
add_current_ attribute string No The path used to add
element_to_ current element to
parent_by parent one. It can hold
relative path, alias path
and value reference
path. This will be used
for sub element only.
connect_ attribute string No The sub element which
reference will be used to be
added to parent
element, used with
add_current_element_
to_parent_by together

Parent Name : attribute


Name Type Data Type Req? Description
exceptions element element No Used to hold different
attribute mapping by
different attribute
value.
name attribute string Yes Element name of
Windchill native
format.
mapped_name attribute string Yes Mapped element name.
It can be relative path,
alias path and value
reference path.
Separated by a comma
(,).
append attribute boolean No Defines whether to
append to the existing
value with defined
separator, default value
is false. For example,
this can be used to
append the iteration
number to the version
(A.5, where the value 5
is appended to A with a
period [.] separator).

Data Exchange using Standards in Windchill 1791


Name Type Data Type Req? Description
seperator attribute string No Separator for append.
For example, this can
be used to concatenate
the iteration number to
version (A.5, where the
value 5 is appended to
A with a period [.]
separator).
add_to_ attribute string No Define the path which
element current element should
be added after finding a
previously exported
element. It can be
relative path, alias path
and value reference
path. Used for link
element only.
use_for_reuse attribute boolean No Defines whether the
attribute should be
used to find previously
exported element, used
with reuse in element
mapping together.
connect_ attribute string No The sub element which
reference will be used to be
added to parent
element, used with
add_current_element_
to_parent_by together
reference_to attribute string No Defines the sub
element used as
reference. Used for link
element only. Default
value is false.
identifier attribute string No Attribute name which
is used to retrieve value
from default_mapped_
name_for_attributes
configuration. If this is
configured, mapped_

1792 Customization Guide


Name Type Data Type Req? Description
name will not be used
during import.
reuse attribute boolean No Define whether the
attribute value can be
multiple. If set to false,
multiple values can be
retrieved during
import. Must be used
when mapped_name is
not configured. Default
value is false.
value attribute string No This is used to
represent a constant
value, which will be set
during export and can
be fetched during
import
required_ attribute string No Attributes which are
attributes required for current
element, separated by a
comma (,).It can be
relative path, alias path
and value reference
path.
add_current_ attribute string No The path used to add
element_to_ current element to
parent_by parent one. It can hold
relative path, alias path
and value reference
path. This will be used
for sub element only.
required_ attribute string No Attributes which are
attributes_for_ required for parent
parent element, separated by a
comma (,).It can be
relative path, alias path
and value reference
path.

Data Exchange using Standards in Windchill 1793


Name Type Data Type Req? Description
Works with add_
current_element_to_
parent_by together to
set attributes basing on
different attribute value

use_parent_ attribute boolean No Define whether to use


object parent element as
reference to find
related element and
store/retrieve attribute
value. Default value is
false.
index attribute int No Define the index to get
value from a list value.

Parent Name : exceptions


Name Type Data Type Req? Description
value attribute string Yes Value of parent
attribute
mapped_value attribute string No Mapped value for
original value, it should
be one-one mapping.
attribute_name attribute string No Element name which is
used to store the
attribute value. It can
be relative path, alias
path and value
reference path. Will not
set attribute when
mapped_element_name
is configured
mapped_ attribute string No Element name which is
element_name used to identify
original value, it should
be one to one mapping,
used for import only
required_ attribute string No Attributes which are
attributes required for current

1794 Customization Guide


Name Type Data Type Req? Description
element, separated by a
comma (,).It can be
relative path, alias path
and value reference
path.
add_current_ attribute string No The path used to add
element_to_ current element to
parent_by parent one. It can hold
relative path, alias path
and value reference
path. This will be used
for sub element only.
required_ attribute string No Attributes which are
attributes_for_ required for parent
parent element, separated by a
comma (,).It can be
relative path, alias path
and value reference
path.
Works with add_
current_element_to_
parent_by together to
set attributes basing on
different attribute value
connect_ attribute string No The sub element which
reference will be used to be
added to parent
element, used with
add_current_element_
to_parent_by together
use_parent_ attribute boolean No Define whether to use
object parent element as
reference to find
related element and
store/retrieve attribute
value. Default value is
false.

Data Exchange using Standards in Windchill 1795


Windchill Elements and Attribute Mapping for Supported
Windchill Objects
The table below explains the mapping between elements and attributes for some
of the key Windchill objects which are supported for this implementation:

Object Type : WTPart ; AP214 AIM Root Element : Product


Windchill Attribute AP214 AIM Element Description
Name
number Id
ObjectID/ufid Descriptive_ Use Property_definition_
masterUfid representation_item representation
/Representation/
descriptive_
representation_item/name
to store the value
Property_definition/name
to store the key and act as
a linking node between
Product_definition and
Property_definition_
representation. “value_
reference_Product_
definition_Property_
definition_representation”
is used to build
relationship.
name Name
versionInfo/versionId Product_definition_ Concatenate as A.2.
versionInfo/iterationId formation/id

1796 Customization Guide


Windchill Attribute AP214 AIM Element Description
Name
iba String_value or Float_ • String_value:
value or Integer_value or Property_definition_
date/time(depends on representation
IbaType) /Representation/
descriptive_
representation_item/
name to store the
value Property_
definition/name to
store the key and act
as a linking node
between Product_
definition and
Property_definition_
representation.
• Float_value:
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value, qualified_
representation_item/
precision_qualifier to
store the precision
• Integer_value:
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value

Data Exchange using Standards in Windchill 1797


Windchill Attribute AP214 AIM Element Description
Name
• Time/date:Applied_
date_and_time_
assignment/date_and_
time calendar_date
local_timeto store
date and time
respectively.
Property_definition/
name to store the key
and act as a linking
node between
Product_definition
and Property_
definition_
representation/
Applied_date_and_
time_assignment.
contentItem Document_file Use applied_document_
reference to build
relationship with item.
The attributes of content
are stored in different
element linked with
Document_file
endItem Descriptive_ Use Property_definition_
defaultTraceCode representation_item representation
/Representation/
genericType descriptive_
partType representation_item/name
partSource to store the value
Property_definition/name
folderPath to store the key and act as
lifecycleInfo/ a linking node between
lifecycleTemplateName Product_definition and
versionInfo/versionLevel Property_definition_
representation. “value_
domainName reference_Product_
lifecycleInfo/ definition_Property_
lifecycleState definition_representation”
externalTypeId is used to build

1798 Customization Guide


Windchill Attribute AP214 AIM Element Description
Name
relationship.

Object Type : EPMDocument ; AP214 AIM Root Element : Product


Windchill Attribute AP214 AIM Element Description
Name
number id
ObjectID/ufid Descriptive_ Use Property_definition_
representation_item representation
/Representation/
descriptive_
representation_item/name
to store the value
Property_definition/name
to store the key and act as
a linking node between
Product_definition and
Property_definition_
representation. “value_
reference_Product_
definition_Property_
definition_representation”
is used to build
relationship.
name name
CADName Descriptive_ Use Property_definition_
representation_item representation
/Representation/
descriptive_
representation_item/name
to store the value
Property_definition/name
to store the key and act as
a linking node between
Product_definition and
Property_definition_
representation. “value_
reference_Product_
definition_Property_
definition_representation”
is used to build

Data Exchange using Standards in Windchill 1799


Windchill Attribute AP214 AIM Element Description
Name
relationship.
versionInfo/versionId product_definition_ Concatenate as A.2.
versionInfo/iterationId formation
iba String_value or Float_ • String_value :
value or Integer_value or Property_definition_
date/time(depends on representation
IbaType) /Representation/
descriptive_
representation_item/
name to store the
value Property_
definition/name to
store the key and act
as a linking node
between Product_
definition and
Property_definition_
representation.
• Float_value :
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value, qualified_
representation_item/
precision_qualifier to
store the precision
• Integer_value :
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value
• Time/date:Applied_
date_and_time_
assignment/date_and_
time calendar_date

1800 Customization Guide


Windchill Attribute AP214 AIM Element Description
Name
local_timeto store
date and time
respectively.Property_
definition/name to
store the key and act
as a linking node
between Product_
definition and
Property_definition_
representation/
Applied_date_and_
time_assignment.
contentItem Document_file Primary Content: Same as
representationSecondary
Content:Use applied_
document_reference to
build relationship with
item. The attributes of
content are stored in
different element linked
with Document_file
masterUfid Descriptive_ Use Property_definition_
authoringApplication representation_item representation
/Representation/
epmDocType descriptive_
derived representation_item/name
domainName to store the value
Property_definition/name
folderPath to store the key and act as
lifecycleInfo/ a linking node between
lifecycleTemplateName Product_definition and
lifecycleInfo/ Property_definition_
lifecycleState representation. “value_
reference_Product_
versionInfo/versionLevel
definition_Property_
epmDocSubType definition_representation”
externalTypeId is used to build
relationship.

Data Exchange using Standards in Windchill 1801


Object Type : EPMMemberLink ; AP214 AIM Root Element : Next_
assembly_usage_occurrence
Windchill Attribute AP214 AIM Element Description
Name
iba String_value or Float_ • String_value:
value or Integer_value or Property_definition_
date/time(depends on representation
IbaType) /Representation/
descriptive_
representation_item/
name to store the
value Property_
definition/name to
store the key and act
as a linking node
between Product_
definition and
Property_definition_
representation.
• Float_value :
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value, qualified_
representation_item/
precision_qualifier to
store the precision
• Integer_value :
Property_definition_
representation
/Representation/
value_representation_
item/name to store the
value

1802 Customization Guide


Windchill Attribute AP214 AIM Element Description
Name
• Time/date : Applied_
date_and_time_
assignment/date_and_
time calendar_date
local_timeto store
date and time
respectively.
Property_definition/
name to store the key
and act as a linking
node between
Product_definition
and Property_
definition_
representation/
Applied_date_and_
time_assignment.
ObjectID/localId Descriptive_ Use Property_definition_
uses/ObjectReference/ representation_item representation
ufid /Representation/
descriptive_
representation_item/name
to store the value
Property_definition/name
to store the key and act as
a linking node between
Product_definition and
Property_definition_
representation. “value_
reference_Product_
definition_Property_
definition_representation”
is used to build
relationship.
transform/matrix4d/m0* Direction Use Representation_
relationship_with_
transformation/
Cartesian_
transformation_operator_
3D/direction/direction_

Data Exchange using Standards in Windchill 1803


Windchill Attribute AP214 AIM Element Description
Name
ratios to store X axis.
transform/matrix4d/m1* Direction Use Representation_
relationship_with_
transformation/
Cartesian_
transformation_operator_
3D/direction/direction_
ratios to store Y axis.
transform/matrix4d/m2* Direction Use Representation_
relationship_with_
transformation/
Cartesian_
transformation_operator_
3D/direction/direction_
ratios to store Z axis.
transform/matrix4d/ Cartesian_ Use Representation_
m03transform/matrix4d/ transformation_operator_ relationship_with_
m13transform/matrix4d/ 3d transformation/
m23 Cartesian_
transformation_operator_
3D/Cartesian_point/
coordinates to store
translation information.
occurences/attribute Descriptive_ Use Property_definition_
name representation_item representation
/Representation/
isAnnotated descriptive_
asStoredChildName representation_item/name
depType to store the value
Property_definition/name
isPlaced to store the key and act as
isRequired a linking node between
externalTypeId Product_definition and
Property_definition_
representation. “value_
reference_Product_
definition_Property_
definition_representation”
is used to build
relationship.

1804 Customization Guide


Data Exchange using Standards in Windchill 1805
AP242 XPX Mapping Guide
This section of the documentation provides mapping of Windchill Express
Schema Entities to Managed Model Based 3D Engineering Schema entities. This
document covers core business objects mapping table and Part 21 format.
• Mapping Table for AP242 to Windchill EXPRESS Entities on page 1807
• Mapping Table for Import of AP242 (non-Windchill data) to Windchill
EXPRESS Entities on page 1838

1806 Customization Guide


Mapping Table for AP242 to Windchill EXPRESS Entities
The documentation on mapping AP42 to Windchill EXPRESS Entities includes
the following information:
• Model Attributes Mapping on page 1808
• Organization Mapping Table on page 1812
• Identifier Mapping Table on page 1813
• EPMDocument on page 1814
• WTDocument on page 1817
• WTPart on page 1820
• WTPartUsageLink and Occurrence on page 1823
• EPMMemberLink on page 1826
• WTPartDescribeLink on page 1831
• WTPartReferenceLink on page 1834
• WTPartReferenceLink on page 1834
• Business Fields on page 1835

Data Exchange using Standards in Windchill 1807


Model Attributes Mapping

String Mapping

String Mapping Table


WNC BOM
Attribute name StringValue.definition as
PropertyDefinitionString
Attribute value StringValue.valueComponent
as CharacterString
Association of Attribute to its StringValue.definition = ‘’
WTObject. StringValue.valueComponent
= ‘’
PropertyValueAssignment.as
signedTo =
PropertyAssignmentSelect
Classification.class=‘part
properties’ or ‘document
properties’ or ‘validation
properties’
PropertyValueAssignment.
classifiedAs
=[Classification]
PropertyValueAssignment.as
signedPropertyValues[] =
StringValue

Part 21 Representation
#1= PART($,$,$,$,$,$,(#2));
#2= PARTVERSION($,$,$,$,$);
#12= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING('wt.epm.EPMDocument:129174'));
#13= PROPERTYVALUEASSIGNMENT($,$,$,$,(#12),#2,$);

1808 Customization Guide


Business Fields String Mapping

Business Fields String Mapping Table


WNC BOM
Attribute name STRINGVALUE.definition as
PropertyDefinition
PROPERTYDEFINITION.id as
IdentifierSelect
IDENTIFIER.id as
IdentifierString
Attribute value STRINGVALUE.valueComponent
as CharacterString
Association of Attribute to its StringValue.definition =
WTObject. propDefn
propDefn.id = ident
propDefn.propertyType =
‘user defined attribute’
ident.id =’’
StringValue.valueComponent
= ‘’
PropertyValueAssignment.as
signedTo =
PropertyAssignmentSelect
Classification.class=‘part
properties’ or ‘document
properties’ or ‘validation
properties’
PropertyValueAssignment.
classifiedAs
=[Classification]
PropertyValueAssignment.as
signedPropertyValues[] =
StringValue

Part 21 Representation
#8= ORGANIZATION(IDENTIFIERSTRING('/NULL'),#9,$,$,$);
#9= LOCALIZEDSTRING($,'Demo Organization');
#95= VIEWCONTEXT(CHARACTERSTRING('part definition'),PROXYSTRING(
'mechanical design'),PROXYSTRING('design'));
#133= PARTVIEW($,$,$,$,$,#95,$);
#136= PROPERTYVALUEASSIGNMENT($,$,$,$,(#98),#133,$);

Data Exchange using Standards in Windchill 1809


#96= IDENTIFIER('sValue',$,CLASSSTRING('identification information'),#8);
#97= PROPERTYDEFINITION(#96,$,$,$,CLASSSTRING('user defined attribute'),$);
#98= STRINGVALUE($,$,#97,$,$,CHARACTERSTRING('test String'));

Business Fields Numerical Mapping

Business Fields Numerical Mapping Table


WNC BOM
Attribute name NUMERICALVALUE.name as
CHARACTERSTRING
and
NUMERICALVALUE.definition
as PropertyDefinition
PROPERTYDEFINITION.id as
IdentifierSelect
IDENTIFIER.id as
IdentifierString
Attribute value NUMERICALVALUE.valueCompo
nent as REAL
Association of Attribute to its NumericalValue.definition =
WTObject. propDefn
propDefn.id = ident
propDefn.propertyType =
‘user defined attribute’
ident.id =’’
NumericalValue.valueCompo
nent = ‘’
PropertyValueAssignment.as
signedTo =
PropertyAssignmentSelect
Classification.class=‘part
properties’ or ‘document
properties’ or ‘validation
properties’
PropertyValueAssignment.
classifiedAs
=[Classification]
PropertyValueAssignment.as
signedPropertyValues[] =
StringValue

1810 Customization Guide


Part 21 Representation
#8= ORGANIZATION(IDENTIFIERSTRING('/NULL'),#9,$,$,$);
#9= LOCALIZEDSTRING($,'Demo Organization');
#17= UNIT(CLASSSTRING('/ANY'),$,$,CLASSSTRING('$'));
#95= VIEWCONTEXT(CHARACTERSTRING('part definition'),PROXYSTRING(
'mechanical design'),PROXYSTRING('design'));
#133= PARTVIEW($,$,$,$,$,#95,$);
#136= PROPERTYVALUEASSIGNMENT($,$,$,$,(#151),#133,$);
#149= IDENTIFIER('intValue',$,CLASSSTRING('identification information'),#8);
#150= PROPERTYDEFINITION(#149,$,$,$,CLASSSTRING('user defined attribute'),$);
#151= NUMERICALVALUE(CHARACTERSTRING('intValue'),$,#150,$,$,$,#17,894.,$);

Data Exchange using Standards in Windchill 1811


Organization Mapping Table
Windchill BOM
organizationId organization.id
organizationName organization.name
Association of Organization to its LocalizedString.text=’’
WTObject Organization.id=’’
Organization.name=
LocalizedString
Identifier.id=’’
Identifier.role=’’
Identifier.identification
Context=Organization
PartVersion.id = Identifier

Part 21 Representation
#1= PART($,$,$,$,$,$,(#2));#2= PARTVERSION(#5,$,$,$,$);
#3= ORGANIZATION(IDENTIFIERSTRING('Demo Organization'),#4,$,$,$);
#4= LOCALIZEDSTRING($,'Demo Organization');
#5= IDENTIFIER('1.1',$,CLASSSTRING('identification information'),#3);

1812 Customization Guide


Identifier Mapping Table
WNC BOM
versionInfo.versionId Identifier.id=versionId + ‘.’
versionInfo.iterationId + iterationId
- Identifier.role =
ClassString(‘identification
information’)
Identifier.identification
Context = ORGANIZATION
Note
For more information see
Organization Mapping Table on
page 1812.

Part 21 Representation
#11= ORGANIZATION(IDENTIFIERSTRING('Demo Organization'),#12,$,$,$);
#12= LOCALIZEDSTRING($,'Demo Organization');
#27= IDENTIFIER('A.1',$,CLASSSTRING('identification information'),#11);

Data Exchange using Standards in Windchill 1813


EPMDocument

Mapping table
Windchill BOM
e_EPMDocument Part. (for master)
PartVersion and PartView. (for
iteration)
Part.versions[] =
PartVersion
PartVersion.views[] =
PartView
PartView.initialContext =
ViewContext
ViewContext.description =
‘part definition’
ViewContext.applicationDo
main=’digital mock-up’
ViewContext.lifeCycle
Stage=’design’
r_number Part.id
Name LocalizedString.text
Part.name = LocalizedString
Version PartVersion.id = Identifier
Note
For more information see Identifier
Mapping Table on page 1813.
lifecycleState Approval.status

1814 Customization Guide


Windchill BOM
Attributes For more information seeModel
[ObjectID.localId, Attributes Mapping on page 1808.
ObjectID.ufid,
objectContainerPath,
ownerApplication,
authoringApplication,
masterUfid,
masterExternalTypeId,
CADName,
epmDocType,
defaultUnit,
collapsible,
genericType,
lengthScale,
domainName,
folderPath,
versionInfo.versionLevel,
versionInfo.series,
versionInfo.versionPosi
tion,
versionInfo.iterationSer
ies,
versionInfo.iterationPosi
tion,
lifecycleTemplateName,ex
ternalTypeId]
Organization For more information see Organization
Mapping Table on page 1812.

Part 21 Representation
#1= PART(#79,#80,$,$,’/NULL’,$,(#2));
#2= PARTVERSION(#44,$,$,$,(#5));
#5= PARTVIEW($,$,$,$,$,#9,$);
#7= APPROVAL($,$,$,$,$,$,CLASSSTRING('DESIGN'),$);
#8= APPROVALASSIGNMENT($,$,$,#7,(#2));

Data Exchange using Standards in Windchill 1815


#9= VIEWCONTEXT(CHARACTERSTRING('part definition'),
PROXYSTRING('digital mock-up'),
PROXYSTRING('design'));
#11= ORGANIZATION(IDENTIFIERSTRING('Demo Organization'),#12,$,$,$);
#12= LOCALIZEDSTRING($,'Demo Organization');
#44= IDENTIFIER('1.1',$,CLASSSTRING('identification information'),#11);
#79= IDENTIFIER('0000000063.PRT',$,CLASSSTRING
('identification information'),#11);
#80= LOCALIZEDSTRING($,'piston.prt');

1816 Customization Guide


WTDocument

Mapping Table
WNC BOM
e_WTDocument Document. (for master)
DocumentVersion and
DocumentDefinition. (for
iteration)
Document.versions[] =
DocumentVersion
ApprovalAssignment.assigne
dApproval = Approval
ApprovalAssignment.as
signedTo=[DocumentVersion]
. (for lifecycle)
DocumentVersion.views[] =
DocumentDefinition
ViewContext.description =
‘part definition’
ViewContext.applicationDo
main=’mechanical design’
ViewContext.lifeCycle
Stage=’design’
ViewContext.lifeCycle
Stage=’InWork’
r_number Document.id
Name LocalizedString.text
Document.name =
LocalizedString
Version DocumentVersion.id =
Identifier
Note
For more information see Identifier
Mapping Table on page 1813.
lifecycleState Approval.status

Data Exchange using Standards in Windchill 1817


WNC BOM
Attributes For more information see Model
[ObjectID.localId, Attributes Mapping on page 1808.
FederationInfo.additional All these attributes will be exported as
PersistInfo.updateCount, the PropertyValueAssignment

FederationInfo.additional
PersistInfo.master.local
Id,
FederationInfo.additional
PersistInfo.master.update
Count,
FederationInfo.repositor
yInfo.lastKnownRepository,
FederationInfo.masterRepo
sitoryInfo.owningReposito
ry,
FederationInfo.masterRepo
sitoryInfo.masterLastKnown
Repository,
ObjectID.ufid,objectContai
nerPath,
masterUfId,docType,
docTitle,
department,
domainName,
folderPath,
versionInfo.versionLevel,
versionInfo.series,
versionInfo.versionPosi
tion,
versionInfo.iterationSer
ies,
versionInfo.iterationPosi
tion,
lifecycleTemplateName,ex
ternalTypeId]
Organization For more information see Identifier

1818 Customization Guide


WNC BOM
Mapping Table on page 1813.

Part 21 Representation
#1= DOCUMENT(#38,#39,$,$,(#6),$,(#2));
#2= DOCUMENTVERSION(#30,$,$,$,(#4));
#4= DOCUMENTDEFINITION($,$,$,$,$,$,$,$,$);
#8= APPROVALASSIGNMENT($,$,$,#31,(#2));
#13= VIEWCONTEXT(CHARACTERSTRING('part definition'),PROXYSTRING(
'mechanical design'),PROXYSTRING('design'));
#30= IDENTIFIER('A.1',$,CLASSSTRING('identification information'),#11);
#31= APPROVAL($,$,$,$,$,$,CLASSSTRING('INWORK'),$);
#38= IDENTIFIER('0000000001',$,CLASSSTRING('identification information'),#11);
#39= LOCALIZEDSTRING($,'submissionDocument');

Data Exchange using Standards in Windchill 1819


WTPart

Mapping Table
WNC BOM
e_WTPart Part. (for master)
PartVersion and PartView. (for
iteration)
Part.versions[] =
PartVersion
PartVersion.views[] =
PartView
PartView.initialContext =
ViewContext
OR
AssemblyDefinition.initial
Context = ViewContext
(PartView is used if the WTPart has
no children. AssemblyDefinition
is used if the WTPart does have
children).
ViewContext.description =
‘part definition’
ViewContext.applicationDo
main=’mechanical design
ViewContext.lifeCycle
Stage=’design’
r_number Part.id
name LocalizedString.text
Part.name = LocalizedString
version PartVersion.id = Identifier
For more information see Identifier
Mapping Table on page 1813.
lifecycleState Approval.status
Attributes For more information see Model
[ObjectID.localId, Attributes Mapping on page 1808.
ObjectID.ufid,

1820 Customization Guide


WNC BOM
ObjectID.FederationInfo.ad
ditionalPersistInfo.mas
ter.localId,
ObjectID.FederationInfo.re
positoryInfo.lastKnownRepo
sitory,
ObjectID.FederationInfo.
masterRepositoryInfo.ow
ningRepository,
ObjectID.FederationInfo.
masterRepositoryInfo.last
KnownRepository,
objectContainerPath,
masterUfid,
name,
defaultUnit,endItem,de
faultTraceCode,collapsi
ble, phantom ,
hidePartInStructure,partTy
pe,partSource,domainName,
folderPath,view,
versionInfo.versionLevel,
versionInfo.series,
versionInfo.versionPosi
tion,
versionInfo.iterationSer
ies,
versionInfo.iterationPosi
tion,
versionInfo.predecessor,
versionInfo.derivedFrom,
versionInfo.viewLevel,
lifecycleInfo.lifecycleTem
plateName,
externalTypeId]

Data Exchange using Standards in Windchill 1821


WNC BOM
Organization For more information see Organization
Mapping Table on page 1812.
IF (endItem = ‘true’)
partType = ‘seperable’ Part. partTypes =
('product','assembly')
partType = ‘inseperable’ Part. partTypes =
('product','assembly','
piece part')
partType = ‘component’ Part. partTypes =
('product','piece part')
IF (endItem = ‘false’)
partType = ‘seperable’ Part. partTypes =
('assembly')
partType = ‘inseperable’ Part. partTypes =
('assembly','piece part')
partType = ‘component’ Part. partTypes = ('piece
part')

Part 21 Representation
#1= PART(#45,#46,$,$,('assembly'),$,(#2));
#2= PARTVERSION(#30,$,$,$,(#5));
#5= PARTVIEW($,$,$,$,$,#14,$);
OR
#5= ASSEMBLYDEFINITION($,$,$,$,$,#14,$,$);
#7= APPROVAL($,$,$,$,$,$,CLASSSTRING('INWORK'),$);
#8= APPROVALASSIGNMENT($,$,$,#7,(#2));
#12= ORGANIZATION(IDENTIFIERSTRING('Demo Organization'),#13,$,$,$);
#13= LOCALIZEDSTRING($,'Demo Organization');
#14= VIEWCONTEXT(CHARACTERSTRING('part definition'),
PROXYSTRING('mechanical design'),
PROXYSTRING('design'));
#30= IDENTIFIER('A.1',$,CLASSSTRING('identification information'),#12);
#45= IDENTIFIER('0000000001',$,CLASSSTRING
('identification information'),#12);
#46= LOCALIZEDSTRING(('en-IN'),'Test_Part1');

1822 Customization Guide


WTPartUsageLink and Occurrence

Mapping Table
WNC BOM
e_WTPartUsageLink NextAssemblyViewUsage.rela
tionType=’next assembly view’
Attributes; localId, ufid, For more information see Model
externalTypeId, traceCode, Attributes Mapping on page 1808.
lineNumber, With
cadSynchronized, PropertyDefinitionSelect as
componentId NextAssemblyViewUsage
quantityAmount, NumericalValue.valueCompo
quantityUnit nent= quantityAmount
NumericalValue.unit = Unit
Unit.name = quantityUnit
NextAssemblyViewUsage.quan
tity = NumericalValue
uses • For WTPartUsageLink Mapping
:
NextAssemblyViewUsage.re
lated=PartView
• For Occurrence Mapping :
SingleOccurrence.defini
tion=PartView
The ‘uses’ role in Windchill is a
WTPartMaster. However AP242
requires a PartView entity which
maps to a WTPart. You can navigate
from a PartView (WTPart) to the
Part (WTPartMaster) using the
INVERSE attributes on the PartView
and PartVersion entities.
usedBy • For WTPartUsageLink Mapping
:
NextAssemblyViewUsage.re
lating=
AssemblyDefinition
• For Occurrence Mapping :
NextAssemblyOccurrenceU
sage.relating=

Data Exchange using Standards in Windchill 1823


WNC BOM
AssemblyDefinition
Occurrence (if present) NextAssemblyOccurrenceUsa
ge.relationType=’next
assembly occurrence’
NextAssemblyOccurrenceUsa
ge.related=
SingleOccurrence
Occurrence.name SingleOccurrence.id
AND
NextAssemblyViewUsage.loca
tionIndicator = (All occurrence
names concatenated together.
Concatenation symbol = ‘,’)
Occurrence. occGlobalId, For more information see Model
buildStatus Attributes Mapping on page 1808.
With
PropertyDefinitionSelect as
SingleOccurrence.
Occurrence.transformString CartesianTransformation.ro
tationMatrix,translation
Vector = Sections of
transformString after split by ‘#’.
NextAssemblyOccurrenceUsa
ge.placement =
CartesianTransformation

Part 21 Representation
#1= ASSEMBLYDEFINITION($,$,$,$,$,#11,$,$);
#11= VIEWCONTEXT(CHARACTERSTRING('part definition'),
PROXYSTRING('mechanical design'),
PROXYSTRING('design'));
#51= ASSEMBLYDEFINITION($,$,$,$,$,#11,$,$);
#228= NEXTASSEMBLYVIEWUSAGE($,$,$,*,#51,#1,$,IDENTIFIERSTRING('A1,A2'),#230);
#229= PROPERTYVALUEASSIGNMENT($,$,$,$,(#231,#233,#234,#235,#236,#237),#228,$);
#230= NUMERICALVALUE($,$,PROPERTYDEFINITIONSTRING('quantity'),$,$,$,#220,2.,$);
#231= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,CHARACTERSTRING
('wt.part.WTPartUsageLink:160359'));
#233= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('ufid'),$,$,CHARACTERSTRING
('wt.part.WTPartUsageLink:160359|789177195-1452009825602-
2048102341-88-244-152-10|
esdcsv-ccv11c.ptcnet.ptc.com'));
#234= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalType'),$,$
,CHARACTERSTRING

1824 Customization Guide


('WCTYPE|wt.part.WTPartUsageLink'));
#235= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('traceCode'),$,$,
CHARACTERSTRING('0'));
#236= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('cadSynchronized'),$,$,
CHARACTERSTRING('no'));
#237= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('componentId'),$,$,
CHARACTERSTRING
('ae7fd4fa-3452-49ed-a1ec-00cfc8ed15a2'));
#238= PROPERTYVALUEASSIGNMENT($,$,$,$,(#241,#243),#239,$);
#239= SINGLEOCCURRENCE(IDENTIFIERSTRING('A1'),$,$,$,#1);
#240= NEXTASSEMBLYOCCURRENCEUSAGE($,$,$,*,#51,#239,#244);
#241= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('occGlobalId'),$,$
,CHARACTERSTRING
('789177195-1452009825602-2048102341-88-244-152-10:1382'));
#243= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('buildStatus'),$,$,
CHARACTERSTRING
('not_built'));
#244= CARTESIANTRANSFORMATION($,$,((0.723874543659168,0.01563703695269772,
-0.6897543969541414),(0.6308190108172688,0.3898854360647259,0.
6708626702508803),
(0.2794154981989259,-0.9207305956793002,0.2723640019280953)),1.,
(2.,3.000000000000001,4.000000000000001));

Data Exchange using Standards in Windchill 1825


EPMMemberLink

Mapping Table
WNC BOM
e_EPMMemberLink (that has NextAssemblyOccurrenceUsa
transform matrix, with ge.relationType=’next
quantityAmount equal to ‘1’ and assembly
quantityUnit equal to ‘ea’) view’NextAssemblyOccurren
ceUsage.related=
SingleOccurrence
e_EPMMemberLink (that doesn’t ViewOccurrenceRelationshi
have transform matrix, or p.relationType=’next
quantityUnit not equal to ‘ea’, or assembly
quantityAmount not equal to ‘1’) view’ViewOccurrenceRelation
ship.related=
QuantifiedOccurrence
Attributes; localId, ufid, Model Attributes Mapping on page
externalTypeId, depType, 1808
asStoredChildName, With
isRequired, uniqueLinkId, PropertyDefinitionSelect as
uniqueNDId, isSuppressed, NextAssemblyOccurrenceUs
isFixed, isAnnotated, age if e_EPMMemberLink has
identifier, quantityAmount, transform, otherwise
quantityUnit, isPlaced, ViewOccurrenceRelationship.
hasTransform, compNumber,
compRevNumber,
compLayerIdx, isSubstitute,
identiferSpaceName
quantityAmount, NumericalValue.valueCompo
quantityUnit nent= quantityAmount
(These are only mapped for NumericalValue.unit = Unit
QuantifiedOccurrence,
Unit.name = quantityUnit
otherwise quantity must be ‘1’ and unit
must be ‘ea’, so we don’t map) QuantifiedOccurrence.quan
tity = NumericalValue
name Occurrence(SingleOccurrence or
QuantifiedOccurrence).id
usedBy NextAssemblyOccurrenceUsa
ge.relating=
AssemblyDefinition
OR

1826 Customization Guide


WNC BOM
ViewOccurrenceRelationshi
p.relating=
AssemblyDefinition
uses NextAssemblyOccurrenceUsa
ge.related= PartView
OR
ViewOccurrenceRelationshi
p.related = PartView
The ‘uses’ role in Windchill is a
EPMDocumentMaster. However
AP242 requires a PartView entity
which maps to a EPMDocument. You
can navigate from a PartView
(EPMDocument) to the Part
(EPMDocumentMaster) using the
INVERSE attributes on the PartView
and PartVersion entities.
transform NextAssemblyViewUsage.
placement =
GeometricRepresentationRe
lationshipWithCartesian
Transformation
GeometricRepresentationRe
lationshipWithCartesian
Transformation.transforma
tion =
CartesianTransformation

Part 21 Representation
#204= NEXTASSEMBLYOCCURRENCEUSAGE($,$,$,*,#1,#227,#229);
#205= PROPERTYVALUEASSIGNMENT($,$,$,$,(#206,#208,#209,#210,
#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,
#221,#222,#223,#224,#225,#226),#204,$);
#206= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING
('wt.epm.structure.EPMMemberLink:192332'));
#208= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('ufid'),$,$,CHARACTERSTRING(
'wt.epm.structure.EPMMemberLink:192332|789177195-1452009825602-2048102341-88
-244-152-10
|esdcsv-ccv11c.ptcnet.ptc.com'));
#209= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'),$,$,
CHARACTERSTRING(
'WCTYPE|wt.epm.structure.EPMMemberLink|

Data Exchange using Standards in Windchill 1827


com.ptc.ptcnet.DefaultEPMMemberLink'));
#210= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('depType'),$,$,
CHARACTERSTRING('2'));
#211= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('asStoredChildName'),$,$,
CHARACTERSTRING('0000000322.prt'));
#212= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isRequired'),$,$,
CHARACTERSTRING('true'));
#213= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('uniqueLinkId'),$,$,
CHARACTERSTRING('2401'));
#214= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('uniqueNDId'),$,$,
CHARACTERSTRING('PDM_2401'));
#215= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isSuppressed'),$,$,
CHARACTERSTRING('false'));
#216= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isFixed'),$,$,
CHARACTERSTRING('true'));
#217= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isAnnotated'),$,$,
CHARACTERSTRING('true'));
#218= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('identifier'),$,$,
CHARACTERSTRING('-2001'));
#219= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('quantityAmount'),$,$,
CHARACTERSTRING('1.0'));
#220= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('quantityUnit'),$,$,
CHARACTERSTRING('ea'));
#221= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isPlaced'),$,$,
CHARACTERSTRING('true'));
222= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('hasTransform'),$,$,
CHARACTERSTRING('true'));
#223= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compNumber'),$,$,
CHARACTERSTRING('-1'));
#224= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compRevNumber'),$,$,
CHARACTERSTRING('-1'));
#225= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compLayerIdx'),$,$,
CHARACTERSTRING('-1'));
#226= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isSubstitute'),$,$,
CHARACTERSTRING('false'));
#227= SINGLEOCCURRENCE(IDENTIFIERSTRING('G1'),$,$,$,#146);
#228= CARTESIANTRANSFORMATION($,$,((1.,0.,0.),(0.,1.,0.),(0.,0.,1.))
,1.,(1.,2.,3.));
#229= GEOMETRICREPRESENTATIONRELATIONSHIPWITHCARTESIANTRANSFORMATION
($,$,$,#69,#197,.F.,#228);
#1= ASSEMBLYDEFINITION($,$,$,$,$,#9,$,$);
#9= VIEWCONTEXT(CHARACTERSTRING('part definition'),
PROXYSTRING('digital mock-up'),
PROXYSTRING('design'));
#197= EXTERNALGEOMETRICMODEL(IDENTIFIERSTRING('0000000322.prt'),$,$,$,$,
#198,(#200),$,$,#181,$);
#198= GEOMETRICCOORDINATESPACE(IDENTIFIERSTRING('/NULL'),$,3,$);
#200= AXISPLACEMENT($,$,$,(0.,0.,0.),$);

1828 Customization Guide


OR

#236= VIEWOCCURRENCERELATIONSHIP($,$,$,CLASSSTRING('next assembly


occurrence'),#1,#258);
#237= PROPERTYVALUEASSIGNMENT($,$,$,$,(#238,#240,#241,#242,#243,
#244,#245,#246,#247,
#248,#249,#250,#251,#252,#253, #254,#255,#256,#257),#236,$);
#238= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING
('wt.epm.structure.EPMMemberLink:192334'));
#240= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('ufid'),$,$,
CHARACTERSTRING(
'wt.epm.structure.EPMMemberLink:192334|789177195-1452009825602-
2048102341-88-244-152-10
|esdcsv-ccv11c.ptcnet.ptc.com'));
#241= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'
),$,$,CHARACTERSTRING(
'WCTYPE|wt.epm.structure.EPMMemberLink|com.ptc.ptcnet.
DefaultEPMMemberLink'));
#242= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('depType'),$,$,
CHARACTERSTRING('131072'));
#243= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('asStoredChildName'),$,$,
CHARACTERSTRING('0000000323.prt'));
#244= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isRequired'),$,$,
CHARACTERSTRING('true'));
#245= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('uniqueLinkId'),$,$,
CHARACTERSTRING('2403'));
#246= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('uniqueNDId'),$,$,
CHARACTERSTRING('PDM_2403'));
#247= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isSuppressed'),$,$,
CHARACTERSTRING('false'));
#248= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isFixed'),$,$,
CHARACTERSTRING('true'));
#249= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isAnnotated'),$,$,
CHARACTERSTRING('true'));
#250= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('identifier'),$,$,
CHARACTERSTRING('-2003'));
#251= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('quantityAmount'),$,$,
CHARACTERSTRING('1.0'));
#252= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('quantityUnit'),$,$,
CHARACTERSTRING('ea'));
#253= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isPlaced'),$,$,
CHARACTERSTRING('false'));
#254= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compNumber'),$,$,
CHARACTERSTRING('-1'));
#255= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compRevNumber'),$,$,
CHARACTERSTRING('-1'));
#256= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('compLayerIdx'),$,$,
CHARACTERSTRING('-1'));

Data Exchange using Standards in Windchill 1829


#257= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('isSubstitute'),$,$,
CHARACTERSTRING('false'));
#258= QUANTIFIEDOCCURRENCE(IDENTIFIERSTRING('/NULL'),$,$,$,#87,
#259);
#259= NUMERICALVALUE($,$,PROPERTYDEFINITIONSTRING('quantity'),$,$,$,
#260,1.,$);
#260= UNIT(CLASSSTRING('ea'),$,$,$);
#1= ASSEMBLYDEFINITION($,$,$,$,$,#9,$,$);
#9= VIEWCONTEXT(CHARACTERSTRING('part definition'),PROXYSTRING
('digital mock-up'),
PROXYSTRING('design'));

1830 Customization Guide


WTPartDescribeLink

Mapping Table
WNC AP242
e_WTPartDescribeLink DocumentAssignment
describedBy documentAssignment.as
signedDocument :=
documentVersion (i.e.
DocumentDefinition);
describes documentAssignment.as
signedTo ++
assemblyDefinition (i.e.
PartView);

Part 21 Representation
#62= DIGITALDOCUMENTDEFINITION($,$,$,$,$,$,$,$,$,(#89,#105,#119));
#358= PARTVIEW($,$,$,$,$,#8,$);
#379= DOCUMENTASSIGNMENT($,$,$,CLASSSTRING('description'),#62,(#358),$);
#380= PROPERTYVALUEASSIGNMENT($,$,$,$,(#386,#388),#379,$);
#382= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('creation'),$,(#379));
#384= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('update'),$,(#379));
#386= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING('wt.part.WTPartDescribeLink:118036'));
#388= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'),$,$,
CHARACTERSTRING('WCTYPE|wt.part.WTPartDescribeLink'));

Data Exchange using Standards in Windchill 1831


WTPartReferenceLink

Mapping Table
WNC AP242
e_WTPartReferenceLink DocumentAssignment
referencedBy documentAssignment.as
signedTo ++
assemblyDefinition (i.e.
PartView);
references documentAssignment.as
signedDocument :=
documentVersion (i.e.
DocumentDefinition);

Part 21 Representation
#358= PARTVIEW($,$,$,$,$,#8,$);
#419= DOCUMENTASSIGNMENT($,$,$,CLASSSTRING('description'),$,(#358),$);
#420= PROPERTYVALUEASSIGNMENT($,$,$,$,(#426,#428),#419,$);
#422= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('creation'),$,(#419));
#424= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('update'),$,(#419));
#426= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING('wt.part.WTPartReferenceLink:116155'));
#428= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'),$,$,
CHARACTERSTRING('WCTYPE|wt.part.WTPartReferenceLink'));

1832 Customization Guide


WTPartReferenceLink

Mapping Table
WNC AP242
e_WTPartReferenceLink DocumentAssignment
referencedBy documentAssignment.as
signedTo ++
assemblyDefinition (i.e.
PartView);
references documentAssignment.as
signedDocument :=
documentVersion (i.e.
DocumentDefinition);

Part 21 Representation
#358= PARTVIEW($,$,$,$,$,#8,$);
#419= DOCUMENTASSIGNMENT($,$,$,CLASSSTRING('description'),$,(#358),$);
#420= PROPERTYVALUEASSIGNMENT($,$,$,$,(#426,#428),#419,$);
#422= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('creation'),$,(#419));
#424= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('update'),$,(#419));
#426= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING('wt.part.WTPartReferenceLink:116155'));
#428= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'),$,$,
CHARACTERSTRING('WCTYPE|wt.part.WTPartReferenceLink'));

Data Exchange using Standards in Windchill 1833


WTPartReferenceLink

Mapping Table
WNC AP242
e_WTPartReferenceLink DocumentAssignment
referencedBy documentAssignment.as
signedTo ++
assemblyDefinition (i.e.
PartView);
references documentAssignment.as
signedDocument :=
documentVersion (i.e.
DocumentDefinition);

Part 21 Representation
#358= PARTVIEW($,$,$,$,$,#8,$);
#419= DOCUMENTASSIGNMENT($,$,$,CLASSSTRING('description'),$,(#358),$);
#420= PROPERTYVALUEASSIGNMENT($,$,$,$,(#426,#428),#419,$);
#422= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('creation'),$,(#419));
#424= DATETIMEASSIGNMENT($,$,$,CLASSSTRING('update'),$,(#419));
#426= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('localId'),$,$,
CHARACTERSTRING('wt.part.WTPartReferenceLink:116155'));
#428= STRINGVALUE($,$,PROPERTYDEFINITIONSTRING('externalTypeId'),$,$,
CHARACTERSTRING('WCTYPE|wt.part.WTPartReferenceLink'));

1834 Customization Guide


Business Fields

Mapping Table
WNC AP242
e_businessField Business Fields String Mapping on
Boolean/String/URL values page 1809
Where attribute_name =
businessField.businessFiel
dID.name
attribute_value =
businessField.r_value
Date Timestamp DATETIMEASSIGNMENT
DATETIMEASSIGNMENT.id =
businessField.businessFiel
dID.name
CLASS.id = ‘user defined
attribute’
DATETIMEASSIGNMENT.role =
class
DATETIMEASSIGNMENT.as
signedDate =
businessField/Value
The date is converted to ISO standard
format. Refer to mapping information.
YYYY-MM-DDTHH:MM:SS
DATETIMEASSIGNMENT.as
signedTo =
PropertyAssignmentSelect
Integer Value For more information seeBusiness
Fields Numerical Mapping on page
1810.
NumericalValue.name =
businessField.businessFiel
dID.name
NumericalValue.value_
component =
busienssField.r_value

Data Exchange using Standards in Windchill 1835


WNC AP242
Float Value For more information see Business
Fields Numerical Mapping on page
1810.
NumericalValue.name =
businessField.businessFiel
dID.name
NumericalValue.value_
component =
busienssField.r_value
Handle precision:
NumericalValue.significant
Digits = precision
Handle Unit:
Unit. Name = ‘/ANY’
NumericalValue.unit = unit
significantDigits and unit are
attributes of ValueWithUnit, which
is supertype of NumericalValue.
Unit Value Unit.name = Base Unit
Unit.quantity =
QOM(Quantity of Measure)
Rest same as float value.

1836 Customization Guide


Data Exchange using Standards in Windchill 1837
Mapping Table for Import of AP242 (non-Windchill data) to
Windchill EXPRESS Entities
The documentation on mapping AP242 (non-Windchill data) to Windchill
EXPRESS entities includes the following information:
• Model Attributes Mapping on page 1839
• WTPartUsageLink and Occurrence on page 1845
• EPMMemberLink on page 1848
• WTPartDescribeLink on page 1850
• WTPartReferenceLink on page 1851
• WTDocument on page 1853
• WTPart on page 1854
• EPMDocument on page 1855
• Content Item on page 1856

1838 Customization Guide


Model Attributes Mapping
The model attributes section contains the following information:
• LocalId and Ufid Generation for Associations on page 1840
• WTPartUsageLink and Occurrence on page 1845
• EPMMemberLink on page 1848
• WTPartDescribeLink on page 1850
• WTPartReferenceLink on page 1851
• WTDocument on page 1853
• WTPart on page 1854
• EPMDocument on page 1855
• Content Item on page 1856

Data Exchange using Standards in Windchill 1839


LocalId and Ufid Generation for Associations

Mapping Table
As in the incoming data from non-WC system (w.r.t above snippet), there is no
means by which localId/ufid can be extracted. So the general strategy for
generation localId and ufid for associations would be as described in the
table below.

1840 Customization Guide


AP242 Windchill Notes
localId ( VersionToMaster 1. <linkType> would
association) be a string value
<linkType>- based on the type of
<parentPartNum association.
ber>-
<parentPartName>- For
<ParentPartVer PartUsageLink:
sion>- linkType :
<childPartNum STRING :=
ber>- 'wt.part.WTPar
<childPartName> tUsageLink'
e.g. For
'wt.part.WTPartUsa PartDescribe
geLink- Link : linkType :
OCR0847312-VIS RLX STRING := '
M50,80-12 AUTOTAR
wt.part.WTPart
SA1ND-001-
7703026050–A-VIS DescribeLink'
RLX M50,80-12 2. However
AUTOTAR SA1ND' <childPartVer
OR sion> would only be
applicable in case
( VersionToVersion WTPartDescribe
association)
Link.
<linkType>-
<parentPartNum
ber>-
<parentPartName>-
<ParentPartVer
sion>-
<childPartNum
ber>-
<childPartName>
-<childPartVer
sion>
e.g.
‘wt.part.WTPartDe
scribeLink-
OCR0847312-VIS RLX
M50,80-12 AUTOTAR
SA1ND-001-

Data Exchange using Standards in Windchill 1841


AP242 Windchill Notes
7703026050–A-VIS
RLX M50,80-12
AUTOTAR SA1ND-002'
OR
( WTPart,
WTDocument,
EPMDocument)
<Type>-<number>-
<name>-<version>
e.g.
‘wt.part.WTPart-
0000000125-
piston-A.1’
ufid ( VersionToMaster
association)
<linkType>-
<parentPartNum
ber>-
<parentPartName>-
<ParentPartVer
sion>-
<childPartNum
ber>-
<childPartNa
me>|<Originating
System or
lastKnownReposi
tory>|<Origina
tingSystem or
lastKnownReposito
ry>
OR
( VersionToVersion
association)
<linkType>-
<parentPartNum
ber>-
<parentPartName>-
<ParentPartVer
sion>-
<childPartNum

1842 Customization Guide


AP242 Windchill Notes
ber>-
<childPartName>-
<childPartVersio
n>|<Originating
System or
lastKnownReposi
tory>|<Origina
tingSystem or
lastKnownReposito
ry>
OR
( WTPart,
WTDocument,
EPMDocument)
<Type>-<number>-
<name>-
<version>|<SYS
TEM_GUI>|<SYSTEM_
DOMAIN> e.g.
‘wt.part.WTPart-
0000000125-
piston-A.1|
ptc.com|ptc.com’
masterUfid ( WTPart,
WTDocument,
EPMDocument)
<Type>-<number>-
<name>|<SYSTEM_
GUI>|<SYSTEM_
DOMAIN> e.g.
‘wt.part.WTPartMas
ter-0000000125-
piston|
ptc.com|ptc.com’
externalTypeId Windchill Objects
(WTDocument, WTPart
and EPMDocument)
externalTypeId is
formed by concatenating
with the partTypes/
documentTypes

Data Exchange using Standards in Windchill 1843


AP242 Windchill Notes
attribute from the Part/
Document entity
respectively if present.
For example :
WCTYPE|wt.doc.WT
Document|3DR

Part 21 Representation
#3321= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_OCR'),PROXYSTRING('FROZEN'));
#3326= PARTVIEW($,$,$,$,$,#3321,$);
#3361= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#3326));
#3404= PART(IDENTIFIERSTRING('OCR0847312'),TRANSLATEDSTRINGSET((#3406,#3408))
,$,$,(#3325,#280),$,(#3361));
#3408= LOCALIZEDSTRING($,'VIS RLX M50,80-12 AUTOTAR SA1ND');
#3414= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_IND'),PROXYSTRING('FROZEN'));
#3421= PARTVIEW($,$,$,$,$,#3414,$);
#3456= PARTVERSION(IDENTIFIERSTRING('002'),CHARACTERSTRING(''),$,$,(#3421));
#3499= PART(IDENTIFIERSTRING('7703026050--A'),TRANSLATEDSTRINGSET
((#3501,#3503))
,$,$,(#3420,#280),$,(#3456));
#3503= LOCALIZEDSTRING($,'VIS RLX M50,80-12 AUTOTAR SA1ND');

1844 Customization Guide


WTPartUsageLink and Occurrence

Mapping Table
AP242 Windchill Notes
NextAssemblyOccur e_ Only one instance per a
renceUsage(…); WTPartUsage distinct pair of parent/
Link(…); child (relating/related) is
ViewOccurenceRela e_ created.
tionship(…); WTPartUsage
Link(…);
For more information see e_
LocalId and Ufid WTPartUsageLin
Generation for k.ObjectID.local
Associations on page Id, e_
1840. WTPartUsageLin
k.ObjectID.ufid
'WCTYPE|wt. e_
part.WTPartUsage WTPartUsageLin
Link' k.externalTypeId
NextAssemblyOccur e_
renceUsage.relat WTPartUsageLink.
ed = quantityUnit
SingleOccur (If it is
rence(…); SingleOccurence,
or quantity is 1 and unit is
“ea”)
ViewOccurrenceRe
lationship.relat (If
ed= QuantifieidOccur
QuantifiedOccur ence, quantity and unit
rence(…); is picked up from that
entity)
QuantifiedOccur
rence.quantity =
NumericalVal
ue(…);
NumericalValue.u
nit =Unit(…);
Unit.name
NextAssemblyOccur e_
renceUsage.relat WTPartUsageLin
ed = k.uses
SingleOccur
rence(…);

Data Exchange using Standards in Windchill 1845


AP242 Windchill Notes
SingleOccurrence.
definition =
PARTVIEW(…);
One can navigate from a
PartView (WTPart) to
the Part (WTPartMaster)
using the INVERSE
attributes on the
PartView and
PartVersion entities.
NextAssemblyOccur e_
renceUsage.relat WTPartUsageLink.u
ing = PARTVIEW(…); sedBy
One can navigate from a
PartView (WTPart) to
the PartVersion
(WTPartVersion) using
the INVERSE attributes
on the PartView entity.
NextAssemblyOccur e_occurence and
renceUsage.relat added to the e_
ed = WTPartUsageLin
SingleOccur k.occurrences list
rence(…);
SingleOccurren e_occurence.name
ce.id
NextAssemblyOccur e_
renceUsage.place occurence.trans
ment = formString
CARTESIANTRANSFOR For more information on
MATION(…); how the placement
information correlates to
transformString see
WTPartUsageLink and
Occurrence on page 1823.

Part 21 Representation
#384= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CMP'),PROXYSTRING('FROZEN'));
#386= PARTVIEW($,$,$,$,$,#384,$);
#869= NEXTASSEMBLYOCCURRENCEUSAGE(IDENTIFIERSTRING('2407966'),
CHARACTERSTRING(''),$,*,#386,#892,#893);
#892= SINGLEOCCURRENCE(IDENTIFIERSTRING('1'),$,$,$,#5306);

1846 Customization Guide


#893= CARTESIANTRANSFORMATION($,$,((1.,0.,0.),(0.,1.,0.),(0.,0.,1.)),$,
(0.,0.,0.));
#3268= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#386));
#3311= PART(IDENTIFIERSTRING('CMP0847328'),TRANSLATEDSTRINGSET((#3313,#3315)
),$,$,(#385,#280),$,(#3268));
#5305= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_OCR'),PROXYSTRING('FROZEN'));
#5306= PARTVIEW($,$,$,$,$,#5305,$);
#5341= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#5306));
#5384= PART(IDENTIFIERSTRING('OCR0847327'),TRANSLATEDSTRINGSET((#5386,#5388))
,$,$,(#3325,#280),$,(#5341));
#5415= VIEWCONTEXT(CHARACTERSTRING('part definition'),PROXYSTRING
('mechanical design'),PROXYSTRING('design'));
#5480= ASSEMBLYDEFINITION($,$,$,$,$,#5415,$,CLASSSTRING('design assembly'));
#181= VIEWOCCURRENCERELATIONSHIP($,$,$,$,#5480,#55180);
#55180= QUANTIFIEDOCCURRENCE(IDENTIFIERSTRING('/NULL'),$,$,$,#55129,#55171);
#55171= NUMERICALVALUE($,$,PROPERTYDEFINITIONSTRING('quantity'),$,$,$,
#55172,1.,$);
#55172= UNIT(CLASSSTRING('kg'),$,$,$);
#55129= PARTVIEW($,$,$,$,$,#5415,$);

Data Exchange using Standards in Windchill 1847


EPMMemberLink

Mapping Table
AP242 Windchill
NextAssemblyOccurrenceUs e_EPMMemberLink(…);
age(…);
ViewOccurenceRelation e_WTPartUsageLink(…);
ship(…);
For more information see LocalId and e_
Ufid Generation for Associations on EPMMemberLink.ObjectID.lo
page 1840. calId, e_
EPMMemberLink.ObjectID.u
fid
'WCTYPE|wt.epm.structur e_
e.EPMMemberLink' EPMMemberLink.externalTy
peId
NextAssemblyOccurrenceUsa e_
ge.related = EPMMemberLink.quantityUnit
SingleOccurrence (…); (If it is SingleOccurence, quantity
or is 1 and unit is “ea”)
ViewoccurrenceRelationshi (If QuantifieidOccurence,
p.related= quantity and unit is picked up from that
QuantifiedOccurrence(…); entity)
QuantifiedOccurrence.quan
tity = NumericalValue(…);
NumericalValue.unit
=Unit(…);
Unit.name

1848 Customization Guide


AP242 Windchill
NextAssemblyOccurrenceUsa e_EPMMemberLink.usedBy
ge.relating = PARTVIEW(…);
One can navigate from a PartView
(EPMDocument) to the
PartVersion
(EPMDocumentVersion) using the
INVERSE attributes on the PartView
entity.
NextAssemblyOccurrenceUsa e_EPMMemberLink.uses
ge.related =
SingleOccurrence(…);
SingleOccurrence.defini
tion = PARTVIEW(…);
One can navigate from a PartView
(EPMDocument) to the Part
(EPMDocumentMaster) using the
INVERSE attributes on the PartView
and PartVersion entities.

Part 21 Representation
#384= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CMP'),PROXYSTRING('FROZEN'));
#386= PARTVIEW($,$,$,$,$,#384,$);
#869= NEXTASSEMBLYOCCURRENCEUSAGE(IDENTIFIERSTRING('2407966'),CHARACTERSTRING
(''),$,*,#386,#892,#893);
#892= SINGLEOCCURRENCE(IDENTIFIERSTRING('1'),$,$,$,#5306);
#893= CARTESIANTRANSFORMATION($,$,((1.,0.,0.),(0.,1.,0.),(0.,0.,1.)),$,
(0.,0.,0.));
#3268= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#386));
#3311= PART(IDENTIFIERSTRING('CMP0847328'),TRANSLATEDSTRINGSET((#3313,#3315)
),$,$,(#385,#280),$,(#3268));
#5305= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_OCR'),PROXYSTRING('FROZEN'));
#5306= PARTVIEW($,$,$,$,$,#5305,$);
#5341= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#5306));
#5384= PART(IDENTIFIERSTRING('OCR0847327'),TRANSLATEDSTRINGSET((#5386,#5388))
,$,$,(#3325,#280),$,(#5341));

Data Exchange using Standards in Windchill 1849


WTPartDescribeLink

Mapping Table
AP242 Windchill
DocumentAssignment (…); e_WTPartDescribeLink (…);
When the DocumentAssignment.
role is present in the
describeLinkRolesList from
Generic.inn.
For example – For Windchill to
Windchill export/import default role is
‘description’.
For more information see LocalId and e_
Ufid Generation for Associations on WTPartDescribeLink.ObjectI
page 1840. D.localId, e_
WTPartDescribeLink.ObjectI
D.ufid
'WCTYPE|wt.part.WTPartDe e_
scribeLink' WTPartDescribeLink.exter
nalTypeId
DocumentAssignment.as e_
signedDocument = DOCUMENT WTPartDescribeLink.descri
(…); bedBy
One can navigate from a Document to
the DocumentVersion using the
INVERSE attributes on the Document
entity.
DocumentAssignment.as e_
signedTo = PartView(…); WTPartDescribeLink.de
scribes
One can navigate from a PartView to
the Part using the INVERSE
attributes on the PartView and
PartVersion entities.

Part 21 Representation
#31696= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CST'),PROXYSTRING('FROZEN'));
#31697= PARTVIEW($,$,$,$,#31765,#31696,$);
#31700= DOCUMENTASSIGNMENT(IDENTIFIERSTRING('G000812460_001'),
CHARACTERSTRING(''),$,CLASSSTRING('describeLinkRole'),#31710,(#31697),$);
#31710= DOCUMENT(IDENTIFIERSTRING('G000812460'),CHARACTERSTRING('G000286254')
,CHARACTERSTRING('RENFORT_TABLETTE_LAT_AR_D'),$,(#3675),$,(#31788));
#31714= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#31697));
#31788= DOCUMENTVERSION(IDENTIFIERSTRING('001'),$,$,$,(#31785));

1850 Customization Guide


WTPartReferenceLink

Mapping Table
AP242 Windchill
DocumentAssignment (…); e_WTPartReferenceLink (…);
When the
DocumentAssignment.role is
present in the
referenceLinkRolesList from
Generic.inn.
For example – For Windchillto
Windchill export/import default role is
‘description’.
For more information see LocalId and e_
Ufid Generation for Associations on WTPartReferenceLink.Objec
page 1840. tID.localId, e_
WTPartReferenceLink.Objec
tID.ufid
'WCTYPE|wt.part.WTPartRe e_
ferenceLink' WTPartReferenceLink.exter
nalTypeId
DocumentAssignment.as e_
signedDocument = DOCUMENT WTPartReferenceLink.refer
(…); ences
One can navigate from a Document to
the DocumentVersion using the
INVERSE attributes on the Document
entity.
DocumentAssignment.as e_
signedTo = PartView(…); WTPartReferenceLink.refer
encedBy
One can navigate from a PartView to
the Part using the INVERSE
attributes on the PartView and
PartVersion entities.

Part 21 Representation
#31696= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CST'),PROXYSTRING('FROZEN'));
#31697= PARTVIEW($,$,$,$,#31765,#31696,$);
#31700= DOCUMENTASSIGNMENT(IDENTIFIERSTRING('G000812460_001'),
CHARACTERSTRING(''),$,CLASSSTRING('referenceLinkRole'),#31710,(#31697),$);
#31710= DOCUMENT(IDENTIFIERSTRING('G000812460'),CHARACTERSTRING('G000286254')
,CHARACTERSTRING('RENFORT_TABLETTE_LAT_AR_D'),$,(#3675),$,(#31788));
#31714= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#31697));

Data Exchange using Standards in Windchill 1851


#31788= DOCUMENTVERSION(IDENTIFIERSTRING('001'),$,$,$,(#31785));

1852 Customization Guide


WTDocument

Mapping Table
AP242 Windchill
DocumentDefinition (…); OR e_WTDocument (…);
DigitalDocumentDefinition
(…);
It is processed when the
Document.documentTypes is
present in the
wcDocumentTypesList or
nonWCDoumentTypesList from
Generic.inn.
For more information see LocalId and e_
Ufid Generation for Associations on WTDocument.ObjectID.local
page 1840. Id, e_
WTDocument.ObjectID.ufid
For more information see e_
ExternalTypeId in LocalId and Ufid WTDocument.externalTypeId
Generation for Associations on page
1840.

Part 21 Representation
#29866= DIGITALDOCUMENTDEFINITION(IDENTIFIERSTRING('2'),$,$,$,
#29883,$,$,$,$,(#217));
#29869= DOCUMENTVERSION(IDENTIFIERSTRING('002'),$,$,$,(#29866));
#29791= DOCUMENT(IDENTIFIERSTRING('G000538031'),CHARACTERSTRING
('G000286254'),CHARACTERSTRING('PLAQUE RENFORT FIX DOSSIER AR D'),$,
(#3675),$,(#29869));
#3675= CLASS(IDENTIFIERSTRING('3DR'),$,$,$);

Data Exchange using Standards in Windchill 1853


WTPart

Mapping Table
AP242 Windchill
PartView (…); OR e_WTPart (…);
AssemblyDefinition (…);
It is processed when the
PartView.initialContext is
present in the
wtPartViewContextsList from
Generic.inn.
For more information see LocalId and e_WTPart.ObjectID.localId,
Ufid Generation for Associations on e_WTPart.ObjectID.ufid
page 1840.
For more information see e_WTPart.externalTypeId
ExternalTypeId in LocalId and Ufid
Generation for Associations on page
1840.

Part 21 Representation
#3600= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CST'),PROXYSTRING('FROZEN'));
#3603= PARTVIEW($,$,$,$,#3671,#3600,$);
#3620= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,(#3603));
#3663= PART(IDENTIFIERSTRING('G000277428'),TRANSLATEDSTRINGSET
((#3665,#3667)),$,$,(#3602,#280),$,(#3620));
#3602= CLASS(IDENTIFIERSTRING('CST'),$,$,$);
#280= CLASS(IDENTIFIERSTRING('piece part'),$,$,$);

1854 Customization Guide


EPMDocument

Mapping Table
AP242 Windchill
PartView (…); OR e_EPMDocument (…);
AssemblyDefinition (…);
It is processed when the
PartView.initialContext is
present in the
epmDocumentViewContexts
List from Generic.inn.
For more information see LocalId and e_
Ufid Generation for Associations on EPMDocument.ObjectID.local
page 1840. Id, e_
EPMDocument.ObjectID.ufid
For more information see e_
ExternalTypeId in LocalId and Ufid EPMDocument.externalTypeId
Generation for Associations on page
1840.

Part 21 Representation
#3600= VIEWCONTEXT($,PROXYSTRING('VPLM_RN_PDT_CST'),PROXYSTRING('FROZEN'));
#3603= PARTVIEW($,$,$,$,#3671,#3600,$);
#3620= PARTVERSION(IDENTIFIERSTRING('001'),CHARACTERSTRING(''),$,$,
(#3603));
#3663= PART(IDENTIFIERSTRING('G000277428'),TRANSLATEDSTRINGSET
((#3665,#3667)),$,$,(#3602,#280),$,(#3620));
#3602= CLASS(IDENTIFIERSTRING('CST'),$,$,$);
#280= CLASS(IDENTIFIERSTRING('piece part'),$,$,$);

Data Exchange using Standards in Windchill 1855


Content Item

Mapping Table
AP242 Windchill
DigitalDocumentDefinition. e_contentItem.role
viewOf.versionOf.document
Types[]
If content role cannot be found using
value above, then try using-
DigitalDocumentDefinition.
documentFormat
If content role cannot be found using
value above, then try using-
DigitalDocumentDefinition.
files[].Format.dataFormat
If content role cannot be found using
value above, then try using-
DigitalDocumentDefinition.
files[].locations[].id
Values found in the above entities are
matched against the values found in the
contentRoleToDocumentType
String,
contentRoleToDataFormat
String and
contentRoleToFileExtension
String variables in “Generic.inn” to
find a content role.

1856 Customization Guide


Implementing Templates

Template Support
There is a one-to-one correspondence between the template definitions in OASIS
DEXlib and the entity definitions in the AP239E2_ARM_ASD_DEX_1_3_
EXTENSION_lf.exp long form schema. This means that there is one entity
definition corresponding to each template definition.
The template extension entities in the long form schema have only forward
references to other extension entities and/or to pure PLCS entities. They are
layered on top of the PLCS entities. This means that all template extension
instances in a population can be stripped off (without hampering the pure PLCS
instances) before exporting the population to a pure PLCS P21 file.

Implementation Examples
Implementation of the representing_part template is used as an example.
The intention is that you can develop or understand the template functions, if you
follow this example as a guideline.

Template Layers
Templates are layered on top of each other with the pure PLCS entities at the
bottom. The template functions are layered in exactly the same way. The sketch
underneath depicts the layers of the representing_part template definition.

Data Exchange using Standards in Windchill 1857


The following three Express-G diagrams depict the representing_part
template down to the lowest level of detail.

representing_part – Diagram 1

1858 Customization Guide


representing_part – Diagram 2

Data Exchange using Standards in Windchill 1859


representing_part – Diagram 3

1860 Customization Guide


Function Categories
For each template there are two mandatory functions, a Get get_
representing_part) function and a Create function (create_
representing_part). The Copy and Delete functions are implemented on
demand if needed.

Initialization

Target Models
For target data models, which are implicitly opened for write, a simple call to
initTemplateAPI is used for initialization. If the ‘with_rdl’ parameter is
set to ‘FALSE’ no RDL is needed. This means that the converter is on its own
with respect to correctness of the classifications it uses. If the ‘with_rdl’
parameter is set to ‘TRUE’, the templateAPI looks for an RDL with the name
<target_model_name>_RDL or an RDL named plcsrdl as the default.

Source Models
Source models are implicitly opened for read. The initTemplateAPI function
will generate template extension instances if that has been done already.
Therefore, when the source model is a PLCS population, it must temporarily be
opened for write during the initialization stage. Afterwards the model should be
reopened for read only again, in order to prevent accidental (faulty) updates of the
source model.
xpxChangeOpenMode(XPXSOURCEMODELID,xpxRW);

PLCSMODELID := XPXSOURCEMODELID;

initTemplateAPI(TRUE);

xpxChangeOpenMode(XPXSOURCEMODELID,xpxRO);
PLCSMODELID is the identifier of the model addressed by the templateAPI.
By default PLCSMODELID is set to XPXTARGETMODELID. In case the source
model is a PLCS population, the PLCSMODELID must be switched to
XPXSOURCEMODELID during initialization. XPXSOURCEMODELID and
XPXTARGETMODELID are EDMxpx built in variables.

Init Function
The init function does not only initialize the templateAPI itself, but also the
model (PLCS population) on which the API operates. The representing_
part instances are initialized with the following call:
somestuff := get_representing_part(?,?,?,?,?,?,?,?,?);

init_rep_part := TRUE;

Data Exchange using Standards in Windchill 1861


This call will return an aggregate of all representing_part instances. The
representing_part instances will be generated, if that has not been done
before. Instances of other template extension entity types are initialized in a
similar way. Since many templates are layered on top of other ones, some get_
xxxxx functions may call other ‘get functions’. Due to these dependencies the
order of the initialization calls is significant. For the same reason some of the
templates have their own private initialization flag in addition to the global one
(initialized).

Get Functions
The following applies to Get functions:
• An invocation of a Get function can result in no, one, or several hits.
• When all arguments are supplied, none or one single hit is possible.
• When all arguments are indeterminate (the value is ? which is similar to null in
Java) all instances of that template type are returned (can be none).
• When some of the arguments are supplied a Get function behaves as a search.
In this case a function invocation returns an aggregate of those instances that
match the input parameters (can also be none).

Section 1
If template extension instances have been initialized before (private or global flag
is checked), the search section is entered. There is not any one recommended
method/way to implement the search. The implementation all depends on the
structure of the template.

Section 2
Section 2 is entered if template extension instances have not been initialized so
far. If you look at get_representing_part, Section 2 starts with:
xpxGetEntityExtentBN (PLCSMODELID,'Part_view_definition',prod_def_bag);

REPEAT i := 1 TO SIZEOF(prod_def_bag);

.......

For example a loop over all instances of 'Part_view_definition' in the


population. This is the “root” in the template, and there shall be one
representing_part instance for each 'Part_view_definition'
instance. Other template types have similar one-to-one correspondences between
the “root” and the extension entity.
'Part_view_definition' instances that are not properly instantiated are
silently skipped. If the population has been validated correctly beforehand such an
event should never occur. An exception should have been thrown, or at least the
instance should have been logged as a faulty one.

1862 Customization Guide


Population of the representing_part attributes
• part_id
A part may have many alias identifications (like Part_name) in addition to
the principal Part_identification_code, but in this context the list
returned from get_assigning_identification is iterated over in
order to find an identification that is classified as Part_
identification_code or a possible subtype.
• part_ver
A Part_version can have no more than one identification (one version id).
Therefore the utility helper_get_one_assigning_
identification is used to get this single version if any.
• domain
The classifications attached to Part_view_definition.initial_
context (View_definition_context) are obtained using the get_
assigning_reference_data function. The one that is Discipline_
domain (or subtype of it) are assigned to domain.
• life_cycle_stage
The classifications attached to Part_view_definition.initial_
context (View_definition_context) are obtained using the get_
assigning_reference_data function. The one that is Life_cycle_
stage (or subtype of it) are assigned to life_cycle_stage.
• prt
The same as Part_view_definition.defined_version.of_
product.
• version
The same as Part_view_definition.defined_version.
• view
is the Part_view_definition instance itself
• contxt
The same as Part_view_definition.initial_context.
• catgy
xpxGetEntityExtentBN is used to find the one single product category
in the population.

Data Exchange using Standards in Windchill 1863


Create Functions
The main behavior of Create functions is simple in the sense that the client
application (converter) always calls the Create function without the need to check
beforehand whether an instance matching the input parameter already exists or
not. The Create function does that for you by calling the corresponding Get
function. So the Create function either creates and returns a new instance or
returns the instance identifier of an already existing one.
A create function has two main sections.

Section 1
Apart from checking the input parameters, the first section of a Create function
simply consist of a call to the corresponding Get function. If an instance that
matches the actual parameters given exists, the function returns with the instance
identifier of the instance. Otherwise section-2 of the function is entered.

Section 2
In section two the main template instance (REPRESENTING_PART) is created.
Actually that is what takes place at the end of the function. As depicted in the
template layers diagram, template entities are layered on top of pure PLCS entities
and normally on top of other template entities as well. Not all instances belonging
to a template instance structure are created. To reduce the volume/size of the
population as much as possible, redundancy is avoided by reusing already existing
instances whenever possible. Using the create_representing_part as example the
steps in section-2 are described.
• Product_category / Product_category_assignment
There should be only one single Product_category (name = part) in a
population. It is reused and linked to all Parts through the Product_category_
assignment.products aggregate. The xpxGetEntityExtentBN returns all
instances of a given type. Normally there is a performance penalty when
iterating through the aggregate of instances returned. In this case, however,
this function can safely be used, since there is maximum one single instance of
Product_category_assignment in the whole population.
• Part
The get_assigning_identification function is used to find out if a Part with the
given identification already exists. If that is the case, that Part is reused.
Otherwise a new Part is created, and its identification is attached using the
create_assigning_identification function.
• Part_version
A list of all Part_versions for the Part is obtained. (this list is of course empty
if the Part was newly created) . For each Part_version in the list the get_
assigning_identification function is used to find out whether one of them has

1864 Customization Guide


an identification that matches the given input. If that is the case that Part_
version is reused. Otherwise a new Part_version is created and connected to
the Part. Its identification is attached, as well, using the create_assigning_
identification function.
• View_definiton_context
There are a very limited number if View_definiton_context instances in the
population. Therefore the aggregate returned by xpxGetEntityExtentBN can
safely be iterated over without any performance penalty. A View_definiton_
context is identified by means of two classifications (life_cycle_stage and
domain). If a View_definiton_context instance with both classifications
already exists, it is reused. Otherwise a new View_definiton_context instance
is created, and the create_assigning_reference_data function is used to attach
the two classifications.
• Part_view_definition
A new Part_view_definition is always is always created (as a consequence of
that a new representing_part instance is created. The Part_version and the
View_definiton_context are attached.
• representing_part
Finally the extension instance representing_part is created. Forward
references to subordinate levels are put in place. These forward references
make life easier for a programmer. One can for instance obtain the
identification of a Part directly. In PLCS many relations are “incoming” ones
(e.g. Identification_assignment, Classification_
assignment, Assigned_property). Therefore the Express function
Usedin has to be used in order find the identification(s) connected to a
specific Part. Therefore the forward references from representing_part
and other extension entities are convenient.
Population of the representing_part attributes :
• part_id
The reused/created assigning_identification instance.
• part_ver
The reused/created assigning_identification instance.
• domain
The reused/created assigning_reference_data instance.
• life_cycle_stage
The reused/created assigning_reference_data instance.
• prt

Data Exchange using Standards in Windchill 1865


The reused/created Part (xpxCreateInstanceBN).
• version
The reused/created Part_version (xpxCreateInstanceBN).
• view
Part_view_definition instance is always created
(xpxCreateInstanceBN).
• contxt
The reused/created View_definition_context.
• catgy
The reused/created Product_category.

Copy Functions
Copy functions are not relevant when converting back and forth between legacy
data or proprietary format such as the Windchill Express schema. The Copy
functions are applicable when a DEX source population is merged into a target
DEX population. A prerequisite is that the source and target schema are the very
same one.
Copy functions consist of two rather simple steps. Copy functions take a source
(representing_part) instance as input. The input parameters required for
the create (create_representing_part) function are extracted from the
source instance. Then the create (create_representing_part) function is
invoked. The create function will either return an already existing instance or
create a new one. So applying the copy functions to all instances in a source
population, the resulting target population will become a union (or merge) of the
source population and the original target population.

Delete Functions
Delete functions are normally not relevant when converting back and forth
between legacy data or proprietary format such as the Windchill Express schema.
Such functions are applicable when a DEX database is maintained over time. For
instance in connections with applications like TruePLM.

1866 Customization Guide


PLCS Data Exchange

PLCS Terminology
DEX / Data Exchange Specification
A Data Exchange Specification (DEX) is a subset of the ISO 10303-239 PLCS
information model. A DEX is designed to support data exchange for specific
activities, provide guidance and rules for how to use and combine the selected
entities and external Reference Data in data exchanges. Each DEX includes a
complete EXPRESS schema. This is a subset of the ISO 10303-239 schema with a
derived XML Schema. Both can be used to define and validate a data exchange
file. A DEX that is defined and managed by the OASIS PLCS TC is referred to as
a "PLCS DEX", as opposed to a "Business DEX."

Reference Data
Reference Data is data that represents information about classes or individuals
which are common to many users. Reference Data provides a tailorable structured
vocabulary that extends the PLCS information model with business-specific
semantics.

Capability
A Capability is a description of how EXPRESS entities are used to represent a
given concept (a specific "functionality" or "capability"). It provides guidance and
rules on what Entities are used to represent a given concept, how the entities are
related, and what Reference Data are used, as well as general guidance. A set of
Templates are documented within a Capability to provide precise specifications of
which Entities are instantiated to represent identified concepts.

Template
A Template is a precise specification of which entities and attributes in the ISO
10303-239 PLCS are instantiated. It also specifies which Reference Data should
be used to represent a concept providing documented functionality in a Capability.
A Template defined and managed by the OASIS PLCS TC is referred to as a
"PLCS Template", as opposed to a "Business Template."
Templates describe and specify how common business concepts are represented
using the PLCS information model. Templates have been defined at a fine grained
level to encourage maximum reuse across different DEXs, hence ensuring
consistent usage of the PLCS information model. For example, the Template
representing_organization is used to represent an organization, and can
be reused whenever this is required.

Data Exchange using Standards in Windchill 1867


PLCS / AP239 Mapping Implementation
ISO 10303-239 Product Life Cycle Support (PLCS) specifies an information
model that defines what information can be represented and exchanged to support
a product through its life cycle. The information model is specified using the
EXPRESS information modeling language. Because the information model
defined by PLCS is a generic model supporting the whole life cycle of a product,
its scope is wider than most applications, business processes, or single data
exchanges. Consequently Data Exchange Specifications (DEXs) are developed by
the OASIS Product Life Cycle Support (PLCS) Technical Committee members to
support the usage of subsets of the model.
PLCS uses the standard DEX templates defined in Release 5.

Reference Data
Reference data must be defined for every property associated with a Windchill
object.
There are some standard annotation-based properties which must be added to
newly added reference data and libraries. For details on the various annotation
properties, please refer “Guidance for PLCS RDL Developers” section in the
PLCS Guide for Reference Data Developer guide.
Reference data us managed in Windchill solution using the ISO_12006_
3VERSION_14 schema.

Note
The PLCS Guide for Reference Date Developer guide can be downloaded
from the OASIS Product Life Cycle Support (PLCS) Technical Committee
website from this external link: PLCS Guide for Reference Date Developer

AP239 / PLCS Configuration


This section describes how to configure AP239/PLCS based data exchange in
Windchill.
1. Load Windchill Express schema.
2. PLCS schema-specific files can be found from the <Windchill>/
codebase/registry/stepdex/ap239 folder. This is the <PLCS_
HOME> folder.
3. Load the PLCS schema AP239E2_ARM_ASD_DEX_1_3_EXTENSION_
lf.exp schema from the <PLCS_HOME>/schema directory. While loading
the schema ensure that you have selected the “edm express extension”
option.

1868 Customization Guide


4. Load the RDL schema, ISO_12006_3_VERSION_14.exp from the
<PLCS_HOME>/rdl directory.
5. Load the following query schemas located in the <PLCS_HOME>/rdl/qex
directory.
a. ifd_adapter.qex
b. ifd_wsdl_express_plcs.qex
c. define_hash_tables.qex
6. Create permanent hash tables by executing a query.
a. Navigate to Data ▶ Query ▶ Execute Query section in the EDMSuperviser.
b. Specify SystemRepository, DummyModel, define_hash_
table, define_hash_tables as entries specific to the Repository,
Model, Query Schema, and Query fields.
c. Select Ok.
7. Import the plcsrdl model from the plcsrdl.stp file located in the
<PLCS_HOME>/rdl directory
8. Load import/export specific xpx files located in import/export specific folders
in the <PLCS_HOME> location.

Note
These manual steps have been incorporated into ant scripts. They can found at:
• <WT_HOME>/bin/configureAP239.xml
• <WT_HOME>/bin/configureSTEP.xml

Handling Reference Data


The new PLCS RDL Editor should be used to add or update RDL. Refer to
“Reference Manual” for usage of the RDL Editor. The Reference manual can be
accessed either through Short cut or through the Help menu in the RDl Editor.

Data Exchange using Standards in Windchill 1869


To add an RDL entry:
1. Load plcsrdlptc.stp present in <Windchill>\codebase\
registry\stepdex\ap239\rdl using the P21 file import model from
Models menu.
2. Select the relevant super type and add a “New child”. Add as many RDL
entries as required.
3. Export the model to plcsrdlptc.stp file.

Note
Model can be loaded using OWLs as well.

Adding Attributes in PLCS

IBAs in PLCS format


IBAs in PLCS standard are represented by reference data. Every attribute on the
business object is represented as reference data.
• A IBA should be added first as reference data in PLCSRDL model. For more
information see Handling Reference Data on page 1869 for information on
how to add attribute to reference data.
• Add an entry in attribute_to_rdl.properties for each attribute.
The attribute_to_rdl.properties file is located in the <WT_
HOME>/codebase/registry/stepdex/ap239/common/
includes directory.
○ The attribute_to_rdl.properties is the file that relates
attribute path to RDL entry (for example WTPart/name=
urn:plcs:rdl:std:Part_name).
• If the attribute is soft attribute, the softtype should be included in
stepdex.properties. For more information see the “Supported Types”
section in Business Field Mapping on page 1704.

Reference Data Library Entities


This section contains tables which depict how various Windchill object-specific
attributes are represented in a Reference Data Library (RDL). The following
namespace conventions are used for representing PLCS and PTC reference data
representation:
• PTC stands for urn:plcs:rdl:ptc
• PLCS stands for urn:plcs:std:rdl

1870 Customization Guide


Reference Data Entry
This section represents how certain common attributes present in various
Windchill Objects such as WTPart or WTDocument are represented in an RDL.
Attribute RD Entry Parent RD
number PLCS:Part_ PLCS:identification_code
identification_code
Ufid PTC:ufid PTC:wtobject_
identification_code
masterufid PTC:masterufid PTC:wtobject_
identification_code
lifeCycleState PTC:lifeCycleState PTC:assigned_
lifecycleInfo_property
lifeCycleName PTC:lifeCycleName PTC:assigned_
lifecycleInfo_property
folderPath PTC:folderPath PLCS:Assigned_property
externalTypeId PTC:externalTypeId PLCS:Assigned_property
versionLevel PTC:versionLevel PLCS:Assigned_property

Reference Data Entries for WTPart


This section represents the snippet reference data hierarchy for WTPart specific
attributes.
Attribute RD Entry Parent RD
partType PTC:partType PTC:assigned_wtpart_
property
defaultUnit PTC:defaultUnit PTC:assigned_wtpart_
property
endItem PTC:endItem PTC:assigned_wtpart_
property
defaultTraceCode PTC:defaultTraceCode PTC:assigned_wtpart_
property
domainName PTC:domainName PLCS:Assigned_property
genericType PTC:genericType PLCS:Assigned_property
partSource PTC:partSource PLCS:Assigned_property
partType PTC:partType PLCS:Assigned_property
view PTC:view PLCS:Assigned_property

Data Exchange using Standards in Windchill 1871


Reference Data Entries for WTDocument
This section represents the snippet reference data hierarchy for WTDocument
specific attributes.
Attribute RD Entry Parent RD
department PTC:department PLCS:Assigned_property
domainName PTC:domainName PLCS:Assigned_property
docTitle PTC:docTitle PLCS:Assigned_
document_property
docType PTC:docType PLCS:Assigned_
document_property
description PLCS:Description PLCS:Descriptor_
assignment

Reference Data Entries for BusinessField Attributes


In PLCS, attribute name and unit values are usually referred with a specific
Reference Data (RD) entry. Since users define attributes on production system, it
is suggested that you create your own RD-specific entry. For unit values, base
unit-specific RD entries are already incorporated in the data exchange standards.
The following table depicts the common base unit’s specific RDL entries already
incorporated into standard PLCS Import export-specific operation.
Unit Name RD Entry Parent RD
M PLCS: m_Length_unit Context_dependent_unit
and Length_unit
G PLCS : g_Mass_unit Context_dependent_unit
and Mass_unit
S PLCS:Time_unit Time_unit
A PLCS:A_ Electric_ Context_depdendent_unit
current_unit and Electric_current_unit
K PLCS: K_ Context_dependent_unit
Thermodynamic_ and Thermodynamic_
temperature_unit temperature_unit
Mol PLCS: mol_Amount_of_ Context_dependent_unit
substance_unit and : Amount_of_
substance_unit
Cd PLCS: cd_Luminous_ Context_dependent_unit
intensity_unit and : Luminous_
intensity_unit
R PLCS: r_Plane_angle_ Context_dependent_unit
unit

1872 Customization Guide


Unit Name RD Entry Parent RD
and : Plane_angle_unit
Sr PLCS: sr_Solid_angle_ Context_dependent_unit
unit and : Solid_angle_unit
Base units other than PLCS: Context_
above 9 standard units. dependent_unit
Units with Multiplication PLCS:Derived_unit
or exponent or division

Note
Base units are simple units without having any multiplication, exponent or
division symbols whereas derived units are units which are generated from
base units. Business field names are configured against Assigned_property
parent class. Only for time based business field parent should be Date or Date_
and_time_assignment class.

Reference Data Entries for Representation


The following table details the snippet reference data hierarchy for representation-
specific attributes.
Attribute RD Entry Parent RD
derivationType PTC:derivationType PLCS:Assigned_property
ClassName PTC:ClassName PLCS:Assigned_property
default PTC:default PLCS:Assigned_property
republishable PTC:republishable PLCS:Assigned_property
representationType PTC:representationType PLCS:Assigned_property
hasBoundingBox PTC:hasBoundingBox PLCS:Assigned_property
boundingBox PTC:boundingBox PLCS:Assigned_property
hasOctree PTC:hasOctree PLCS:Assigned_property
Octree PTC:octree PLCS:Assigned_property
repContentId PTC:repContentId PLCS:Assigned_property
Derived_image PTC:Derived_image PLCS:Document_
assignment

Windchill to PLCS Template Mapping


This section outlines the mapping of Windchill objects with the corresponding
DEX templates available in the PLCS Schema.

Data Exchange using Standards in Windchill 1873


WTPart Mapping
The following table depicts the common template mapping for WTPart and its
associated attributes.
Attribute Mapped Template
e_WTPart REPRESENTING_PART
Name assigning_identification
Number + (versionId + Iternation Id) + representing_part
Org Name
Ufid assigning_identification_with_no_
organization (associated to PART
VIEW DEFINITION)
masterufid assigning_identification_with_no_
organization (associated to PART)
view assigning_identification
lifeCycleState, assigning_product_property
lifeCycleTemplateName, domainName, product_property_text
externalTypeId, folderPath, defaultUnit,
partSource, partType, versionLevel,
defaultTraceCode, defaultUnit,
endItem, genericType

WTDocument Mapping
The following table depicts the common template mapping for WTDocument and
its associated attributes.
Attribute Mapped Template
e_WTDocument REPRESENTING_DOCUMENT
Name assigning_identification
Number + (versionId + Iternation Id) + representing_document
Org Name
Ufid assigning_identification_with_no_
organization (associated to document
version)
masterufid assigning_identification_with_no_
organization (associated to doc master)

1874 Customization Guide


Attribute Mapped Template
description assigning_descriptor
lifeCycleState, assigning_product_property
lifeCycleTemplateName, domainName, product_property_text
externalTypeId, folderPath,
versionLevel, docType, docTitle,
department,

BusinessField Mapping
BusinessFields (aka IBAs) are treated as simple properties associated to various
Windchill business objects. Based on the type of property, different templates
have been adopted for mapping purposes.
The following table depicts the common template mapping for BusinessField
and its related attributes based on the data type of property
Attribute Datatype Mapped Template
String, Boolean, HyperLink, Long, assigning_product_property
FloatingPoint product_property_text
FloatingPointWithUnits assigning_product_property
process_property_numeric
Timestamp assigning_time

Common Mapping for various data types except FloatingPointWithUnit is


straight forward. In later case apart from the common values one has to map the
unit value associated with each one.
In PLCS, individual units must be associated with a Reference data. Currently
only some basic unit-specific definitions are incorporated in the PTC-specific
standard template library. For details see the “Reference Data Entries for
BusinessField Attributes” section in Reference Data on page 1868.

WTPartDescribeLink Mapping
Express G Representation of WTPartDescribeLink and
WTPartReferenceLink.
The following figure shows the WTPart – WTDocument link.

Data Exchange using Standards in Windchill 1875


Detailed template mapping for WTPartDescribeLink and its associated
attributes can be found from the following table.
Attribute Mapped Template
e_WTPartDescribeLink ASSIGNING_DOCUMENT
(with “role” as “Document_
assignment”; “is_assigned_to” refers to
part version; and “assigned_document”
refers to document version)

WTPartReferenceLink Mapping
For Express G Representation of WTPartReferenceLink, see the WTPart –
WTDocument link diagram.
The following table describes the detailed template mapping for
WTPartReferenceLink and its associated attributes.

1876 Customization Guide


Attribute Mapped Template
e_WTPartReferenceLink ASSIGNING_DOCUMENT
(with “role” as “Document_reference”;
“is_assigned_to” refers to part version
(referencedBy); and “assigned_
document” refers to document
(references))

WTPart with Representation Mapping


The following diagram details WTPart with representation and content mapping.

The following table describes the detailed template mapping for Representation
and its associated attributes.

Data Exchange using Standards in Windchill 1877


Entity/Attribute/Relation Mapped Template
e_Representation (Entity) REPRESENTING_DIGITAL_
DOCUMENT
Association with WTPart ASSIGNING_DOCUMENT
(role as “Derived_image” which is an
extension RDL for “Document_
assignment”. With assigned_document
as representing_digital_document.doc
and is_assigned_to as representing_
part. View
Default, repContent.id, default, assigning_product_property
republishable,
derivationType, representationType,
hasBoundingBox, boundingBox,
hasOctree, octree

WTPART with Content Mapping


For a diagram detailing WTPart with content mapping, see the diagram in the
“WTPart with Representation Mapping” section.
The following table describes the detailed template mapping for WTPart with
content item association
Entity/Attribute/Relation Mapped Template
e_contentItem (Entity) REPRESENTING_DIGITAL_FILE
Association with WTPart ASSIGNING_DOCUMENT
(role as “Document_assignment” With
assigned_document as representing_
digital_file. digital_fileand is_
assigned_to as representing_part. View

Additional PLCS Resources


• For details related to DEX Templates see: http://docs.oasis-open.org/plcs/
dexlib/R5/dexlib/dex_index.htm
• For the PLCS Guide to Reference Data Development see: http://www.oasis-
open.org/committees/download.php/11732/PLCS%20Guide%20for%
20Reference%20Data%20Developers

1878 Customization Guide


Note
These are external links. PTC does not own or author this content. The content
is not hosted in the Windchill Help Center.

Data Exchange using Standards in Windchill 1879


42
Windchill Workgroup Manager
Customization
Custom Windchill Workgroup Manager Requests .................................................... 1884
Creating the Windchill Server-side Customization .................................................... 1890
Pre Operation Customization Hooks for PDM Actions .............................................. 1895
Registering a Custom Event Listener ...................................................................... 1896

Custom services can be registered with Windchill server to create the


infrastructure to validate a custom request, locate, and execute a custom service.
The server returns a custom response to be interpreted by the custom client code
which invokes a custom service through Windchill Workgroup Manager request
protocols.
A Windchill Workgroup Manager client invokes a custom service on Windchill
through the Custom Windchill Workgroup Manager Request Protocols.
This section contains the following information:
• Custom Windchill Workgroup Manager Requests on page 1884
• Creating the Windchill Server-side Customization on page 1890
• Registering a Custom Service on page 1894
• Pre Operation Customization Hooks for PDM Actions on page 1895
• Registering a Custom Event Listener on page 1896
This section details the server-side customization needed for custom requests that
have been created in Windchill Workgroup Manager. For more information on the
corresponding client customizations, see the Windchill Workgroup Manager
Toolkit section of the Windchill Workgroup Manager Help Center.

1881
Note
Some code examples in this section have been reformatted for presentation
purposes and, therefore, may contain line number, hidden editing characters
(such as tabs and end-of-line characters), and extraneous spaces. If you cut and
paste code from this manual, check for these characters and remove them
before attempting to use the example in your application.

1882 Customization Guide


Windchill Workgroup Manager Customization 1883
Custom Windchill Workgroup Manager
Requests

This is the object model of customWindchill Workgroup Manager requests.


A typical custom Windchill Workgroup Manager request, is inherited from
IterationRequest, and has the following attributes:
• ServiceDescriptor – a descriptor that helps locate a custom service to
be invoked
• RequestInstructionsData– a stringdict aka Map <String, String> to
carry the intended instructions
• Collection of IterationC11Instructions – a set of persistable objects
on which operation is performed, and a stringdict for each.
There are two types of custom Windchill Workgroup Manager requests:
• Custom request with workspace (WorkspaceC11nRequest). This could
be used for custom workspace operation.
• Custom request without workspace (C11nRequest). This could be used for
custom common space operation.

1884 Customization Guide


• If WorkspaceC11nRequest, workspace is an additional attribute.
• A Custom Response (C11nMessage) is a typical stringdict aka Map <String,
String> object that a client is supposed to interpret. Additionally there is set of
IterationC11nResponse. If there is a WorkspaceC11nRequest, it
would contain an updated workspace message
(WorkspaceUpdateC11nMessage).
• WorkspaceUpdate is processed through a Request Result Cache (RRC)
property populator module, while a rich set of fixed message for
FolderedIterations in C11nMessage is serialized back to the client.

Windchill Workgroup Manager Customization 1885


C11nRequest
public interface C11nRequest
extends UwgmRequest, IterationRequest
{
public final static UwgmRequestType type = new
UwgmRequestType("uwgmsvc::C11nRequest");

public final static C11nRequest EMPTY = null;

// RequestInstructionData access methods


/**
* Get value of attribute RequestInstructionData
*/
public stringdict getRequestInstructionData ();
/**
* Assign value to attribute RequestInstructionData
*/
public void setRequestInstructionData (stringdict value);

// ServiceDescriptor access methods

/**
* Get value of attribute ServiceDescriptor
*/
public String getServiceDescriptor ();
/**
* Assign value to attribute ServiceDescriptor
*/
public void setServiceDescriptor (String value);

// IterationC11nInstruction access methods

/**
* Get value of attribute IterationC11nInstruction
*/
public IterationC11nInstruction.Iterator getIterationC11nInstruction ();

/**
* Size of collection IterationC11nInstruction
*/
public int sizeOfIterationC11nInstruction ();

/**
* Get content of collection IterationC11nInstruction as array
*/
public IterationC11nInstruction<] getIterationC11nInstructionArray ();

// BEGIN_CUSTOM_DEFS guid=49BA56C202A4 type=JAVA_INTERFACE_DEFS


// END_CUSTOM_DEFS guid=49BA56C202A4 type=JAVA_INTERFACE_DEFS
}

1886 Customization Guide


WorkspaceC11nRequest
Definition of interface com.ptc.windchill.uwgm.
soap.uwgmsvc.WorkspaceC11nRequest

Unified WGM Source Code Generation Utility


*/

//
// $$NONE
//

package com.ptc.windchill.uwgm.soap.uwgmsvc;

import com.ptc.windchill.uwgm.soap.bins11n.*;

import com.ptc.cipjava.*;
import com.ptc.windchill.uwgm.soap.uwgm.*;
import com.ptc.windchill.uwgm.soap.bins11n.*;

// BEGIN_CUSTOM_DEFS guid=49BA63010149 type=JAVA_INTERFACE_HEADER


// END_CUSTOM_DEFS guid=49BA63010149 type=JAVA_INTERFACE_HEADER

/**
*
*/
@UwgmBinRegisterable
public interface WorkspaceC11nRequest
extends UwgmRequest, C11nRequest, WithWorkspace
{
public final static UwgmRequestType type = new
UwgmRequestType("uwgmsvc::WorkspaceC11nRequest");

public final static WorkspaceC11nRequest EMPTY = null;

// BEGIN_CUSTOM_DEFS guid=49BA63010149 type=JAVA_INTERFACE_DEFS


// END_CUSTOM_DEFS guid=49BA63010149 type=JAVA_INTERFACE_DEFS
}

Windchill Workgroup Manager Customization 1887


C11nMessage
public interface C11nMessage
extends UwgmMessage
{
public final static UwgmMessageType type = new
UwgmMessageType("uwgmsvc::C11nMessage");

public final static C11nMessage EMPTY = null;

// ResponseData access methods


/**
* Get value of attribute ResponseData
*/
public stringdict getResponseData ();

/**
* Assign value to attribute ResponseData
*/
public void setResponseData (stringdict value);

// IterationC11nResponse access methods


/**
* Get value of attribute IterationC11nResponse
*/
public IterationC11nResponse.Iterator getIterationC11nResponse ();

/**
* Size of collection IterationC11nResponse
*/
public int sizeOfIterationC11nResponse ();

/**
* Get content of collection IterationC11nResponse as array
*/
public IterationC11nResponse[] getIterationC11nResponseArray ();

// BEGIN_CUSTOM_DEFS guid=49BDE77E01EC type=JAVA_INTERFACE_DEFS


// END_CUSTOM_DEFS guid=49BDE77E01EC type=JAVA_INTERFACE_DEFS
}

1888 Customization Guide


WorkspaceUpdateC11nMessage
Definition of interface com.ptc.windchill.uwgm.soap.
uwgmsvc.WorkspaceUpdateC11nMessage

Unified WGM Source Code Generation Utility


*/

//
// $$NONE
//

package com.ptc.windchill.uwgm.soap.uwgmsvc;

import com.ptc.windchill.uwgm.soap.bins11n.*;

import com.ptc.cipjava.*;
import com.ptc.windchill.uwgm.soap.uwgm.*;
import com.ptc.windchill.uwgm.soap.bins11n.*;

// BEGIN_CUSTOM_DEFS guid=49BDE7C602D8 type=JAVA_INTERFACE_HEADER


// END_CUSTOM_DEFS guid=49BDE7C602D8 type=JAVA_INTERFACE_HEADER

/**
*
*/
@UwgmBinRegisterable
public interface WorkspaceUpdateC11nMessage
extends UwgmMessage, C11nMessage, WorkspaceUpdateMessage
{
public final static UwgmMessageType type = new
UwgmMessageType("uwgmsvc::WorkspaceUpdateC11nMessage");

public final static WorkspaceUpdateC11nMessage EMPTY = null;

// BEGIN_CUSTOM_DEFS guid=49BDE7C602D8 type=JAVA_INTERFACE_DEFS


// END_CUSTOM_DEFS guid=49BDE7C602D8 type=JAVA_INTERFACE_DEFS
}
Please note that creation of custom request (WorkspaceC11nRequest or
C11nRequest) is part of client side customization. The Windchill server
provides infrastructure to execute custom request. Client side customization also
needs to process server response of the custom request. Interfaces shown above
(C11nRequest, WorkspaceC11nRequest, C11nMessage and
WorkspaceUpdateC11nMessage) are used in client side customization code
to implement custom request on client side and process custom response.

Windchill Workgroup Manager Customization 1889


Creating the Windchill Server-side
Customization
The Windchill server provides the infrastructure to validate custom Windchill
Workgroup Manager requests, and invoke a custom service. Typically, you need to
perform the following steps:
1. Implement the UwgmC11nService interface.
2. Register the custom service in <Windchill>/codebase/com/ptc/
windchill/uwgm/common/delegate/
application.service.xconf.
The different types of custom requests invoke different methods:
• The non–workspace based custom request (C11nRequest) invokes the
UwgmC11nService.execute() method.
• The workspace-based custom request (WorkspaceC11nRequest) invokes
the UwgmC11nService.executeInWS() method.
However, both of these methods use a customized request context
(C11nRequestContext) which provides the getters for the following
attributes:
• WTPrincipal
• Locale
• Client Name
• Version
• SessionID
Both these methods ((execute() and executeInWS()) return an
intermediate UwgmC11nResponse which is then serialized back to the client as
C11nMessage.

1890 Customization Guide


UwgmC11nService
public interface UwgmC11nService
{
/**
* The Cutsom service delegate is expected to implement execute
* @param c11nCtx
: com.ptc.windchill.uwgm.proesrv.c11n.C11nRequestContext
* @param c11nInstructions
: Map<String, String>
* @param c11nIterationInstructions
: Map<Persistable, Map <String, String>>
* @return UwgmC11nResponse
: com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nResponse
* @throws WTException
: Exception
* @throws ConflictException
: Conflict
*/
public UwgmC11nResponse execute(C11nRequestContext c11nCtx,
Map<String, String> c11nInstructions,
Map<Persistable, Map<String, String>>
c11nIterationInstructions)
throws WTException, ConflictException;

/**
* The Cutsom service delegate is expected to implement execute
* @param c11nCtx
: com.ptc.windchill.uwgm.proesrv.c11n.C11nRequestContext
* @param c11nInstructions
: Map<String, String>
* @param c11nIterationInstructions
: Map<Persistable, Map <String, String>>
* @param ws
: EPMWorksapce
* @return UwgmC11nResponse
: com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nResponse
* @throws WTException
: Exception
* @throws ConflictException
: Conflict
*/
public UwgmC11nResponse executeInWS(C11nRequestContext c11nCtx,
EPMWorkspace ws,
Map<String, String> c11nInstructions,
Map<Persistable, Map<String, String>>
c11nIterationInstructions) throws WTException,
ConflictException;
}

Windchill Workgroup Manager Customization 1891


C11nRequestContext
public interface C11nRequestContext
{
/**
* returns current user (principal)
* @return WTPrincipal
*/
public WTPrincipal getPrincipal();

/**
* returns current client's locale
* @return Locale
*/
public Locale getLocale();

/**
* returns client canonic name
* @return String
*/
public String getClientName();

/**
* returns client canonic version
* @return int
*/
public String getClientVersion();

/**
* returns the session information of the Client
* @return String
*/
public String getClientSessionID();

/**
* retruns the name of the PDM request
* @return String
*/
public String getRequestName ();
}

1892 Customization Guide


UwgmC11nResponse
public UwgmC11nResponse(Map<String, String> stringData,
Map<Persistable, Map<String, String>> iterationData)
{
responseData = stringData;
iterationResponseData = iterationData;
}

/**
* It is expected that the client recieving the response
* understands the semantics
* of the keys; and accordingly interprets the
* value of the response.
* @return Map <String, String>
*/
public Map<String, String> getResponseData()
{
return responseData;
}

/**
* Response elements associated to the Persistable.
* It is expected that the client recieving the response s
* understand the semantics of the key; and accordingly
* interprets the value of the entries in the String Map
* associated with each Persistable in the Map.
*
* @return Map<Persistable, Map<String, String>>
*/
public Map<Persistable, Map<String, String>> getIterationResponseData()
{
return iterationResponseData;
}

/**
* logging
*/
private static Log log = LogFactory.getLog(UwgmC11nResponse.class);
}
An example implementation of UwgmC11nService is provided in your
Windchill installation at <Windchill>/codebase/com/ptc/
windchill/uwgm/proesrv/c11n/UwgmC11nServiceTest.java for
reference only. You are not expected to reuse this class. You need to implement
your own server-side customization as per your needs.

Windchill Workgroup Manager Customization 1893


Registering a Custom Service
Custom services must be registered in the <Windchill>/codebase/com/
ptc/windchill/uwgm/common/delegate/
application.service.xconf file.
Here is an example of a typical format:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">

<Configuration targetFile="codebase/service.properties">

<!-- UWGM Custom Services Implementation for Unit Test -->

<Service context="default"
name="com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nService">
<Option cardinality="duplicate" requestor="java.lang.Object"
selector="UWGMC11N_UNIT_TEST"
serviceClass="com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nServiceTest"/>
<Option cardinality="duplicate"
requestor="java.lang.Object"
selector="UWGMWSC11N_UNIT_TEST"
serviceClass="com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nServiceTest"/>
</Service>

</Configuration>
The selector provides the key to be able to locate a registered service. This key
forms the ServiceDescriptor attribute of the C11nRequest; and helps the
application services infrastructure to invoke appropriate services.
It is important that your custom code needs to pass this key properly in the Uwgm
Request to execute a custom code on the server.
You must use the xconfmanager utility to propagate changes in
application.service.xconf file to the service.properties file.

1894 Customization Guide


Pre Operation Customization Hooks for
PDM Actions
Currently pre operation hooks are supported only for checkin, checkout, rename,
revise, and save as operations. Post operation hooks are not supported. The pre
operation hooks are only be vetoable in nature; and would only add workflow that
would not modify the persistables. The only checks are to catch the exceptions
vetoed and abort the transaction. This facilitates adding a workflow that could
extract properties from the persistables, and add additional validation mechanism.
You must perform following steps to implement custom pre operation hook:
1. Implement UWGMEventListener interface
2. Register the implemented event listener in <Windchill>/codebase/
com/ptc/windchill/uwgm/common/delegate/
application.service.xconf

UWGMEventListener
Below is the description of the UWGMEventListener API that a custom
EventHandler code needs to implement.
public interface UwgmEventListener
{
/**
* API to process UwgmEvent
* Custom UwgmEventService delegate should implement this API.
*
* @param iteration : Collection of request Iterations
* @param workspace : EPMWorkspace
* @return WTCollection : Response
* @throws WTException
*/

public WTCollection processUwgmEvent(C11nRequestContext


requestContext,WTCollection iteration,EPMWorkspace workspace)
throws WTException;

}
Am example implementation of UWGMEventListener is provided in your
Windchill installation at <Windchill>codebase/com/ptc/windchill/
uwgm/proesrv/c11n/UwgmC11nEventListenerTest.java for
reference purposes only. You are not expected to reuse this class. You need to
implement your own server-side customization as per your own needs.

Windchill Workgroup Manager Customization 1895


Registering a Custom Event Listener
You must register any custom listener (UwgmEventListener) handler in the
<Windchill>/codebase/com/ptc/windchill/uwgm/common/
delegate/application.service.xconf file.
Here is an example of a typical format:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">
<Configuration targetFile="codebase/service.properties">
<!-- UWGM Custom Services Implementation for Unit Test -->

<Service context="default"
name="com.ptc.windchill.uwgm.proesrv.c11n.UwgmEventListener">
<Option cardinality="duplicate"
requestor="java.lang.Object" selector="PRE_CHECKIN"
serviceClass="com.ptc.windchill.uwgm.proesrv.c11n.UwgmC11nEventListenerTest"/>
</Service>
</Configuration>
The following selectors are currently supported for registering custom event
listeners:
• PRE_CHECKIN
• PRE_CHECKOUT
• PRE_RENAME
• PRE_SAVEAS
• PRE_REVISE
You must use the xconfmanager utility to propagate changes in
application.service.xconf file to the service.properties file.

1896 Customization Guide


43
CAD Document Structure
Publishing to Other Systems
CAD Document Structure Publishing to Other Systems ............................................ 1898

This section contains information on publishing CAD document structures to


other systems.

1897
CAD Document Structure Publishing to
Other Systems
It is possible to send CAD Document Structures to other systems using the
Windchill Gateway Architecture along with the Windchill ESI framework. This
functionality works in a similar manner as Windchill ESI functionality.
You can associate a Distribution Target to a CAD Document and then the CAD
Document can be published to the Distribution Target. The initial publishing of a
CAD document structure to a Distribution Target will send the entire structural
information. The subsequent publishing of the same CAD document structure that
is initiated due to changes in the structure will send only the delta information.
The delta will have only the changed information since the last time it was
published to the same Distribution Target.

Process Overview for Publishing CAD Document


Structures to Other Systems
The detail process flow that can be followed in order to use this functionality is as
follows.

Creating New Distribution Target


A user with ESI author or ESI administrator credentials can create a new
Distribution Target of type “Distributed Process.” See the “Creating a Distribution
Target” topic in the Windchill Help Center for more information.

Associate the Distribution Target to CAD Document


CAD Document will have an “Associate Distribution Target” using which, user
can associate “Distributed Process” type of Distribution Targets to CAD
Documents. This is action is available from the Distribution Target table on CAD
Document details page as well
It is possible to associate a Distribution Target to a CAD Document using “Update
Distribution Targets” action in structure browser. This is a multi-select action and
using this action, user is able to associate targets to multiple objects.

Send to Distribution Target Action


A CAD Document will have a “Send to Distribution Target” action. If the CAD
Document is associated to any “Distributed Process” type of Distribution Target, a
Send To Distribution Target page is launched. This allows you to select specific
Distribution Targets (if multiple targets are associated) to which the CAD
Document is to be published.
Only the organization default target cannot be excluded from publishing. You can
view a preview if desired and the Send button will initiate the publishing action.

1898 Customization Guide


For each publishing, the Distributed Process creates a schedule, a job and an ESI
transaction. See the “Sending to a Distribution Target” topic in the Windchill Help
Center for more information.

Reviewing Transaction
An ESI transaction can be accessed from the ESI Transaction Log page (available
from Site ▶ Utilities) page for an Organization Administrator. Each transaction will
be associated to a job. User can navigate to corresponding job details page using a
context (RMB) menu action on a specific transaction.

Event Based Publishing


Apart from being able to manually publish a CAD Document structure to
Distribution Target, Windchill also offers an event based publishing capability. It
is possible to publish any CAD Document when its LC state changes. You can
define the LC states at which the publishing event should be triggered. This is
controlled through the “Lifecycle States Triggering Publication of a CAD
Document” preference.

Reviewing Jobs
You can navigate to the Jobs List page from the Process List page using the List
Jobs action available from the context (RMB) menu. The Jobs List page lists all
jobs against the selected Distributed Process. On the Job Details page, you can
view the attributes defined on the job.
The Operation Status tab provides a list of all operations in the job. It provides
information about the name and status of each operation. From here you can view
the logs associated with each operation as well. The Export And Publish operation
will have the exported JAR file attached to it. This file can be downloaded for
further use if required.
You can add a custom tab to the job details page and add a custom table using
Customize ▶ Related Objects ▶ Transaction. This displays a Related Transaction
table which provides information about the related ESI transaction.
See the “Viewing Related ESI Transactions” topic in the Windchill Help Center
for more information.

Details on Delta
The following objects are factored into delta calculation; EPMDocument,
EPMMemberLink and EPMReferenceLink. When delta information is sent,
it is categorized in 3 distinct categories; Create, Changed and Unchanged.
• Create – The object is being sent for the first time to the distribution target.
When an object is categorized in the “Create” category, the complete object

CAD Document Structure Publishing to Other Systems 1899


information is bundled in the PLM message. This includes all metadata in
PLM Services format along with all content information
• Change – The object is changed since the last publishing to the distribution
target. When an object is categorized in the “Changed” category, the complete
object information is bundled in the PLM message. This includes all metadata
in PLM Services format along with all content information. A CAD Document
will be considered as Changed only when its iteration, revision or LC State
changes. An EPMMemberLink will be considered as Changed only when any
attribute information on the EPMMemberLink changes. If a parent is iterated,
but no other attribute information changes on the EPMMemberLink, then
such EPMMemberLink is not called as Changed.
• Unchanged – The object is Unchanged since last publishing to the distribution
target. When an object is categorized in the “Unchanged” category, only
reference information (the information which is absolutely required in a PLM
message in order to establish relationships, etc) is sent in the PLM message.
Note that content is not sent for objects categorized as “Unchanged”

1900 Customization Guide


Configuring Publishing CAD Document Structures
to Other Systems
To configure the capability to publish CAD document structures to other systems,
Windchill needs to be configured with a 3rd party MOM (Message oriented
Middleware).

Configuring the Inqueue and Outqueue in Windchill


The following properties must be set in wt.properties :
• com.ptc.windchill.dpimpl.distproc.impl.inqueuename=
<name_of_inqueue>
• com.ptc.windchill.dpimpl.distproc.out.queuename=
<name_of_outqueue>
The following property must be set in install.properties to enable the
Distribute Process Controller :
• Windchill.DPC=true
You must generate security keys to enable the Distributed Process Architecture.
• Run the following command in a Windchill shell to generate keys :
windchill
com.ptc.windchill.dpimpl.util.DPGenerateKeys
• You can verify the generated keys in the “<%WT_HOME%>/DistProc”
folder.

Update JMS configurations for JMS Services


When configuring Info*Engine with a JMS MOM, it is recommended to create a
new JMS service entry with name SunMQ. If the JMS service is created with
different name then the same name has to be updated in <%WT_HOME%>\
DistProc\distproc.properties. The property name is
com.ptc.windchill.dpimpl.distproc.jms.service having default
value of SunMQ.
Manually add the JMS Base URI Principal / JMS Base URI Password in the
Info*Engine Administration page for the JMS service configured above.

CAD Document Structure Publishing to Other Systems 1901


Note
For information on detailed information on JMS Properties see the “Core JMS
Properties” section in the “Windchill Adapter Properties” online help topic.
Located at: Windchill Help Center > Specialized Administration >
Info*Engine Administration

Working with Process Templates


This section details the various options available for process templates.

Viewing a Process in a Distribution Target


1. Navigate to the Process List page : http://<server_host_
name>:<port>/Windchill/app/#ptc1/comp/

1902 Customization Guide


netmarkets.dpimpl.processList?appType=distribution_
target
2. The following options are available for viewing a process:
• Delete ( ) lets you delete a process.
• New Process ( ) lets you create a new process.
• Find ( ) gives you the option of text searching within the file names.
• Table Display ( ) gives you the option of freezing and unfreezing the
columns, and viewing the processes that only you have selected.
• Information ( ) lets you view the details of the process. The details of a
process are read-only. This window lists all the attributes such as Name,
Template, Created On, Last Modified, and information on the adapter, task
Uniform Resource Identifier (URI), and input.
3. Select Close to close the windows.

Viewing a Job List in a Distribution Target


A job is a run of the process. The job executes by passing through various
execution points. The infrastructure maintains a status of each job running, and
provides the owner of the job a way to manage the job.
On the Jobs List page, the following options are available to view job lists
Option Description
Search in Table ( ) Allows you to search for text within the
file names.
Pick a View drop-down menu Lets you select the types of jobs you
want to see displayed: All, Cancelled,
Completed, Failed, or Running.
Table Display ( ) Gives you the option to View selected
objects only when the check boxes next
to the processes are enabled. If no
processes are selected, all processes are
displayed.
Delete icon Lets you delete a job.
Display Schedules for Process ( ) Displays the schedule of the process the
job is run from.
View Process ( ) Display the process associated with the
job.
Click the Information icon Display details of the selected job.

CAD Document Structure Publishing to Other Systems 1903


Viewing a Schedule List in a Distribution Target
The following options are available to view schedule lists.
Option Description
Find ( Lets you search text within file names.
)
View Drop-Down Menu Gives you the option of displaying all,
enabled only, or disabled only
schedules.
Table Display ( ) Gives you the option of freezing or
unfreezing the columns, and viewing
the schedules that you have selected.
Information ( ) Displays the details of the schedule.

1904 Customization Guide


44
ThingWorx
Adding a ThingWorx Mashup to Windchill................................................................ 1906

This section contains information on customizations related to ThingWorx.

1905
Adding a ThingWorx Mashup to Windchill
How to add a ThingWorx mashup to Windchill.
The site administrator is able to add ThingWorx actions into the Windchill UI to
embed ThingWorx mashups within the Windchill page or launch ThingWorx
mashups ‘standalone’ in separate window or browser tab.

Prerequisites
• Windchill 11.0+ server
• ThingWorx server (and a ThingWorx mashup to be added to Windchill UI)

Configuring the com.ptc.thingworxURL wt.property


Using the xconfmanager from a Windchill shell, add wt.properties property
that contains the ThingWorx URL. For example:
xconfmanager -s com.ptc.thingworxURL="http://server_
name.domain1.com:9999/Thingworx/" -t codebase\
wt.properties -p

Note
This property could contain URL parameters if desired.

1906 Customization Guide


Find the Action Model to Update
Enable Customization Utilities
To view Action Model info pages, the Windchill customization utilities included
in the user interface need to be enabled. They are not enabled by default.
To enable the customization utilities:
1. From the Navigator browse to Site ▶ Utilities ▶ Preference Manager
2. Navigate the tree to Client Customization and expand the entry.
3. Right click on Client Customization, select Set Preference, and set the value to
“Yes”.
4. Refresh your browser.
5. From the Navigator browse to Site and select the Customization icon ( ).
6. Select Tools from the Customization menu.

Note
The direct URL to the menu is: <server>/<webapp>/app/#ptc1/
carambola/tools/list?tab=customization

ThingWorx 1907
Finding the Action Model
1. Navigate to Customization ▶ Tools ▶ Action Model.

2. Search for the action model of interest to find its corresponding info page.
3. From the action model, info page actions can be added into the model, See
Creating a new ThingWorx Action in the Model on page 1912 for instructions.

1908 Customization Guide


thingworxActionsMenu and thingworxCustomizeMenu Action Models
A thingworxActionsMenu and thingworxCustomizeMenu action
submodel was added into the OOTB actions menu and customize menu models
for several types. The thingworxActionsMenu and
thingworxCustomizeMenu action models are placeholders for custom
ThingWorx actions. Those models are empty OOTB and will not display to the
user untill at least one action is added into the model.
The action submodels were added for types: Part, Document, Caddoc, Problem
Report, Change Request, Change Notice, Variance, and Change Task
(wt.part.WTPart, wt.doc.WTDocument, wt.epm.EPMDocument,
wt.change2.WTChangeIssue, wt.change2.WTChangeRequest2,
wt.change2.WTChangeOrder2, wt.change2.WTVariance, and
wt.change2.WTChangeActivity2)

ThingWorx 1909
Other Action Models
ThingWorx actions could be added into any model (not just the
thingworxActionsMenu and thingworxCustomizeMenu models).
However, such customizations override the OOTB action models, so take care to
re-evaluate what is customized in those files as it may cause conflicts during
upgrades.

1910 Customization Guide


How to find an Action Model using jcaDebug
Open the Windchill UI in a browser. Go to the desired UI/menu/info page for the
ThingWorx mashup to be added. Add “jcaDebug=true” URL parameter to see
what action models are being used.
Either of these examples is valid:
• http://<host>/<webapp>/app/#ptc1/tcomp/infoPage?oid=
VR%3Awt.part.WTPart%3A54330&jcaDebug=true
• http://<host>/<webapp>/app/?jcaDebug=true#ptc1/
tcomp/infoPage?oid=VR%3Awt.part.WTPart%3A54330
Either option works to enable jcaDebug for the content area. Option 2 is necessary
to enable jcaDebug in the navigator as well. Once jcaDebug is enabled, there
would be an extra action named ‘<action model name>’ Action Model Report that
opens the Action Model info page when clicked. From the action model info page
actions can be added into the model.

ThingWorx 1911
Creating a new ThingWorx Action in the Model
The site administrator has actions available in the toolbar to create/remove/paste
actions into the model. Those actions update the <wt home>/codebase/
custom-actions.xml and <wt home>/codebase/custom-
actionmodels.xml files as necessary and then all the action definitions are
reloaded.
1. Create an Action.

2. On step 1 of the wizard provide the Label, Name, and Object Type. These can
be any values.

3. On step 2 of the wizard provide the URL. The URL must be: ptc1/
twx?mashup=<name of mashup>

The ptc1/twx URL is handled by a ThingWorxController that looks up the


ThingWorx URL in wt.properties and forwards/redirects as necessary to
launch the ThingWorx mashup in popup or embed it in the page.

1912 Customization Guide


In addition, the ThingWorxController handles giving the mashup the oid
and ContainerOid as URL parameters (where applicable). The mashup would then
have to make the necessary calls (using Windchill REST services) to acquire any
additional data that is necessary for displaying the mashup. For more information
about mashups, see the ThingWorx Help Center.

Note
Currently it is not supported to pass additional parameters to the mashup via
the action URL.

Popup vs Embedded in Page


If the action is being added into an actions menu, then the windowType could be
set to popup so the ThingWorx mashup is launched standalone in its own browser
window/tab.

If the action has no windowType, or is given windowType=page, then the


mashup displays embedded in the Windchill shell.
Note: if the action is being added to a model that is designed to keep content in the
Windchill shell, then the ThingWorx mashup is embedded in the Windchill shell
even if you select windowType=popup. The customize menu, info page tab set,
and navigation models are examples of this scenario.

Supported Types / Non Supported Types


If adding an action into the thingworxActionsMenu or
thingworxCustomizeMenu model, and the action should only show up for
certain types, then the Supported Types / Non Supported Types attributes on step 2
of the Create Action wizard should be filled in with the desired types.

Window and iframe Sizing


For the ThingWorx mashups displayed embedded in the Windchill shell, the
iframe is hard coded to a 1200px height that mashups should adhere to. If the
1200px iframe is too small there could be unnecessary scrollbars. If the iframe is
too large there could be unnecessary whitespace. In future release this may be
fixed to auto-size based on the contents of the iframe.

ThingWorx 1913
For popups, the ThingWorx content would not be in any iframe. The default size
of the popup window may not match the content, but the user would be able to
resize the window. The window size is not sticky. It is possible in the XML action
definition to control the size of the popup with <moreurlinfo>height=
1000,width=1200</moreurlinfo>. This change must be made by editing
the action xml files directly, because the the moreurlinfo param is not currently set
via the action model report UI.

1914 Customization Guide


Testing New ThingWorx Actions
Once you have created your new ThingWorx action from the action model report,
test it out from its launch point. If you added an action into the
thingworxActionsMenu or thingworxCustomizeMenu action models
you should now be able to see the ThingWorx option in the menu/tabset/
navigator (without any jcaDebug=true URL parameter).

This is an example of ThingWorx mashup embedded in Windchill info page:

ThingWorx 1915
Troubleshooting
The ThingWorx mashup will not appear if there is a misconfiguration. Various
ways to misconfigure include:
• The com.ptc.thingworxURL property in wt.properties is either not
set, or set to an invalid URL.
• The url in the action definition is misconfigured because of a typo in the URL,
or the mashup parameter is missing.

Error Messages Due to Misconfigurations


Below are the various error messages that are logged/displayed in the UI when the
ThingWorx action is launched if they have the above misconfigurations:

1916 Customization Guide


Error Messages from the ThingWorx Server
If the ThingWorx server is down, the actions will still appear in the Windchill UI,
but when clicked it would result in the following error.

ThingWorx 1917
ThingWorx ClickJack Support
Clickjacking is when an attacker uses a frame to display a site and applies one or
more invisible layers over the site, tricking the user into thinking they are clicking
on one thing when they are actually clicking on the something in the invisible
layer. A defense against Clickjacking utilizes response headers from the server
that tell the browser whether it is ok to frame the page. Because of compliance
differences in browsers, two different headers must be used to indicate domains
allowed to frame. These two headers (X-Frame-Options and Content-
Security-Policy) are described below. ThingWorx utilizes both of these
headers, enabling the administrator to configure to disallow all framing, only
allow framing from its own origin, or allow framing from a specific domain.

Header Descriptions
The two headers used to combat Clickjacking are X-Frame-Options and
Content-Security-Policy.
The Content Security Policy Level 2, which contains frame-ancestors, is
supported by the current version of all browsers except Internet Explorer, Edge,
Opera Mini, and only partially supported as of Firefox 52. A full list can be found
at: http://caniuse.com/#feat=contentsecuritypolicy2. The X-Frame-Options
Allow-From header is supported in Internet Explorer as of version 8 and
Firefox as of version 18, but is not supported by Chrome, Safari, or Opera. A list
of supported browsers can be found at: https://www.owasp.org/index.php/
Clickjacking_Defense_Cheat_Sheet#Limitations

X-Frame-Options
• DENY - The page cannot be displayed in a frame, regardless of the site
attempting to do so.
• SAMEORIGIN - The page can only be displayed in a frame on the same origin
as the page itself.
• ALLOW-FROM http://example.com - The page can only be displayed in
a frame on the specified origin.

Content-security-policy
• frame-ancestors ‘none’ - Prevents loading resources in a frame from
any origin.
• frame-ancestors ‘self’ - Allows loading resources in a frame but only
from the same origin.
• frame-ancestors domain1.com domain2.com - Allows loading
resources in a frame but only from domains in the given list.

1918 Customization Guide


ThingWorx Support
Configuration
ThingWorx will support both headers through the use of a Http request filter. The
administrator will be able to enable or disable one of three filters:
ClickjackFilterDeny, ClickjackFilterSameOrigin, and
ClickjackFilterWhiteList by uncommenting one of the three filter
mappings in the web.xml file of the ThingWorx application.
For example:
<!-- use the Deny version to exclude all framing -->
<!--
<filter-mapping>
<filter-name>ClickjackFilterDeny</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<!-- use the SameOrigin version to allow your application to frame, but nobody else -->
<!--
<filter-mapping>
<filter-name>ClickjackFilterSameOrigin</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<!-- use the WhiteList version to allow framing from specified domains -->
<filter-mapping>
<filter-name>ClickjackFilterWhiteList</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

No other configuration is needed for the ClickjackFilterDeny or the


ClickjackFilterSameOrigin. If the administrator chooses to use the
ClickjackFilterWhiteList, they must add the accepted domains in the
filters “domains” parameter value.
For example:
<filter>
<filter-name>ClickjackFilterWhiteList</filter-name>
<filter-class>com.thingworx.security.filter.ClickjackFilter</filter-class>
<init-param>
<param-name>mode</param-name>
<param-value>WHITELIST</param-value>
</init-param>
<init-param>
<param-name>domains</param-name>
<param-value>http://media-pc:8080
http://192.168.152.133:8080 http://domainY.com</param-value>
</init-param>

ThingWorx 1919
</filter>
The given domains must be in the format shown, a space separated list which
includes the scheme (http).

Note
There is a restriction to the Allow-From header. It will only allow a single
domain.

1920 Customization Guide


45
Deploying Arbortext
Customizations
Annonymous Arbortext Access............................................................................... 1922

Arbortext Editor (version 5.4 F000 and later) is capable of downloading a zipped
custom directory structure using HTTP, extracting its contents to a temporary
file system location, and using that as a custom directory. This allows
administrators to store Arbortext doctypes and other customizations in Windchill.
Windchill makes the zipped custom directories available by designating a
special anonymous access folder whose contents will be made available over
anonymous HTTP. The HTTP access is anonymous so the user is not presented
with an unexpected credentials prompt during Arbortext Editor startup.

1921
Annonymous Arbortext Access
Process Overview
To host an XML Application in Windchill and use it from Arbortext Editor:
1. Create a zip archive of the custom directory structure.
2. Log in to Windchill, locate a Product or Library (or create one if needed), and
then select the Folders second-level navigation for the container.

Note
Only Products and Libraries are supported. Other containers (Site, Org,
Program, Project) are not supported by this feature.

3. Create a folder (if needed) to hold the Arbortext customizations. This folder
can be at the top-level or it can be nested inside some other folder (at any
depth).
4. Inside that same Product or Library, bring up the Preference Management
utility, expand the Arbortext preference group, and locate the Customizations
Folder preference.
5. Edit that preference and enter the name and path of the desired folder. Some
example values are:
Value Description
Arbortext Customizations Top level folder with a space in the
folder name.
Arbortext/Applications Top level folder called “Arbortext”
with a child folder called
“Applications”.

Having set this preference, any WTDocument objects in the specified folder
will now be available via anonymous HTTP. (specific details on constructing
the URL will come later in this document).
6. Upload the zip file into the desired folder. When creating the document in
Windchill, the “Type” and “CAGE Code” values do not matter.
7. Put the anonymous access URL for your archive into the browser and verify
that you can successfully download the zipped archive. See Anonymous
Access URL Format on page 1923 for information on the anonymous access
URL.
8. Set the APTCUSTOM environment variable to the anonymous access URL for
your zip archive and launch Arbortext Editor to use the customizations.

1922 Customization Guide


Note
For more information on zipped Arbortext customizations, see the "Deploying
zipped customizations" section of the Arbortext Help Center (Programming >
Arbortext Customizer's Guide > Custom applications > Deploying zipped
customizations).

Anonymous Access URL Format


Type URL Format
Library http://server:port/Windchill/servlet/
WindchillGW/
com.ptc.arbortext.windchill.anonymous.Anony
mousAccessDownloader/lib/orgName/
libraryName/name[?params]
Product http://server:port/Windchill/servlet/
WindchillGW/
com.ptc.arbortext.windchill.anonymous.Anony
mousAccessDownloader/product/orgName/
productName/name[?params]

Note
The folder name itself is not contained in the URL. The folder name is defined
in the Customizations Folder preference. See Configuring the Folder Path for
Anonymous Access on page 1926 for information on setting this preference.

Note
As is normal for HTTP URLs, some characters, like spaces, colons, and non-
Latin characters will need to be escaped in the URL; for example, space
characters will need to be replaced with %20.

Deploying Arbortext Customizations 1923


The name portion of the URL can be one of three things:
• The object number in Windchill
• The object name in Windchill
• The filename of the underlying file. Generally, this is the originally uploaded
file name.
Since folders in Windchill may contain multiple objects with the same name or
underlying filename, the safest way to ensure you get the correct object is to use
its number. Name clashes should be rare.
As an example, suppose you uploaded a file called hello.txt into this folder.
The object name may be “hello”, an example object number may be
“0000007324”, and the filename would be “hello.txt”. In this case, any of
these could be used to specify this object in the URL.
When looking for an object to match the given string, highest priority is given to
matching the number. If no matching number is found then a match against the
first object with same name is done. If no matching name is found the, lastly, a
match against the first object with the same filename is done.
In general, it is unlikely that there will be multiple objects with the same name or
filename. But if that situation exists, the number can be used to safely access the
desired object.
The optional combination of query parameters are as follows: The order of these
parameter does not matter.
Parameter Description
(no parameters) The latest iteration from the latest
version will be selected; not counting
working (checked-out) iterations.
state The most recent iteration from the most
recent version that matches the given
lifecycle state will be selected.
version The most recent iteration from the
specified version will be selected.
iteration The iteration parameter is ignored. This
is only used along with the version
parameter.
state, iteration The iteration parameter will be ignored.
See “state” above.
state, version The most recent iteration from the
specified version that matches the given
state will be selected.

1924 Customization Guide


Parameter Description
version, iteration The specified iteration from the
specified version will be selected.
state, version, iteration The iteration parameter will be ignored.
See “state, version” above.

Examples of query parameter usage:


Query Parameters Description
.../custom.zip.xml?ver Version C.2 of custom.zip
sion=C&iteration=2
.../custom.zip?state= The most-recent version marked as
Approved Approved.
.../custom.zip?state= The most-recent version marked as
Approved&version=B Approved with a version of B.
.../custom.zip?version=B The latest iteration in the B version.

If you specify the name of an object which does not exist in the folder, or no
iteration of the object matches the given request parameters, the anonymous
access URL will return a 404 response to the caller. This is normal HTTP
behavior when the requested object is not found.

Note
Selecting the “Latest” Version
When dealing with versioned Windchill objects, the convention is that the
“latest” object is selected by version and then by iteration. The latest iteration
in version D will always be considered “newer” than the latest iteration in
version C, even if that iteration was created more recently. For example, when
browsing folder contents using the web UI, you’ll always see the latest
iteration from the latest version, even if there are newer iterations in other
versions.
The version selection for anonymous access URLs works in this way. For
example, if the state parameter is specified without a version, and A.4 and B.2
both have the requested state, B.2 will always be returned regardless of when
A.4 was created.

Deploying Arbortext Customizations 1925


Objects Available for Anonymous Access
Although this functionality is primarily to allow Arbortext products to access
Windchill-managed XML applications, other files types, such as word documents
or text files can also be accessed. In order for the anonymous access URL to work,
the target object must be a WTDocument object (or subtype thereof). You cannot
access other Windchill object types, such as EPMDocument objects (CAD files
or Arbortext Editor-created XML files) or WTPart structures.

Configuring the Folder Path for Anonymous Access


The Customizations Folder preference specifies the path to a folder that contains
Arbortext customizations in a zipped format. The content from all Windchill
documents in the specified folder will be made available without authentication
via a specially constructed URL.
To set this preference navigate to Site ▶ Utilities ▶ Preference Management ▶
Arbortext ▶ Customizations Folder.

• Site/Organizations : To disable anonymous access, set an empty value for this


preference and select the Lock checkbox.
• For Products/Libraries : Specify the path to a folder in this Product or Library
that contains Arbortext customizations in a zipped format. An empty value for
this preference means that no folders in the Product or Library are exposed
anonymously

Note
For more information on zipped Arbortext customizations, see the
"Deploying zipped customizations" section of the Arbortext Help Center
(Programming > Arbortext Customizer's Guide > Custom applications >
Deploying zipped customizations).

By default, this preference value is empty. If a Product or Library has an empty


value for this preference then anonymous access is not allowed for that container.
One way for an administrator to forcibly disable this feature is to set and lock the
preference at a Site or Org level to be an empty value. Due to the normal
inheritance rules of Windchill, this will force all child Product and Library
containers to also have an empty value for this preference and thus the feature will
be entirely disabled.

1926 Customization Guide


Here are some example preference values:
• Arbortext Customizations : Creates a top level folder named
“Arbortext Customizations” which includes a space in the folder
name.
• Arbortext/Applications : Creates a parent folder named
“Arbortext” with a child folder named “Applications”.
Suppose a non-empty value is set for this preference inside a Project or Program.
That setting will have no effect because the feature does not work with those
container types. To be more precise, there is no HTTP URL you can construct to
access any such folder from these containers.
Suppose a non-empty value is set for this preference inside a Site or Org. This is
actually undesirable because, due to the inheritance rules, all child containers will
inherit this value (unless they override a specific value of their own). This will
imply that any child Product or Library that happens to have a folder path that
matches the preference value, will have that folder’s contents exposed
anonymously.
When setting the value of the preference, an alert will be displayed if a non-empty
value is assigned to a site, organization, project, or program container context. A
non-empty value assigned to a site or organization container would force the value
to each child container and could inadvertently expose material. A non-empty
value assigned to a project or program has no effect and without an alert, a user
could be confused at the unexpected result. An example alert is shown below:

Deploying Arbortext Customizations 1927


Listing Objects Available for Anonymous Access
You can generate list of objects that are available through the anonymous access
functionality. This can help you determine if any objects have been exposed by
mistake and can assist you in providing the HTTP URL for each object.
Generating the list of objects available through anonymous access is restricted to
users with administrator access.
To generate a list of objects being shared anonymously:
1. Open a Windchill Shell. See Windchill Shell on page 180 for more
information.
2. cd bin
3. ant -f anonymousAccess.xml listAvailableResources
4. Enter your administrator credentials.

Sample Output for Available Items


The output contains an entry for each document accessible via anonymous access
and each entry lists the organization, container (product or library), and folder
containing the document as well as the document name and a skeleton of a URL
which can be used to access the document anonymously.
********************************************************************************
!+! STARTED @ Fri Oct 14 13:28:10 EDT 2011
********************************************************************************
Log file is '<Windchill>\Windchill\buildlogs\0000-anonymousAccess.log'

--------------------------------------------------------------------------------
!+! ENTERING Anonymous Access
--------------------------------------------------------------------------------

listAvailableResources:
[echo] ------------------------------------------------------------------
[echo] The following is a list of documents in Windchill that are exposed
[echo] to anonymous http access. Each entry lists the Organization,
[echo] Product or Library, and Name of the document as well as the Url
[echo] used to access it.
[echo] ------------------------------------------------------------------
[java]
[java] Organization: Demo Organization
[java] Library: New Library
[java] Folder: /Shared Folder
[java] Document: Lib Item 1
[java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/
com.ptc.arbortext.windchill.anonymous.AnonymousAccessDownloader/lib/
Demo%20Organization/New%20Library/Lib%20Item%201
[java]
[java]
[java] --------------------------------------------------------------------
[java]

1928 Customization Guide


[java] Organization: Demo Organization
[java] Product: GOLF_CART
[java] Folder: /Apps
[java] Document: Thing1
[java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/
com.ptc.arbortext.
windchill.anonymous.AnonymousAccessDownloader/product/Demo%20Organization/
GOLF_CART/Thing1
[java]
[java] -------------------------------------------------------------
[java]
[java] Organization: Demo Organization
[java] Product: GOLF_CART
[java] Folder: /Apps
[java] Document: Thing 2
[java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/
com.ptc.arbortext.
windchill.anonymous.AnonymousAccessDownloader/product/
Demo%20Organization/GOLF_CART/Thing%202
[java]
[echo] ------------------------------------------------------------------
[echo] Example:
[echo] http://MyServerName/Windchill/servlet/WindchillGW/
com.ptc.arbortext.
windchill.anonymous.AnonymousAccessDownloader/lib/ExampleOrganization/
ExampleLibraryName/ExampleDocName
[echo] ------------------------------------------------------------------
********************************************************************************
!+! FINISHED @Fri Oct 14 13:28:19 EDT 2011
!+! Log: <Windchill>\Windchill\buildlogs\0000-anonymousAccess.log
********************************************************************************

BUILD SUCCESSFUL
Total time: 9 seconds
Note that the example URLs do not contain actual hostname and web-app
values because these values are unavailable through the command line interface.
The URLs displayed are quite long and break across lines in the command
prompt. Viewing the log file referred to at the beginning of the listing is an easier
way of viewing the output.
This list includes all document objects being shared throughout your Windchill
installation, including all products and libraries in all organizations.

Sample Output for no Available Items


There are three cases where no objects are exposed:

Deploying Arbortext Customizations 1929


1. The Customizations Folder preference has been set to an empty value and
locked at the site level.
2. No folders are exposed anonymously.
3. At least one folder is exposed anonymously, but it contains no WTDocument
objects.
If no documents are currently being shared using the anonymous access
functionality, the following output is generated:

********************************************************************************
!+! STARTED @ Fri Oct 14 14:19:59 CDT 2011
********************************************************************************
Created log dir <Windchill>\Windchill\buildlogs'

--------------------------------------------------------------------------------
!+! ENTERING Anonymous Access[<Windchill>\Windchill\bin\anonymousAccess.xml]
--------------------------------------------------------------------------------

listAvailableResources:
[echo] ------------------------------------------------------------------
[echo] The following is a list of documents in Windchill that are exposed
[echo] to anonymous http access. Each entry lists the Organization,
[echo] Product or Library, and Name of the document as well as the Url
[echo] used to access it.
[echo] ------------------------------------------------------------------
[java]
[java] No shared documents found.
[java]
[echo] ------------------------------------------------------------------
[echo] Example:
[echo] http://MyServerName/Windchill/servlet/WindchillGW/com.ptc.arbortext.
windchill.anonymous.AnonymousAccessDownloader/lib/ExampleOrganization/
ExampleLibraryName/ExampleDocName
[echo] ------------------------------------------------------------------
********************************************************************************
!+! FINISHED @ Fri Oct 14 14:20:23 CDT 2011
!+! Log: <Windchill>\Windchill\buildlogs\0000-anonymousAccess.log
********************************************************************************

BUILD SUCCESSFUL
Total time: 24 seconds

1930 Customization Guide


46
Customizing Configuration
Specifications
Customizing Logic to Determine the Default Configuration Specifications .................. 1932

This section contains information on customizing configuration specifications.

1931
Customizing Logic to Determine the
Default Configuration Specifications
You can develop customized logic to determine the default configuration
specification used by various applications. For example, this could be used to
implement custom logic that will be used to create a default configuration
specification for when adding objects to a Work Package.
WTDocumentGetConfigSpecForDelegate2 is the delegate that is used by
{@link
ConfigService#getConfigSpecFor(NavCriteriaContext)} to
create the list of ConfigSpec. The delegate is looked up using service name
= wt.vc.config.GetConfigSpecForDelegate and requestor =
{@link NavCriteriaContext#getApplicableType()} and
optional selector = {@link
NavCriteriaContext#getApplicationName()}.
The delegate can be registered with or without selector but the system will give
precedence to a delegate registered with a selector that matches the {@link
NavCriteriaContext#getApplicationName()}.
To create a custom delegate, extend one of the classes {@link
wt.part.WTPartGetConfigSpecForDelegate}, {@link
wt.doc.WTDocumentGetConfigSpecForDelegate}, or {@link
wt.epm.EPMDocGetConfigSpecForDelegate}. Then register that
delegate using the xconfmanager with the service name, selector, and requestor as
defined above.

Note
For more information on the xconfmanager, see Using the xconfmanager
Utility

Please refer to Javadoc for more information about the delegates.

1932 Customization Guide


I
Identified Business
Classes
Identity Attributes
Identity attributes are the attributes of an object that, as a whole, distinguish it to
the user from other objects. The designer of a class must decide which attributes
compose its identity. For example, a SubFolder is identified by its name and its
parent folder. A WTPart’s identity attributes include number and name. For
classes that are uniquely identified, at least one of the identity attributes of the
class must have a uniqueness constraint in order to distinguish between different
instances of the class.

Note
For more information on Java Annotations see Modeling Business Objects on
page 1944.

Permissions to Modify Identity


Business object attributes are modelled with the "Changeble" property set to
"ViaOtherMeans" to prevent use of the attribute's setter after the object is
persisted; this enforces use of a service (such as the Identity Service) for changing
these attributes. A separate use of the "Changeable" property- on the attributes
of the wt.fc.IdentificationObject, not the business object- will
identify attributes which can be edited only by users possessing the MODIFY_
IDENTITY permission.
If an attribute of a wt.fc.IdentificationObject is modelled with the
"Changeable" property set to "ViaOtherMeans", the Identity Service will
consider that attribute part of the identity, and will require that the user have

1934 Customization Guide


MODIFY_IDENTITY permission to change that attribute. The Identity Service
will require MODIFY permission to change attributes whose models do not have
the "Changeable" property set to "ViaOtherMeans". Attributes which are
modelled as "Changeable Via Other Means" on the business object, but are not so
modelled on the IdentificationObject, will not be protected by the
MODIFY_IDENTITY permission.

Note
See the Javadoc for
com.ptc.windchill.annotations.metadata.Changeable.

Identified Business Classes 1935


1937
47
Identified Business Classes
Identity Attributes
Identity attributes are the attributes of an object that, as a whole, distinguish it to
the user from other objects. The designer of a class must decide which attributes
compose its identity. For example, a SubFolder is identified by its name and its
parent folder. A WTPart’s identity attributes include number and name. For
classes that are uniquely identified, at least one of the identity attributes of the
class must have a uniqueness constraint in order to distinguish between different
instances of the class.

Note
For more information on Java Annotations see Modeling Business Objects on
page 1944.

Permissions to Modify Identity


Business object attributes are modelled with the "Changeble" property set to
"ViaOtherMeans" to prevent use of the attribute's setter after the object is
persisted; this enforces use of a service (such as the Identity Service) for changing
these attributes. A separate use of the "Changeable" property- on the attributes
of the wt.fc.IdentificationObject, not the business object- will
identify attributes which can be edited only by users possessing the MODIFY_
IDENTITY permission.
If an attribute of a wt.fc.IdentificationObject is modelled with the
"Changeable" property set to "ViaOtherMeans", the Identity Service will
consider that attribute part of the identity, and will require that the user have
MODIFY_IDENTITY permission to change that attribute. The Identity Service
will require MODIFY permission to change attributes whose models do not have

1938 Customization Guide


the "Changeable" property set to "ViaOtherMeans". Attributes which are
modelled as "Changeable Via Other Means" on the business object, but are not so
modelled on the IdentificationObject, will not be protected by the
MODIFY_IDENTITY permission.

Note
See the Javadoc for
com.ptc.windchill.annotations.metadata.Changeable.

Identified Business Classes 1939


48
Services and Infrastructure
Customization
Modeling Business Objects .................................................................................... 1944
Creating New Tablespaces..................................................................................... 1971
The EnumeratedType Class ................................................................................... 1974
Creating an EnumeratedType Subclass .................................................................. 1976
Editing the Resource Info for an Enumerated Type................................................... 1977
Localizing an Enumerated Type.............................................................................. 1979
Extending an Enumerated Type.............................................................................. 1980
The Enumerated Type Customization Utility ............................................................ 1981
GUI Usage of an Enumerated Type ........................................................................ 1983
External Enumerated Value Lists ............................................................................ 1984
Customizing LDAP Mapped Attributes in a User Information Page ............................ 1994
Customizing LDAP Mapped Attributes in a Group Information Page .......................... 1997
Creating a System Configuration Collector Plugin .................................................... 2002
Customizing Column Lengths................................................................................. 2052
The Object Reference Design Pattern ..................................................................... 2056
The Business Service Design Pattern ..................................................................... 2058
The Master-iteration Design Pattern........................................................................ 2061
Background .......................................................................................................... 2064
The Windchill Approach ......................................................................................... 2065
Localizing Text Visible to the User........................................................................... 2067
Resource Info (.rbInfo) Files ................................................................................... 2071
Enterprise Abstractions.......................................................................................... 2076
Document Abstractions.......................................................................................... 2083
Part Abstractions................................................................................................... 2086
Change Abstractions ............................................................................................. 2093
Persistence Datastore Sequence Customization...................................................... 2108
QuerySpec ........................................................................................................... 2114
SearchCondition ................................................................................................... 2122
How to Write an IX Application................................................................................ 2130

1941
How to Write Exp/Imp Handlers .............................................................................. 2146
Navigating Through an Object’s Structure with ObjectSet Application ........................ 2160
Product Design eXchange (PDX) Support for Export ................................................ 2181
Adding Export Functionality in the Project Plan Table ............................................... 2188
Background Information......................................................................................... 2193
General Externalization Guidelines ......................................................................... 2193
Hand-coded Externalization Guidelines................................................................... 2195
Migration Guidelines for Classes with Hand-coded Externalization ............................ 2196
Examples of Generated Externalization Code for Evolvable Classes ......................... 2197
Modeling Large Objects ......................................................................................... 2204
Adding and Updating Data Formats for Content Holders........................................... 2210

This section contains information on customizations related to the technical


infrastructure of your Windchill system.

1942 Customization Guide


49
System Generation
Modeling Business Objects .................................................................................... 1944
Creating New Tablespaces..................................................................................... 1971

This chapter describes the details of modeling business objects.

Note
As of release 10.0 Windchill no longer uses Rational Rose for modeling.

1943
Modeling Business Objects

Note
Code examples in this chapter have been reformatted for presentation purposes
and, therefore, may contain line number, hidden editing characters (such as
tabs and end-of-line characters) and extraneous spaces. If you cut and paste
code from this manual, check for these characters and remove them before
attempting to use the example in your application.

Overview of Windchill Persistence


The Windchill persistence architecture maps Java classes and fields to database
rows and columns (schema). Modeling, the manner in which schema is described,
consists of annotating the class declarations of Java source files with PTC
“GenAs” annotations that include annotation members for describing properties,
associations, and other meta-data.
Java annotation processors are invoked during javac compilation and are
responsible for generating fields, accessors, RMI and PDS externalization APIs,
and other methods (such as equals() and hashCode()). SQL scripts
representing the database schema (tables, columns, and indexes) are generated
separately post-compilation.
The Java compiler not only generates and compiles the necessary artifacts to
implement the model as declared by the annotations, it also produces information
required at runtime to introspect on the model. It registers classes
(modelRegistry.properties), associations
(associationRegistry.properties), and their hierarchy
(descendentRegistry.properties) and produces ClassInfo files
which are utilized by runtime introspection.

Jython
Jython is a Java implementation of the popular Python programming language.
Jython is used in this chapter to provide working code that demonstrates the
examples in “real world” scenarios. Jython’s dynamic nature makes it particularly
attractive (over Java programs) because its interpreter facilitates interaction and
exploration that simply is not possible with compiled code and a debugger.
Additionally, while Jython is a Python implementation (on top of Java), the syntax
is readily familiar to Java programmers and instantly translatable.

1944 Customization Guide


Jython can be obtained from http://jython.org.

Note
The examples using Jython assume a Windchill CLASSPATH, which is
readily available if run from inside a Windchill shell (which can be started by
invoking <load point>/Windchill/bin shell).

Modeling Tables
Modeled class anatomy (GenAsPersistable)
To begin with, here is a simple, functional example. Other sections within this
chapter will refer back to this example.
Listing 1: SimpleExample.java
01 package com.acme.example;
02
03 import wt.fc.InvalidAttributeException;
04 import wt.fc.WTObject;
05 import wt.inf.container.WTContained;
06 import wt.util.WTException;
07 import wt.util.WTPropertyVetoException;
08
09 import com.ptc.windchill.annotations.metadata.*;
10
11 @GenAsPersistable(superClass=WTObject.class,
interfaces={WTContained.class},
12 properties={
13 @GeneratedProperty(name="name", type=String.class,
14 constraints=@PropertyConstraints(required=true))
15 })
16 public class SimpleExample extends _SimpleExample {
17 static final long serialVersionUID = 1;
18
19 public static SimpleExample newSimpleExample() throws WTException {
20 final SimpleExample instance = new SimpleExample();
21 instance.initialize();
22 return instance;
23 }
24
25 @Override
26 public void checkAttributes() throws InvalidAttributeException {
27 super.checkAttributes();
28 try {
29 nameValidate(name);
30 } catch (WTPropertyVetoException wtpve) {

System Generation 1945


31 throw new InvalidAttributeException(wtpve);
32 }
33 }
34 }
A class, SimpleExample (line 16) is defined which extends
_SimpleExample. The class is annotated by the GenAsPersistable
annotation (lines 11-15), which indicates that this class is to be persisted as a table
in the database. The class has a single property called “name” (lines 13–14)
which is a (required) String. Additionally, two methods have been implemented; a
static factory method (lines 19-23) and an override of the
checkAttributes() method (lines 25-33).
The source of the _SimpleExample is as follows:
• The annotation processor for the GenAsPersistable annotation generates
the parent class (more precisely , it generates a source file which the compiler
then compiles).
• The parent class provides an implementation (query constant, field, getter,
setter, and setter validation) for the “name” property as well as externalization
logic and other needed methods.
The “_” class consists of the fields and methods shown in Listing 2.
Listing 2: _SimpleExample javap results
01 public abstract class com.acme.example._SimpleExample extends wt.fc.WTObject
implements wt.inf.container.WTContained,java.io.Externalizable{
02 static final long serialVersionUID;
03 static final java.lang.String RESOURCE;
04 static final java.lang.String CLASSNAME;
05 public static final java.lang.String NAME;
06 static int NAME_UPPER_LIMIT;
07 java.lang.String name;
08 wt.inf.container.WTContainerRef containerReference;
09 public static final long EXTERNALIZATION_VERSION_UID;
10 public com.acme.example._SimpleExample();
11 public java.lang.String getName();
12 public void setName(java.lang.String) throws
wt.util.WTPropertyVetoException;
13 void nameValidate(java.lang.String) throws
wt.util.WTPropertyVetoException;
14 public java.lang.String getContainerName();
15 public wt.inf.container.WTContainer getContainer();
16 public wt.inf.container.WTContainerRef getContainerReference();
17 public void setContainer(wt.inf.container.WTContainer) throws
wt.util.WTPropertyVetoException, wt.util.WTException;
18 public void setContainerReference(wt.inf.container.WTContainerRef) throws
wt.util.WTPropertyVetoException;

1946 Customization Guide


19 void containerReferenceValidate(wt.inf.container.WTContainerRef) throws
wt.util.WTPropertyVetoException;
20 public java.lang.String getConceptualClassname();
21 public wt.introspection.ClassInfo getClassInfo() throws
wt.introspection.WTIntrospectionException;
22 public java.lang.String getType();
23 public void writeExternal(java.io.ObjectOutput) throws
java.io.IOException;
24 protected void super_writeExternal_SimpleExample(java.io.ObjectOutput) throws
java.io.IOException;
25 public void readExternal(java.io.ObjectInput) throws
java.io.IOException, java.lang.ClassNotFoundException;
26 protected void super_readExternal_SimpleExample(java.io.ObjectInput) throws
java.io.IOException, java.lang.ClassNotFoundException;
27 public void writeExternal(wt.pds.PersistentStoreIfc) throws
java.sql.SQLException, wt.pom.DatastoreException;
28 public void readExternal(wt.pds.PersistentRetrieveIfc) throws
java.sql.SQLException, wt.pom.DatastoreException;
29 boolean readVersion6009937787959182077L(java.io.ObjectInput, long, boolean)
throws java.io.IOException, java.lang.ClassNotFoundException;
30 protected boolean readVersion(com.acme.example.SimpleExample,
java.io.ObjectInput,
long, boolean, boolean) throws java.io.IOException,
java.lang.ClassNotFoundException;
31 protected boolean super_readVersion_
SimpleExample
(com.acme.example._SimpleExample,
java.io.ObjectInput, long, boolean, boolean) throws
java.io.IOException, java.lang.ClassNotFoundException;
32 boolean readOldVersion(java.io.ObjectInput, long, boolean, boolean) throws
java.io.IOException, java.lang.ClassNotFoundException;
33 static {};
34 }

The annotation consists of a declaration that is then implemented by the compiler.


Rather than implement all aspects of “name” manually, it is declared as a property
within the annotation and the “_” parent file implements all the necessary
components. Listing 3 contains an example of the effect required=true has
on the nameValidate() method.
Listing 3: nameValidate() snippet
01 if (name == null || name.trim().length() == 0)
02 throw new wt.util.WTPropertyVetoException("wt.fc.fcResource",
wt.fc.fcResource.REQUIRED_ATTRIBUTE,
03 new Object[] { new wt.introspection.PropertyDisplayName
(CLASSNAME, "name") },
04 new java.beans.PropertyChangeEvent(this, "name",
this.name, name));

System Generation 1947


The purpose of superClass and interfaces (line 11, listing 1) is as
follows:
• The superClass annotation member is simple; extends was co-opted by
the “_” class so modeled elements could be generated into code and
incorporated into the class. Consequently, superClass is needed to allow
you to specify your “true” (logical) parent (in this case, WTObject), which
the “_” class (_SimpleExample) then extends for you (as seen above).
• The interfaces annotation member exists for a similar purpose: to make it
possible to identify the interfaces you wish to implement. While
implements was not similarly co-opted, various technical considerations
made an annotation member the logical choice over utilizing implements
directly. This example extends WTObject and implements WTContained.
The compiler will enforce the “public class <X> extends _<X> { ...
} ” syntax and generates a compile error if this syntax is not used.
Note the use of the factory pattern (newSimpleExample() (line 19 of Listing
1). Windchill utilizes this pattern over constructors because externalization needs
to construct an instance using the noarg constructor and calling it should be
inexpensive. The factory pattern consists of a static method of the form “public
static <X> new<X>(<args...>) throws WTException { ... }” and
should be used in place of constructors in annotated files. The body of the factory
should follow the form demonstrated by the example. Specifically, it should:
1. Construct an instance of the class using its (default) no-arg constructor.
2. Call the (non-static) initialize method, passing the arguments provided
to the static method. The static factory should never handle the arguments on
its own because then no subclass could take advantage of the static method’s
work (this is the primary purpose of the initialize methods: to make it
possible to inherit behavior). You may need to create your own initialize
method (if one does not exist or you need to augment behavior), in which case
it should be of the form protected void initialize(args...)
throws WTException and should call super.initialize(...).
3. Return the instance.
The following factory/initialize pair demonstrates the proper way one would add a
factory method accepting name so as to assign the required property.
Listing 4: Factory/initialize pair example
01 public static SimpleExample newSimpleExample(final String name)
throws WTException {
02 final SimpleExample instance = new SimpleExample();
03 instance.initialize(name);
04 return instance;
05 }
06
07 protected void initialize(final String name) throws WTException {
08 super.initialize();
09 try {

1948 Customization Guide


10 setName(name);
11 } catch (WTPropertyVetoException wtpve) {
12 throw new WTException(wtpve);
13 }
14 }
Additionally, the serialVersionUID (line 17 of Listing 1) is necessary since
Windchill manages externalization logic (including, as needed, old version
deserialization) and system-assigned serial version UIDs would break this logic.
As before, the compiler will generate a compile error if this is not provided.
Finally, checkAttributes() is notable only in that it demonstrates the use of
generated fields and methods (line 29, Listing 1). In particular, name and
nameValidate() are generated with default access specifically to make them
accessible to the annotated class.

Compilation
Compilation is covered extensively in the JavaDoc for the
com.ptc.windchill.annotations.metadata package. However, the
SimpleExample customization can be compiled and incorporated by executing
the following steps:
1. cd to your load point (for example, /opt/ptc/Windchill)
2. Start a Windchill shell by invoking bin/windchill shell
3. Create the src/com/acme/example directory via mkdir -p src/com/
acme/example
4. Create SimpleExample.java in this directory and give it the contents of
the example above
5. Compile the example with ant -f bin/tools.xml class
-Dclass.includes=com/acme/example/* (note that this command
must be executed in the load point directory)
6. Generate SQL scripts with ant -f bin/tools.xml sql_script
-Dgen.input=com.acme.example.*
7. Find the create_SimpleExample_Table.sql SQL script (it will be
somewhere in db) and load it
8. Repeat for create_SimpleExample_Index.sql.
9. Start/restart the MethodServer
Jython can be used to quickly validate the example, as shown in Listing 5.
Listing 5: Persisting SimpleExample
01 from wt.fc import PersistenceHelper
02 from com.acme.example import SimpleExample
03
04 se = SimpleExample.newSimpleExample()

System Generation 1949


05 se.setName('test')
06 se = PersistenceHelper.manager.store(se)
When prompted, authenticate as the system administrator. The object will be
created in the site container, which can be confirmed via
sn.getContainer().getName(). Note that, had we created the factory/
initialize methods with name as an argument, we could have avoided calling
setName(’test’) separately.

Mapping classes to tables and columns


The example persisted an instance of SimpleExample, resulting in the addition
of a row in a table. Details of the table are shown in Listing 6.
Listing 6: create_SimpleExample_Table.sql
01 exec WTPK.dropTable('SimpleExample')
02 set echo on
03 REM Creating table SimpleExample for com.acme.example.SimpleExample
04 set echo off
05 CREATE TABLE SimpleExample (
06 classnamekeycontainerReferen VARCHAR2(600),
07 idA3containerReference NUMBER,
08 name VARCHAR2(600) NOT NULL,
09 createStampA2 DATE,
10 markForDeleteA2 NUMBER NOT NULL,
11 modifyStampA2 DATE,
12 classnameA2A2 VARCHAR2(600),
13 idA2A2 NUMBER NOT NULL,
14 updateCountA2 NUMBER,
15 updateStampA2 DATE,
16 CONSTRAINT PK_SimpleExample PRIMARY KEY (idA2A2))
17 STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 )
18 ENABLE PRIMARY KEY USING INDEX
19 TABLESPACE INDX
20 STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 )
21 /
22 COMMENT ON TABLE SimpleExample IS 'Table SimpleExample created for
com.acme.example.SimpleExample'
23 /
24 REM @//com/acme/example/SimpleExample_UserAdditions
The table’s name reflects the name of the class (this can be changed – see the
JavaDoc for the annotation member “tableProperties” and the associated
member “tableName” for details). Of the columns, “name” is certainly
recognizable, though the rest may not be. The
classnamekeycontainerReferen and idA3containerReference
columns are necessary to store the reference to the container, which we got by
being WTContained. Everything else comes from being Persistable, which
is the top-level interface for persisting Windchill classes as tables.

1950 Customization Guide


Modeled associations (GenAsBinaryLink)
GenAsPersistable is one of two annotations for mapping classes to tables.
The other is GenAsBinaryLink, which represents an association, linking two
persistent objects (rows in two tables) together. Each binary link consists of two
roles, an “A” role and a “B” role.
We can create a graph of SimpleExamples, in which a SimpleExample may
have multiple parents and children.
Listing 7: SimpleExampleLink.java
01 package com.acme.example;
02
03 import wt.fc.ObjectToObjectLink;
04 import wt.util.WTException;
05
06 import com.ptc.windchill.annotations.metadata.*;
07
08 @GenAsBinaryLink(superClass=ObjectToObjectLink.class,
09 roleA=@GeneratedRole(name="parent", type=SimpleExample.class),
10 roleB=@GeneratedRole(name="child", type=SimpleExample.class))
11 public class SimpleExampleLink extends _SimpleExampleLink {
12 static final long serialVersionUID = 1;
13
14 public static SimpleExampleLink newSimpleExampleLink
(final SimpleExample parent, final SimpleExample child)
throws WTException {
15 final SimpleExampleLink instance = new SimpleExampleLink();
16 instance.initialize(parent, child);
17 return instance;
18 }
19 }
After similarly compiling it, it can be validated with Jython, as shown in Listing 8.
Listing 8: Persisting SimpleExampleLink
01 from wt.fc import PersistenceHelper
02 from com.acme.example import *
03
04 parent = SimpleExample.newSimpleExample()
05 parent.setName('parent')
06 parent = PersistenceHelper.manager.store(parent)
07
08 child = SimpleExample.newSimpleExample()
09 child.setName('child')
10 child = PersistenceHelper.manager.store(child)
11
12 l = PersistenceHelper.manager.store(SimpleExampleLink.
newSimpleExampleLink (parent, child))

System Generation 1951


As with SimpleExample, we have a factory method (lines 14-17). Links,
however, always associate two objects, so the factory method (and associated
initialize method) accepts the A/B roles as arguments.

Modeling Columns
Modeling Columns
GenAsPersistable and GenAsBinaryLink provide three mechanisms for
specifying database columns:
1. properties (an array of GeneratedPropertys) represent strings,
numbers, booleans, etc.
2. foreignKeys (an array of GeneratedForeignKeys) reference other
persistent objects (and are stored as a classname/key pair)
3. roleA/roleB (GenAsBinaryLink only) are a special form of a foreign
key used in associations
Additionally derivedProperties (an array of DerivedPropertys)
provide convenience accessors to properties and foreign keys.
It is sometimes useful to collect a set of properties together into its own class
which can then be managed as an entity and aggregated into a persistent object.
The GenAsObjectMappable annotation exists for this purpose and is widely
utilized by Windchill “cookies”. When a GenAsObjectMappable-annotated
class is specified as the type for a GeneratedProperty, all its properties
become columns in the owning class’s table. To prevent name-collisions, the
names are “mangled” using a character/number pattern dictated by an arcane
algorithm; it is this mangling that accounts for the “idA3” in
idA3containerReference and the mapping of
Persistable.thePersistInfo.theObjectIdentifier.id to
idA2A2.

GeneratedProperty
An example of GeneratedProperty in our SimpleExample (name, which
is required and of type String) has already been shown.
GeneratedProperty supports a number of annotation members for
controlling generation and behavior. See the Windchill JavaDoc for more
information.

GeneratedForeignKey
A foreign key was not modeled, it was inherited from WTContained.
Listing 9: container definition snippet
01 @GeneratedForeignKey(name="ContainerLink",
02 foreignKeyRole=@ForeignKeyRole(name="container",
type=wt.inf.container.WTContainer.class, referenceType=wt.inf.

1952 Customization Guide


container.WTContainerRef.class, supportedAPI=SupportedAPI.PRIVATE,
03 constraints=@PropertyConstraints(required=true)),
04 myRole=@MyRole(name="contents", supportedAPI=SupportedAPI.PRIVATE))
The impact of the container reference had on SimpleExample’s schema is that
it resulted in two columns (previously discussed). In fact, if we peel this back
further, we can see that we got these fields from WTContainerRef – a
GenAsObjectMappable – by way of ObjectReference. We can say that a
foreign key is “simply” another property (and, in fact, you could model a property
with a type of ObjectReference as the type and accomplish the “same”
results (from the perspective of the columns that would be created)), however the
Windchill persistence layer recognizes foreign keys as a type of association and
can manage them for you. In particular:
• you can prevent the foreignKeyRole object from being deleted (when it
participates in your assocation) by setting owner=false
• you can cause the myRole object to be deleted when the foreignKeyRole
object is deleted by setting cascade=true
• when cascade=false (the default value) and foreignKeyRole role is
deleted, the reference held by myRole will automatically be cleared
• you get accessors for both the reference and the referenced object generated
for you
• you can automatically retrieve the referenced object (when required=
true) by setting autoNavigate=true, preventing an additional database
hit when accessing the referenced object
• you can navigate the foreign key link just as you would any other binary link.
The GeneratedForeignKey is used when a given persistable is associated to
at most one other persistent object. It is preferable to utilize
GeneratedForeignKey over a GeneratedProperty of some concrete
subtype of WTReference because the former makes it possible for the
Windchill persistence architecture to manage the reference as an association.
However, there are exceptions to this. In particular, associations to
WTPrincipals (users) should be modeled as GeneratedPropertys of type
WTPrincipalReference rather than as GeneratedForeignKeys. This is
because we don’t need the association management (users can’t be deleted) and
because we only want accessors for the reference (which contains everything
anyone should ever need to know about users).

System Generation 1953


Note
Just as with GeneratedRoles, you can constrain an existing foreign key
(modeled on a parent class/interface), as is commonly done to constrain an
iteration’s master. When constraining a foreign key, you need only provide the
values that are different from that of the foreign key you’re inheriting from;
you needn’t faithfully re-specify all of the properties of your parent.

GeneratedRole
The GeneratedRole annotation is used to describe the role A and B of a
GenAsBinaryLink, which we saw earlier in SimpleExampleLink. Roles
can be thought of as special foreign keys associating the link with two persistables
(and have the same inheritance capabilities as foreign keys). Whereas foreign keys
are applicable only when the cardinality of the associated role is 0-1 and where the
association requires no additional data (properties), binary links are applicable
when the association is many-to-many, when the association carries properties, or
when the association would otherwise be persisted on a PTC business object
(since you cannot alter existing PTC classes).

DerivedProperties
Derived properties aren’t themselves persisted, but they do provide convenience
accessors (getters, setters, and query constants) to persisted properties that would
otherwise be buried in cookies or across foreign key references. Let’s say you
have a field c which is buried inside a cookie b which is itself buried inside a
cookie a which is a property of our current class.
We could access it using this.getA().getB().getC(), being careful to
handle possible NullPointerExceptions should the cookies not be
initialized. Better yet, we could just add this derived property to our class and let
everything (including the handling of NullPointerException) be handled
for us.
Listing 10: a.b.c derived property
@DerivedProperty(name="c", derivedFrom="a.b.c")

With this derived property, we can now simply call this.getC().


If you need to cross a foreign key to access a field in the associated object, use the
“>” delimiter after the foreign key’s name in place of “.”. To directly access the
name of the associated master, WTPart relies on the following derived
property:
Listing 11: master>name derived property
@DerivedProperty (name="name " , derivedFrom="master>name " )

1954 Customization Guide


System Generation 1955
Specialized Persistence Constructs
GenAsUnPersistable “tables”
All classes recognized as being mapped to database tables must extend
wt.fc.Persistable. The GenAsPersistable-generated “_” class
automatically handles this for you; the GenAsBinaryLink-generated “_” class
achieves this by implementing wt.fc.BinaryLink, which extends
Persistable.
When modeling interfaces to be implemented by persistent classes, you will
typically use these annotations to describe the columns (properties, foreign keys,
and roles) you’ll ultimately want the implementing (concrete) classes to represent
as columns. Windchill’s domain interfaces employ this strategy, allowing you to
simply implement a bunch of interfaces to acquire important business logic like
work-in-progress (Workable) lifecycle management (LifeCycleManaged),
and so on.
You must annotate an interface if you want implementing classes to
(automatically) persist the interface’s properties. However, not every interface is
always intended to be implemented only by persistent classes. In some (exceeding
rare) cases, an interface may be implemented by persistent classes (necessitating
that the interface be annotated so its data can be persisted) and by non-persistent
classes (for which GenAsPersistable and GenAsBinaryLink’s ensuring
that the class ends up being Persistable is a problem). In these cases, you can
use the GenAsUnPersistable annotation to bridge the gap: any persistent
implementer will automatically treat the interface as though it were persistent,
while non-persistent implementers won’t get persistence foisted on them.
It should be noted that you’ll likely want your non-persistent classes to be
annotated with GenAsUnPersistable to get the same generation benefits as
its persistent cousins do, but this is not necessary. Additionally, since
externalization logic comes “for free”, you may wish to utilize this annotation in
cases where the class is to be “persisted” as a BLOB , since RMI externalization is
employed when blobbing instances. Here, “persisted as a BLOB” means that the
entire class will be stored in a BLOB column inside a persisted class’s table.
BLOBing an object is almost never recommended because it’s easy to overlook
the complexities of reading the BLOB back out, especially if the class has
changed since the instance was put in. Note that if you wish to store as a BLOB
any class implementing wt.fc.NetFactor, you must make that class
wt.util.Evolvable.

GenAsEnueratedType columns
Windchill provides support for modeling a discrete, localizable set of strings. Let’s
say you want to store computer models in Windchill and wanted to categorize
them as being either a desktop, laptop, or server. You could do this as
follows:

1956 Customization Guide


Listing 12: ComputerType.java
01 package com.acme.example;
02
03 import com.ptc.windchill.annotations.metadata.*;
04
05 @GenAsEnumeratedType
06 public class ComputerType extends _ComputerType {
07 public static final ComputerType DESKTOP = toComputerType("desktop");
08 public static final ComputerType LAPTOP = toComputerType("laptop");
09 public static final ComputerType SERVER = toComputerType("server");
10 }

Listing 13: ComputerTypeRB.rbInfo


01 ResourceInfo.class=wt.tools.resource.EnumResourceInfo
02
03 desktop.value=Desktop
04 desktop.order=10
05
06 laptop.value=Laptop
07 laptop.order=20
08 laptop.defaultValue=true
09
10 server.value=Server
11 server.order=30

You can incorporate this into your Computer class using a


GeneratedProperty as follows:
Listing 14: Computer type snippet
01 @GeneratedProperty(name="type", type=ComputerType.class,
initialValue="ComputerType.getComputerTypeDefault()",
02 constraints=@PropertyConstraints(upperLimit=20, required=true))

The class follows the general format established previously: an annotated class
that extends it’s (generated) “_” class. Classes annotated by
GenAsEnumeratedType will ultimately extend wt.fc.EnumeratedType
and, as can be seen, a number of methods are generated for you. Among them are
to<X>(String) and get<X>Default(), where X is the name of our class
(to see a complete listing, invoke javap com.acme.example._
ComputerType).
Lines 7-9 (of Listing 12) consist of constant declarations which rely on the
toComputerType(...) API to produce instances of the enumerated type.
Note that these entries must be present in the corresponding rbInfo file, which
is named <X>RB.rbInfo and resides in the same directory. This rbInfo file is

System Generation 1957


of type ResourceInfo.class=
wt.tools.resource.EnumResourceInfo and supports both localization
and value ordering.
We incorporate this enumerated type as a GeneratedProperty. Note the use
of initialValue and the constraints: all computer models must be assigned to one of
our three types, and the default type is laptop. Enumerated types are stored (and
serialized) as simple strings (in this case, the stored value will be one of
desktop, laptop, or server). Since the default upperLimit for strings is
fairly large at 200 characters (see JavaDoc for more information), a more
reasonable limit is provided.
To build the rbInfo file, run ant -f bin/tools.xml bundle
-Dbundle.input=com.acme.example.*. The extension must be
“rbInfo”, and is case sensitive. If you neglect the uppercase “I”, the bundle
target will ignore your file.

GenAsPrimitiveType columns
If you look at the JavaDoc for wt.fc.EnumeratedType. you will see that
EnumeratedType is annotated with GenAsPrimitiveType. Also, the
single argument to the annotation is String.class.
The GenAsPrimitiveType annotation is a simple annotation, requiring a
single value: the “primitive” type the annotated class reduces to (for persistence
and serialization). You will likely never use it, but it exists when you want to build
a class (logic) around what is otherwise a pretty boring field. If you do use it, you
not only need to specify the type to reduce this class to as part of the annotation,
you also need to provide a constructor accepting the primitive type and a <type-
in-lower-case>Value() method to return the current value.
For more information, refer to the annotation’s JavaDoc.

GenAsDatastoreSequence database sequences


Windchill, out-of-the-box, will automatically assign part number and document
numbers. It does this by employing a database sequence.
Listing 15: MySequence.java
01 package com.acme.example;
02
03 import com.ptc.windchill.annotations.metadata.*;
04
05 @GenAsDatastoreSequence
06 public class MySequence extends _MySequence { }

As before, you need to generate and load the SQL (also, anytime you make a
change to an annotated class, you will need to restart the MethodServer). Once
completed, you can acquire values as demonstrated (the following example will
print “1” and “2”, assuming you’ve not already acquired sequence values):

1958 Customization Guide


Listing 16: Acquiring sequence values
01 from com.acme.example import MySequence
02 from wt.fc import PersistenceHelper
03
04 print PersistenceHelper.manager.getNextSequence(MySequence )
05 print PersistenceHelper.manager.getNextSequence(MySequence )

Note
The GenAsDatastoreSequence is one of four GenAsDatastore
annotations.

System Generation 1959


Services
Windchill services provide APIs and logic to manage modeled business objects.
They consist of:
• An (optional) helper consisting of static fields and methods, including a static
field (generally named service or manager) referring to a service
• A service interface consisting of remotely-invocable method declarations
• A standard service which implements the service and is registered to run as a
service in the Method Server.
Services are covered elsewhere in this document. However, this is the basic
pattern.
Listing 17: ExampleHelper.java
01 package com.acme.example;
02
03 import wt.services.ServiceFactory;
04
05 /** Helpers are not instantiated and should consist of only static
fields/methods **/
06 public final class ExampleHelper {
07 /** Use the ServiceFactory to acquire an instance of the service. **/
08 public static final ExampleService service = ServiceFactory.
getService(ExampleService.class);
09 }

Listing 18: ExampleService.java


01 package com.acme.example;
02
03 import wt.method.RemoteInterface;
04 import wt.util.WTException;
05
06 /** RemoteInterface annotation is required for all service interfaces **/
07 @RemoteInterface
08 public interface ExampleService {
09 /** All interface methods are callable via RMI and must
throw WTException **/
10 SimpleExample createSimpleExampleByName(final String name)
throws WTException;
11 }
Listing 19: StandardExampleService.java
01 package com.acme.example;
02
03 import wt.fc.PersistenceHelper;
04 import wt.services.StandardManager;
05 import wt.util.WTException;
06 import wt.util.WTPropertyVetoException;

1960 Customization Guide


07
08 /** service must extend StandardManager, implement service interface **/
09 public class StandardExampleService extends StandardManager implements
ExampleService {
10 /** MethodServer refectively calls this API during startup **/
11 public static StandardExampleService newStandardExampleService()
throws WTException {
12 final StandardExampleService instance = new StandardExampleService();
13 instance.initialize();
14 return instance;
15 }
16
17 @Override
18 public SimpleExample createSimpleExampleByName(final String name)
throws WTException {
19 final SimpleExample example = SimpleExample.newSimpleExample();
20 try {
21 example.setName(name);
22 }
23 catch (WTPropertyVetoException wtpve) {
24 throw new WTException(wtpve);
25 }
26 return (SimpleExample) PersistenceHelper.manager.store(example);
27 }
28 }

The service must be registered in site.xconf; the number 99999 must be


unique so as not to replace an existing service. Note that changes to
site.xconf must be propagated using xconfmanager. All customization
services must be registered in site.xconf.
Listing 20: site.xconf fragment
01 <Property name="wt.services.service.99999"
02 targetFile="codebase/wt.properties"
03 value="com.acme.training.MyService/com.acme.
training.StandardMyService"/>

With this service, we could reduce our Jython example to persist a


SimpleExample to the following:
Listing 21: Persisting SimpleExample with service
01 from com. acme . example import
02
03 se = ExampleHelper.service.createSimpleExampleByName(’test’)

System Generation 1961


Localized Text
We have already seen an example localized text; ComputerTypeRB.rbInfo
contains the (default English) text for ComputerType. Beyond providing
localized text for enumerated types, we will want to localize class and fields
names as well as messages (like exception messages).

Class and attribute names


Introspection provides APIs to get the (localized) display name for classes and
properties. Default display names are calculated when explicit values aren’t
provided, as shown by the following example which produces “Simple
Example.Name”:
Listing 22: Display values for SimpleExample
01 from wt.introspection import WTIntrospector
02 from com.acme.example import SimpleExample
03
04 snci = WTIntrospector.getClassInfo(SimpleExample)
05 print "%s.%s" % (snci.getDisplayName(), snci.getPropertyDisplayName
(snci.getPropertyDescriptor('name'), None))

Let’s say we want to display SimpleName as “Simple” and


SimpleName.name as “aka”. You can do this by creating a
MetadataResourceInfo in the same directory, as follows:
Listing 23: exampleModelRB.rbInfo
01 ResourceInfo.class=wt.tools.resource.MetadataResourceInfo
02
03 # Entry Format (values equal to default value are not included)
04 # <key>.value=
05 # <key>.category=
06 # <key>.comment=
07 # <key>.argComment<n>=
08 # <key>.constant=
09 # <key>.customizable=
10 # <key>.deprecated=
11 # <key>.abbreviatedDisplay=
12 # <key>.fullDisplay=
13 # <key>.shortDescription=
14 # <key>.longDescription=
15
16 # Entry Contents
17 SimpleExample.value=Simple
18 SimpleExample.name.value=aka

1962 Customization Guide


These bundles are similar to the bundle style used for enumerated types and are
compiled in the same manner. Once compiled, our Jython script will produce
“Simple.aka”.

Messages
Localizing class names and properties is not sufficient. Everything you wish to
communicate to users should be localized (note: a developer is not, necessarily, a
user). The rbInfo format is used for enumerated types as well as classes and
their properties. For general messages (typically included in exception or status
messages reported by services), Java source/class files ultimately extending
java.util.ListResourceBundle are utilized. As the contract for
ListResourceBundle is arcane, we’ll utilize WTListResourceBundle,
which is more declarative. An example:
Listing 24: exampleResource.java
01 package com.acme.example;
02
03 import wt.util.resource.*;
04
05 /** This example blatantly plagiarized from the JavaDoc. **/
06 @RBUUID("com.acme.example.exampleResource")
07 public class exampleResource extends WTListResourceBundle {
08 @RBEntry("This is the localized text with a single
substitution: \"{0}\".")
09 @RBComment("An example entry.")
10 @RBArgComment0("Any string...")
11 public static final String EXAMPLE_STRING = "0";
12 }

With this, we produce a message or an exception:


Listing 25: Messages utilizing exampleResource
01 from com.acme.example import exampleResource
02 from wt.util import WTException, WTMessage
03
04 print WTMessage(exampleResource.getName(), exampleResource.EXAMPLE_STRING,
['substitution']).getLocalizedMessage()
05
06 raise WTException(exampleResource.getName(), exampleResource.EXAMPLE_STRING,
['substitution'])

The first call will produce This is the localized text with a single
substitution: ‘‘substitution’’. and the second will raise (throw) an
exception with the message wt.util.WTException:
(com.acme.example.exampleResource/0)
wt.util.WTException: This is the localized text with a
single substitution: ‘‘substitution’.

System Generation 1963


For more information, refer to the JavaDoc for the wt.util.resource
package, particularly wt.util.resource.WTListResourceBundle.

1964 Customization Guide


Documenting the Model
Every (supported) class is documented as part of JavaDoc, and every (supported)
GenAs-annotated class includes the GenAs annotation in its JavaDoc. This
means that Windchill’s schema is entirely documented in JavaDoc and is available
for reference when modeling your own class. Furthermore, the annotations
themselves are included in JavaDoc (and reside in the
com.ptc.windchill.annotations.metadata package). Information
about, and example usages of annotations are readily available in JavaDoc.
JavaDoc is particularly useful for understanding how to model and for mining
Windchill’s model for examples. However, it can be difficult to determine the
associations a particular class participates in from the JavaDoc alone, as the role
members typically don’t include references to their associations in their own
JavaDoc. Information about the associations a given object participates is
available via Windchill introspection and can be accessed via two utilities.
The first utility is InfoReport. When run against a specified class in a
Windchill shell, InfoReport will generate everything that is known about the
class, including properties, database info, descendants, and, especially,
associations.
The second utility is included as part of the Windchill user interface, but is not
enabled by default. The client, when enabled, provides a navigable interface for
browsing introspection information.
To enable it:
1. Go to Site -> Utilities -> Preference Manager
2. “Find in tree” Client Customization
3. Right click, select Set Preference, and assign the value to “yes”.
4. Refresh the browser
5. Browse to the tool icon (next to Site)
6. Select Tools, then Modeled Objects

System Generation 1965


Developing with Eclipse
The examples in this chapter (and customizations similar to it) can be developed
using nothing more than a text editor for authoring and Ant for building. They can
also be developed using Eclipse (http://eclipse.org), which is an IDE
(tools.xml’s “eclipse_project.help” target will help you get started).
In particular, you will need to to install Eclipse, install the FileSync plug-in,
generate a workspace and project (via the eclipse_project target), and
configure Eclipse to use both the workspace and project. All of this is covered in
eclipse_project.help.
The generated Eclipse project is configured to work with source in <load
point>/src, just as is tools.xml. It builds into an Eclipse-managed output
directory (<load point>/eclipse_codebase) and utilizes FileSync to
propagate changes to the “real” codebase (load point/codebase), which ensures a
final result equivalent to invoking the class target. The generated project doesn’t
compile directly to <load point>/codebase because Eclipse would
otherwise obliterate it.
Eclipse supports compilation and annotation processing: whenever a source file is
saved, it is immediately compiled. Compilation includes, as necessary, invocation
of annotation processors and generation of code. Eclipse support does not extend
to building rbInfo files and generating SQL, however, requiring the continued use
of tools.xml to build those artifacts.
Eclipse users will want to utilize WTListResourceBundle and its annotations
over the old rbInfo-formatted StringResourceInfo bundles. rbInfo
files of type ResourceInfo.class=
wt.tools.resource.StringResourceInfo are the only rbInfo
format to compile to Java class files. Eclipse simply does not recognize class files
produced in this way and won’t provide completion for it (it flags usages of the
constants in these bundles as errors). The WTListResourceBundle is, by
contrast, fully compiled by Eclipse and Eclipse is fully aware of it. If you have
existing StringResourceInfo files, consider converting them using the
bundle_convert target.
The generated Eclipse workspace includes a debug configuration for debugging
the MethodServer (see the help for details). Even though Windchill does not ship
source, but you will be able to debug your own code.
The eclipse_target, notably, is fairly bereft of options. This is an intentional
restriction to ensure a working workspace/project is created. A cursory glance at
tools.xml’s targets relating to eclipse_project and the output of
eclipse_project itself will give you a good sense of what is going on and
will give you insight as to how you might tailor the results to make it more
suitable to your needs.

1966 Customization Guide


Deploying Modeled Customizations
This section documents guidelines for deploying modeled customizations. By
“deploying” in this context we mean copying the customizations from one system
to another – from a source to a destination. The process you use will depend on
the actual source and destination of the customizations.
Modeled customizations, when built, will impact the installation in three primary
ways:
1. 1. Registering modeled (annotated) classes in <loadpoint>/codebase in
the following files:
• modelRegistry.properties
• associationRegistry.properties
• descendentRegistry.properties
2. Adding compiled and generated files:
• Java Classes (*.class)
• introspection artifact files (*.ClassInfo.ser)
• serialized bundle files (*.RB.ser)
3. Updating database scripts in <loadpoint>/db to incorporate any
additional schema (including indexes)
• database files (*.sql)
Additionally, you may have added entries to site.xconf to register services.
In any case, you must:
1. Copy over the changes introduced by your customization into the destination
system (these are the files enumerated above)
2. Install the schema by invoking the SQL scripts necessary to create tables and
indexes
3. Augment the destination system’s site.xconf to incorporate the
customization’s changes (and run xconfmanager)
4. Restart the destination system

Deploying Modeled Customizations from Development to Production


One common scenario is an environment where the source is a Development
system and the destination is a Production system. In this scenario we can make
assumptions that simplify the deployment process. Most importantly, we assume
the development and production systems are essentially clones.
This section uses “Development System” to refer to the source where the
customizations are being developed. “Production System” refers to the destination
that is either currently being used by the customer for their production work, or
the new production system that is being developed as part of a new deployment,

System Generation 1967


migration or upgrade. Your environment may include other systems that need to
be maintained such as a test system or staging (pre-production) system. All the
steps described below for deploying customizations to production apply as well to
the other systems – as long as the same assumptions apply.
In this scenario we assume that the development and production systems are
clones, and that as you make changes to the development system, you can copy
them to the production system. For that reason it is important that the production
system and development system share the same fundamental state (the same
products are installed, the same patches, and all are at the same release level) or
your classes may be incompatible, your registry files may contain extraneous
entries (or drop important ones), and your database schema may be incorrect.
If these assumptions are met, then you can follow the guidelines in the following
steps:
1. Copy over the changes introduced by your customization into the production
system (these are the files enumerated above)
2. Copy over the changes introduced by your customization into the production
system.
a. Copy the follow registry files before starting customization to: C:\temp\
original_registry_files :
• associationRegistry.properties
• descendentRegistry.properties
• modelRegistry.properties
• moduleRegistry.properties
b. Create a new modeled object. See Model a New Document Subclass for
more information.
c. To create merge files for the additions and deletions inside: d:\
Windchill\temp\_model_registry run the following command
in a Windchill shell.:
ant -f bin/tools.xml registry_diff -Dregistry_
diff.basedir=C:\temp\original_registry_files
-Dregistry_diff.modsdir=D:\windchill\codebase
-Dregistry_diff.diffdir=d:\Windchill\temp\_model_
registry
d. Copy the _model_registry folder to the new Windchill target system
and paste it in d:\Windchill\temp
e. Run the following command in a Windchill shell on the new target system:
ant -f bin/tools.xml registry_merge -Dregistry_
merge.adds=D:\Windchill\temp\_model_registry\reg_

1968 Customization Guide


adds -Dregistry_merge.removes=D:\Windchill\temp\_
model_registry\reg_removes
3. Install the schema by invoking the necessary SQL scripts to create tables and
indexes
4. Augment the production system’s site.xconf to incorporate the customization’s
changes (and run xconfmanager)
5. Restart the production system.

Additional Strategies for Deploying Modeled Customizations


Deploying your customization from your source to your destination entails
replaying your actions in the source environment on the destination system. One
strategy would be to simply copy over the source and rebuild it on the destination
system. This strategy, however, necessitates compiling on the destination system,
but if that is your production system then that is probably not acceptable.
Another strategy is to use a version control system, like Git or Subversion, putting
your entire load point under it, allowing the version control system to tell you how
your customization impacted the installation, and merge over the changes.

Merging Modeled Customizations


If the destination system includes customizations that are not part of the source
system you are deploying, you will need to create incremental registry files that
can be merged into the registry files in the destination system. The registry_
diff target can be run against the source system files to produce the incremental
files to merge into the destination system with the registry_merge target.
The registry_diff target can be run from the Windchill shell of either
system, as long it has access to the required folders, described below.
ant -f <loadpoint>/bin/tools.xml registry_diff -Dregistry_diff.basedir=/wt_dev/base
-Dregistry_diff.modsdir=/wt_dev/codebase -Dregistry_diff.diffdir=/wt_dev/diff

• registry_diff.basedir - the folder that contains the original registry


file, prior to developing the customizations
Ideally you would have preserved the original state of your registry files before
doing any customization. If not, then to access your original registry files you may
need to unregister your customized classes, preserve the registry files as your
base, and then rebuild your customizations. For example, to unregister your
customized classes that begin with the prefix “ext.”:
Remove lines beginning with “ext.” or containing “=ext.”:
ant -f <loadpoint>/bin/tools.xml model_uninstall
-Dmodel_uninstall.filter="\Aext\.|=ext\."
Note: This will match any key or value that begins with “ext.”.

System Generation 1969


For additional usage examples execute: ant -f <loadpoint>/bin/
tools.xml model_uninstall.help
• registry_diff.modsdir is the folder that contains the development
registry files (ie the development codebase), that is the version of the registry
files with your customizations registered.
• registry_diff.diffdir is the folder where the delta between the
basedir and modsdir will be output. Within the directory two folders
could be created: reg_adds and reg_removes. These two folders will be
used by the registry_merge command on the destination system as
described below.
The registry_merge target must be run from the Windchill shell of the
destination system, and it must have access to the files generated by the
registry_diff target.
ant -f <loadpoint>/bin/tools.xml registry_merge
-Dregistry_merge.adds=/wt_dev/diff/reg_adds
-Dregistry_merge.removes=/wt_dev/diff/reg_removes

• registry_merge.adds is the folder that contains the customization


entries to add to the destination system
• registry_merge.removes is the (optional) folder that contains the
customization entries to remove from the destination system

1970 Customization Guide


Creating New Tablespaces
1. Launch PSI and select Windchill components.
2. On the database configuration options window, select Use Existing for
Database, and Create or Use Existing for Database Installation User.
3. On "the select data sets window DO NOT select any of the available options,
Create database schema, Load base data, Load demo data.
4. If you selected to create a database installation user in Step 2 then on the
database information page type in target database and new user information.
• In the Default Tablespace Name field type in the new default tablespace
name (i.e. USERS_DATA)
• In the Temporary Tablespace Name field type in the new Temporary
tablespace name (i.e. TEMP2)
5. Once the installation is finished, open a Windchill Shell and change directory
to <Windchill>\db.
6. Execute following ChangeDdlTablespaceNames.class from
SystemGeneration.jar to update Windcihll DDL with new tablespace
names :
java -cp <Windchill>\srclib\tool\SystemGeneration.jar
wt.tools.generation.sql.ChangeDdlTablespaceNames
7. Execute the following commands to change the properties to point to new
tablespaces.
xconfmanager -s
wt.generation.sql.defaultTablespaceName=<NEW_
DEFAULT_Tablespace_Name> -t "codebase/wt.properties"
-pxconfmanager -s
wt.generation.sql.BLOBTablespaceName=<NEW_BLOBS_
Tablespace_Name> -t "codebase/wt.properties"
-pxconfmanager -s
wt.generation.sql.indexTablespaceName=<NEW_INDEX_
Tablespace_Name> -t "codebase/wt.properties"
-pxconfmanager -s
wt.generation.sql.auditTablespaceName=<NEW_AUDIT_
Tablespace_Name> -t "codebase/wt.properties" -p
8. Execute create_ddl_wt.sql script from <Windchill>\db\sql or
<Windchill>\db\sql3 folder (if multi-byte option was selected during
install) using wt.tools.sql.SQLCommandTool class as follows.
• On Windows:

System Generation 1971


set JAVA_ARGS=
"-Dwt.tools.sql.warningOutputFileName=warnings.txt
-Dwt.tools.sql.errorOutputFileName=errors.txt
-Dwt.tools.sql.dbUser=WNC101
-Dwt.tools.sql.dbPassword=WNC101"
windchill --java=E:\ptc\Windchill_10.1\Java\bin\
java --javaargs="JAVA_ARGS"
wt.tools.sql.SQLCommandTool create_ddl_wt.sql E:\
ptc\Windchill_10.1\Windchill\db\sql
• On Unix (korn shell example):
# JAVA_ARGS="-Dwt.tools.sql.warningOutputFileName=
warnings.txt -Dwt.tools.sql.errorOutputFileName=
errors.txt -Dwt.tools.sql.dbUser=WNC101
-Dwt.tools.sql.dbPassword=WNC101"
# export JAVA_ARGS
# windchill --java=/mnt/disk1/x22m40jdk41spc/Java/
bin/java --javaargs=$JAVA_ARGS
wt.tools.sql.SQLCommandTool create_ddl_wt.sql /mnt/
disk1/x22m40jdk41spc/Windchill/db/sql
9. Start Windchill Server, and load data.

1972 Customization Guide


50
Enumerated Types
The EnumeratedType Class ................................................................................... 1974
Creating an EnumeratedType Subclass .................................................................. 1976
Editing the Resource Info for an Enumerated Type................................................... 1977
Localizing an Enumerated Type.............................................................................. 1979
Extending an Enumerated Type.............................................................................. 1980
The Enumerated Type Customization Utility ............................................................ 1981
GUI Usage of an Enumerated Type ........................................................................ 1983
External Enumerated Value Lists ............................................................................ 1984

This chapter describes enumerated types.

1973
The EnumeratedType Class
EnumeratedType represents a type whose possible values are constrained to a
set (as defined in a resource).

value
The internal value, which is persisted.
display
The localizable display text.
comment
An optional comment describing the value.
order
Provides an explicit sort order for the value.
defaultValue
Specifies the value that is the default value for the type.
selectable
Specifies if the value should be allowed to be selected.
• The constructors for EnumeratedTypes are protected so that instances can
only be constructed internally. The data needed for construction is obtained
from a resource and used to construct the instances in the static initializer.
• getValueSet() returns the set of possible values for the class, where the
possible values are instances of the class.
• toString() returns the internal value, which will be persisted. This follows
the pattern of primitive wrappers provided by Sun. This means toString() is

1974 Customization Guide


not available for generic use by GUI components; they must use
getDisplay().

Enumerated Types 1975


Creating an EnumeratedType Subclass
To create an EnumeratedType subclass, perform the following steps:
1. Create a java class annotated with @GenAsEnumeratedType.
For example (src/example/MySize.java):
package example.MySize;

import com.ptc.windchill.annotations.metadata.GenAsEnumeratedType;

@GenAsEnumeratedType
public class MySize extends _ MySize {
static final long serialVersionUID = 1;
}
2. Optionally, code any desired programmatic constants in MySize.java. For
example:
public static final State SMALL = toMySize("sm");
3. . Create its companion resource info file. For MySize, it will be named
MySizeRB.rbInfo. See details below.

1976 Customization Guide


Editing the Resource Info for an
Enumerated Type
The name of the resource info file is RB.rbInfo, with the simple package name
prepended, for example, MySizeRB.rbInfo. The following sections describe
the resource info files.

Enumerated Type Resource Info Header


Each resource info file contains the following lines that define certain file level
information:
ResourceInfo.class=wt.tools.resource.EnumResourceInfo
ResourceInfo.customizable=true
ResourceInfo.deprecated=false

The first line classifies the resource info and should never be changed. The values
of the second two lines can be changed by the owner of the package, if the file
should not be customized and if the file is deprecated.

Resource Entry Format


See Resource Entry Format on page 2072 in Internationalization and Localization
on page 2063 .
The <key>.value, the two Display values (abbreviatedDisplay and
fullDisplay), and the two Description values (shortDescription and
longDescription) are the only ones that are localizable.

Resource Entry Contents


The following are examples of the entries:
lrg.value=Large
lrg.order=30

med.value=Medium
med.order=20

sm.value=Small
sm.order=10

If the order properties are not defined, the options will be displayed in alphabetical
order, using the locale specific display value. One of the entries can have
defaultValue set to true. For example, the attributes for the "sm" value could
be as follows:
sm.value=Small

Enumerated Types 1977


sm.shortDescription=Small Comment
sm.order=10
sm.defaultValue=true

Building Runtime Resources


Windchill provides a utility to build the runtime resource for the .rbInfo files.
• To build the runtime resources into the codebase for a particular RB file, use
the following command:
ResourceBuild <package.ClassName>
For example:
ResourceBuild example.MySizeRB
• To build the runtime resource into the codebase for all the resource info files
for a particular directory, use the following command:
ResourceBuild <directory_relative_to_src>
For example:
ResourceBuild example

The above script is a convenience wrapper for the bundle target in the bin/
tools.xml Ant script. To see all the options available for direct use of the
bundle target, use the following command:
ant -f bin/tools.xml bundle.help

The resulting resource file is named <name>.RB.ser, which is a serialized


instance of SerializedResourceBundle. For example, src/wt/example/
MySizeRB.rbInfo will build to codebase/wt/example/
MySizeRB.RB.ser.
To verify the values stored in a resource bundle, a verification utility is provided
by the EnumeratedType base class. A batch file, enumVerify.bat, can be
used to invoke this verification, as follows:
enumVerify <fully_qualified_
EnumClassname>[<language>][<country>][<variant>]
The following are examples of usage:
enumVerify wt.lifecycle.State
enumVerify wt.lifecycle.State fr
enumVerify wt.lifecycle.State fr CA

For information on locales, and codes for languages and countries, see the
java.util.Locale class entry in your installed Windchill Javadoc.

1978 Customization Guide


Localizing an Enumerated Type
To have a locale-specific set of display values for an enumerated type, a locale-
specific version of the enumerated type’s resource bundle can be created. To do
so, perform the following steps:
1. Make a copy of the standard resource bundle for the enumerated type, giving it
a file name with the appropriate locale suffix. For example, to create a French
version of the resource bundle for MySize, copy the MySizeRB.rbInfo bundle
and name it MySizeRB_fr.rbInfo.
2. Do not change the keys of entries being localized; they must match those in
the standard bundle.
3. Edit the display and description fields with the appropriate translation.
4. Change the order and defaultValue fields if desired; it is not likely to be
necessary.
5. Do not change the selectable field.
After creating the resource info file for a specific locale and translating it, build
the runtime resource from it. Then verify the results of your localization by using
the verification utility mentioned earlier.

Enumerated Types 1979


Extending an Enumerated Type
An enumerated type can be extended, and using it in a constraining, or covariant,
manner is supported. For example, MySize can be extended by MyDerivedSize,
and it can be used as indicated by MyDerivedItem, as shown in the following
figure.

The one caveat with using extended EnumeratedType instances is that, if concrete
types are used in the model, they are the only types that can be read back from the
database. Using the example in the preceding figure, this means that other
subclasses of MySize can be assigned to the size attribute of MyItem, and they
can be stored in the database, but they can be read out only as instances of the
types that are modeled.
This limitation would not apply if MySize were an abstract class. When an
abstract class is modeled, the runtime type information is stored in the database
along with the instance information. Therefore, the exact type and instance can be
reconstructed when reading it back from the database.

1980 Customization Guide


The Enumerated Type Customization
Utility
The Enumerated Type Customization Utility allows you to add or edit values of an
enumerated type. When customizing enumerated types, use the Enumerated Type
Customization Utility rather than directly creating customized resource info files.
The utility will create, or update, files in a parallel directory structure defined by
the wt.generation.custom.dir property, which defaults to
$(wt.home)/wtCustom. The resource info files provided with Windchill
should never be changed.

Note
The Type and Attribute Management utility is now the one and only
configuration point for "default values" shown in the UI. For more information
see the “Default Values Tab” online help topic in the Windchill Help Center.

The remainder of this section describes how to start the utility. For specific
instructions on its usage, see the online help available when you start the utility.

Starting the Utility


In the tools properties, the wt.resource and wt.clients.tools.enumtype properties
(described in properties.html) are used to configure the utility for your
environment. Most of these properties need not be set, since appropriate defaults
are provided.

Enumerated Types 1981


To start the Enumerated Type Customization Utility, open a console prompt and
enter the following script name:
enumCustomize

To see the changes you have made after using the utility, perform the following
steps:
1. Restart the method server.
2. Rebuild all of the client jar files (see ”Managing Client JAR Files” in
Managing Customizations on page 100) so clients can access the new values.
3. Restart any Java clients. (HTML clients access the new values as soon as their
pages are refreshed from the server.)

1982 Customization Guide


GUI Usage of an Enumerated Type
The localizable display field for an enumerated type can be displayed by using
getDisplay() or getDisplay(locale).
To use enumerated types in GUI drop-down list selections, wt.clients.util.
EnumeratedChoice is provided as a generic control for enumerated types. The
following is a simple example of using the control:
// construct and initialize a ChoiceBox for an EnumeratedType
EnumeratedChoice mySizeChoice = new EnumeratedChoice();
mySizeChoice.setEnumeratedTypeClassName( "wt.example.MySize" );

// set current choice selection to the current value


mySizeChoice.setSelectedEnumeratedType( myItem.getSize() );

... user makes selection

// obtain the chosen selection


MySize selection =
(MySize)mySizeChoice.getSelectedEnumeratedType();

Enumerated Types 1983


External Enumerated Value Lists
You can define an enumeration constraint on an attribute that is not a simple static
list of values. The values come from some external source and may change over
time. The Type and Attribute Management utility lets you define static enumeration
constraints on attributes. These enumerations must be maintained manually
through the UI. However, there are some cases where you might want to retrieve
the enumeration from an external source rather than maintaining the static list
manually.

Scope/Applicability/Assumptions
This capability applies to string attributes defined in the Type and Attribute
Management utility.

Intended Outcome
With this solution, you can constrain an attribute to an enumerated list of values
that comes from an external source. You can control the following:
• Localization of the values
• Sort order of the values
• Selectability of the values
• Any trigger condition to ensure the enumeration is always up to date

Solution
Implement an EnumerationInfoProvider to supply the enumerated list and
configure a constraint in the Type and Attribute Management utility to use your
EnumerationInfoProvider.

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of the following:
• Adding constraints to an attribute in the Type and Attribute Management utility.
• How to extract the required enumeration values from your external source.

1984 Customization Guide


Solution Elements
Element Type Description
EnumerationInfo java The interface defines how
Provider to implement a custom
dynamic enumeration
provider. Instances of this
are instantiated through
reflection. Therefore a
public no-arg
constructor is required.
Any exceptions thrown
from the methods in this
interface result in an
empty enumeration.
EnumerationInfo java This interface defines the
Manager method that enumeration
info providers can use to
reset their cached
enumerations.
EnumerationInfo java This class represents an
enumeration. It contains
both the properties of the
enumeration as well as it's
entries. This class is not
thread safe and should not
be modified after handing
it off to other code.
EnumerationEn java This class represents an
tryInfo enumeration entry. It
contains the properties of
the enumeration entry.
There is a unique name
for each enumeration
entry.

Procedure – Implementing an EnumerationInfoProvider


Provide an implementation of the EnumerationInfoProvider interface.
• The initialize method is called once, before the first time the
enumeration is retrieved by the system. The usage of the parameter field is
optional. If your implementation does not require any inputs, then the
parameter can be ignored. The syntax of the parameter field is entirely up to

Enumerated Types 1985


you, with the only restriction being that it should not contain white space or
the ‘~’ character. The parameter is not used by the system for any purpose.
The EnumerationInfoProvider.initialize() method is also
invoked after
EnumerationInfomanager.resetEnumeration(<provider>)
call is made.
• The getEnumerationInfo method is called after the initialization, and
the results of that call is cached by the system automatically. The
getEnumerationInfo method is called again only on the next request for
the enumeration after an
EnumerationInfomanager.resetEnumeration(<provider>)
call is made. Otherwise, the cached information is returned. You can use any
logic appropriate to your use case to determine when to make the
resetEnumeration call. If you never call it, then the enumeration is
effectively static (unless the system caches flush for another reason.) You
could call it periodically, or in response to a trigger. For best performance,
only call this method after changes to the external information have been made
which need to be reflected in the enumeration.
• The getEnumerationInfo() method is where you return an instance of
the EnumerationInfo data structure. The EnumerationInfo supports
two non-localizable properties that you can use to customize the behavior of
your enumeration.

Sample
public EnumerationInfo getEnumerationInfo() {
EnumerationInfo enumerationInfo = new EnumerationInfo();

enumerationInfo.setNonLocalizableProperty(EnumerationInfo.AUTO_SORT,
Boolean.TRUE);
enumerationInfo.setNonLocalizableProperty(EnumerationInfo.DEFAULT_LOCALE,
Locale.EN_US);

Set<EnumerationEntryInfo> enumEntryInfos = getEntries();


enumerationInfo.addEnumerationEntryInfos(enumEntryInfos);

return enumerationInfo;
}
An EnumerationInfo contains a collection of EnumerationEntryInfo
data structures. The EnumerationEntryInfo data structure supports two
non-localizable and one localizable property that you can use to customize the
behavior of your enumeration. Localizable properties can have distinct values set
of any number of different locales.

Sample
Set<EnumerationEntryInfo> enumEntryInfos =
new LinkedHashSet<EnumerationEntryInfo>(12);
loop (…) {

1986 Customization Guide


String name = …;
EnumerationEntryInfo enumEntryInfo = new EnumerationEntryInfo(name);

int sortOrder = …;
Boolean selectable = …;

enumEntryInfo.setNonLocalizableProperty(EnumerationEntryInfo.SORT_ORDER,
sortOrder);
enumEntryInfo.setNonLocalizableProperty(EnumerationEntryInfo.SELECTABLE,
selectable);

Locale locale = …;
String displayName = …;
enumEntryInfo.setLocalizableProperty(EnumerationEntryInfo.DISPLAY_NAME,
locale, displayName); }

Procedure – Configuring an External Enumerated Value List


Constraint in the Type Manager and Attribute Management
Utility
When you add an External Enumerated Value List constraint to an attribute in the
Type and Attribute Management utility, you must specify two fields.

• Specify the fully qualified classname of your


EnumerationInfoProvider implementation.
• Optionally specify a parameter String which should be passed to your
EnumerationInfoProvider implementation’s initialize method.

Enumerated Types 1987


Customization Points
Customization Points - EnumerationInfo
Property Default Possible Required? Description
Value Values
Enumeratio Boolean. Boolean. no If the
nInfo.AU FALSE FALSE Enumeratio
TO_SORT Boolean. nInfo.AU
TRUE TO_SORT
property is set
to true, then
the system
automatically
sorts the
enumeration
based on the
localized
display names
of the entries.
If it is set to
false, then the
system sorts
the
enumeration
based on the
relative sort
order you
assign to the
entries. If two
or more entries
are given the
same sort
order, those
entries are
sorted relative
to each other
based on their
display names.
Entries
without a sort
order defined
are sorted after

1988 Customization Guide


Property Default Possible Required? Description
Value Values
all entries with
a sort order
defined.
Enumeratio System Locale Any Locale no Indicates the
nInfo.DE locale which
FAULT_ should be used
LOCALE as the fallback
if the client
requests the
localized
display
information
for an
enumeration
entry for a
locale for
which
localizations
are not
available.

Enumerated Types 1989


Customization Points - EnumerationEntryInfo
Property Default Possible Required? Description
Value Values
Enumeratio null Any Integer no If the
nEntryIn Enumeratio
fo.SORT_ nInfo.AU
ORDER TO_SORT
property is set
to false, the
system sorts
the
enumeration
based on the
relative sort
order you
assign to the
entries. If two
or more entries
are given the
same sort
order, those
entries are
sorted relative
to each other
based on their
display names.
Entries
without a sort
order defined
are sorted after
all entries with
a sort order
defined.
Enumeratio Boolean. Boolean. no Indicates
nEntryIn TRUE TRUE whether the
fo.SELECTA Boolean. entry should
BLE FALSE be selectable
by the end user
during edit
operations.
Enumeratio null Any String no The display
nEntryIn name for the

1990 Customization Guide


Property Default Possible Required? Description
Value Values
fo.DIS enumeration
PLAY_NAME entry for the
indicated
locale.

Enumerated Types 1991


51
Customizing LDAP Attributes
Customizing LDAP Mapped Attributes in a User Information Page ............................ 1994
Customizing LDAP Mapped Attributes in a Group Information Page .......................... 1997

This chapter contains details on customizing LDAP mapped attributes and


viewing them on User Information Pages.

1993
Customizing LDAP Mapped Attributes in
a User Information Page
1. Login as the Site Adminstrator and navigate to Site ▶ Utilities ▶ Info*Engine
Administration

Edit the JNDI adapter which is configured for the LDAP that contains the
additional attributes you want mapped to the user.
In the Additional Properties section of the JNDI adapter properties page, add
the property
<service.name>.windchill.mapping.user.attributes and
enter the attributes (comma separated) you want mapped as values for this
property. The <service.name> is the name of the adapter whose
properties you are modifying. If you chose to replace windchill with either
the name you provided for the web application, or any other name, then you
can add the property “wt.org.webAppName” to wt.properties and
provide the name you intend to use.
2. Open the LogicalAttributes.xml file from the <Windchill>\
codebase directory. Search for any definition of the WTUser class name
and append definitions for the attributes you created in step 1 to this section.
For example, for an attribute name “citizenship” the definition is shown below.
Make sure the value in the LogicalForm tag is the same as the attribute you
defined in step 1. The attributes are case-sensitive.
<Property>
<LogicalForm>citizenship</LogicalForm>
<ExternalForm>SCA|citizenship.key</ExternalForm>
</Property>
3. Add additional information on each of these attributes and the corresponding
Server Calculated Attribute Function (SCAF) that needs to be invoked to
retrieve the values of these attributes, into a resource bundle that is supported
for customization.
For example, modify the orgModelRB.rbInfo file in the
<Windchill>\src\wt\org directory and add entries similar to the
following:
WCTYPE|wt.org.WTUser~SCA|citizenship.key.value=Citizenship
WCTYPE|wt.org.WTUser~SCA|citizenship.key.abbreviatedDisplay=Citizenship
WCTYPE|wt.org.WTUser~SCA|citizenship.key.dataType=java.lang.String
WCTYPE|wt.org.WTUser~SCA|citizenship.key.serverFunction=
com.ptc.core.foundation.org.server.impl.SACFLdapAttributeContainerFunction
WCTYPE|wt.org.WTUser~SCA|citizenship.key.serverFunction.arg1=

1994 Customization Guide


String{citizenship}

Note
The value of serverFunction should remain the same as the one
provided above, unless you write your own SCAF function. In addition if
the attribute was defined as a Boolean in step 1, then key.dataType
should be java.lang.Boolean. Do not change the type in
key.serverFunction. This must always be a String type.

4. Then run the following command in a Windchill shell to generate the


corresponding .ser file in the runtime location (for example
<Windchill>\codebase\wt\org).
tools bundle -Dbundle.input=<Windchill>\src\wt\org -Dbundle.recurse=true

5. Once the build is successful, check the runtime location at <Windchill>\


codebase\wt\org to make sure the .ser files were created.
6. Run the following command in a Windchill shell and view the .lst file
generated in the <Windchill>\temp directory to verify the entries
generated correctly.
windchill wt.util.resource.ResourceBundleUtil wt.org.orgModelRB en_US

7. Run the following command from a Windchill shell to rebuild the client jars.
ant -f codebase/MakeJar.xml
8. Delete the work directory from the <Windchill>\Tomcat directory.
9. Restart Windchill.
10. Navigate to the Site ▶ Utilities ▶ Type and Attribute Management. and create
new alias attributes for the attributes defined in step 2 for the User type.
• Verify the value for Internal Name matches the name provided in the
LogicalForm tag in step 2.
• Select the corresponding type in the next screen depending on whether the
attribute in ldap that you are mapping to, is a String or a Boolean.
• On the following screen provide a display name. This can be anything.
This controls what displays on the layout to which these attributes will be
added.
• In the Mapping field, provide the value that matches the ExternalForm
tag in step 2.
11. After the attributes are created, you can add them to the Information Page
layout. By default these additional attributes will also appear on the Simplified
User details page. To hide these additional attributes from the Simplified User

Customizing LDAP Attributes 1995


details page, there needs to be a custom Java validator written. You will find
an example validator under prog_examples\principal\user\
validators of your install directory. The file is called
UserAttributeCompanyNameValidator.
The only thing that needs to change based on the attribute that you want
hidden, is the name of the class and the return type. You will need to create a
similar file in your customization directory and then execute the following
command in a Windchill shell to build it.
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source=
<custom directory structure where the file exists>

For example:
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source=
<Windchill>\prog_examples\principal\user\validators

Note
One validator must be written for each attribute that should be hidden.

12. The validator information should then be included in the <!-user


attribute validators -!> section of the PrincipalAdmin-
service.properties.xconf file, which is located in the codebase\
com\ptc\windchill\principal directory.
Propogate the changes using the xconfManager -Fp command.
Example:
<OptionserviceClass="com.ptc.windchill.principal.user.validators.
UserAttributeCompanyNameValidator"
cardinality="duplicate" requestor="null" selector="company" />

13. Restart Windchill.

1996 Customization Guide


Customizing LDAP Mapped Attributes in
a Group Information Page
1. Login as the Site Adminstrator and navigate to Site ▶ Utilities ▶ Info*Engine
Administration

Edit the JNDI adapter which is configured for the LDAP that contains the
additional attributes you want mapped to the group.
In the Additional Properties section of the JNDI adapter properties page, add
the property
<service.name>.windchill.mapping.group.attributes and
enter the attributes (comma separated) you want mapped as values for this
property. The <service.name> is the name of the adapter whose
properties you are modifying. If you chose to replace windchill with either
the name you provided for the web application, or any other name, then you
can add the property “wt.org.webAppName” to wt.properties and
provide the name you intend to use.
2. Open the LogicalAttributes.xml file from the <Windchill>\
codebase directory. Search for any definition of the WTGroup class name
and append definitions for the attributes you created in step 1 to this section. If
one does not exist, you must create a new definition for one.
For example, for an attribute name “CreateDate” the definition is shown
below. Make sure the value in the LogicalForm tag is the same as the
attribute you defined in step 1. The attributes are case-sensitive.
<Property>
<LogicalForm>CreateDate</LogicalForm>
<ExternalForm>SCA|CreateDate.key</ExternalForm>
</Property>
3. Add additional information on each of these attributes and the corresponding
Server Calculated Attribute Function (SCAF) that needs to be invoked to
retrieve the values of these attributes, into a resource bundle that is supported
for customization.
For example, modify the orgModelRB.rbInfo file in the
<Windchill>\src\wt\org directory and add entries similar to the
following:
WCTYPE|wt.org.WTGroup~SCA|CreateDate.key.value=CreateDate
WCTYPE|wt.org.WTGroup~SCA|CreateDate.key.abbreviatedDisplay=CreateDate
WCTYPE|wt.org.WTGroup~SCA|CreateDate.key.dataType=java.lang.String
WCTYPE|wt.org.WTGroup~SCA|CreateDate.key.serverFunction=
com.ptc.core.foundation.org.server.impl.SACFLdapAttributeContainerFunction
WCTYPE|wt.org.WTGroup~SCA|CreateDate.key.serverFunction.arg1=

Customizing LDAP Attributes 1997


String{CreateDate}

Note
The value of serverFunction should remain the same as the one
provided above, unless you write your own SCAF function. In addition if
the attribute was defined as a Boolean in step 1, then key.dataType
should be java.lang.Boolean. Do not change the type in
key.serverFunction. This must always be a String type.

4. Then run the following command in a Windchill shell to generate the


corresponding .ser file in the runtime location (for example
<Windchill>\codebase\wt\org).
tools bundle -Dbundle.input=<Windchill>\src\wt\org -Dbundle.recurse=true

5. Once the build is successful, check the runtime location at <Windchill>\


codebase\wt\org to make sure the .ser files were created.
6. Run the following command in a Windchill shell and view the .lst file
generated in the <Windchill>\temp directory to verify the entries
generated correctly.
windchill wt.util.resource.ResourceBundleUtil wt.org.orgModelRB en_US

7. Run the following command from a Windchill shell to rebuild the client jars.
ant -f codebase/MakeJar.xml
8. Delete the work directory from the <Windchill>\Tomcat directory.
9. Restart Windchill.
10. Navigate to the Site ▶ Utilities ▶ Type and Attribute Management. and create
new alias attributes for the attributes defined in step 2 for the Group type.
• Verify the value for Internal Name matches the name provided in the
LogicalForm tag in step 2.
• Select the corresponding type in the next screen depending on whether the
attribute in ldap that you are mapping to, is a String or a Boolean.
• On the following screen provide a display name. This can be anything.
This controls what displays on the layout to which these attributes will be
added.
• In the Mapping field, provide the value that matches the ExternalForm
tag in step 2.
11. After the attributes are created, you can add them to the Information Page
layout. By default, these additional attributes will also appear on the
Simplified Group details page. To hide these additional attributes from the

1998 Customization Guide


Simplified Group details page, there needs to be a custom Java validator
written. You will find an example validator under prog_examples\
principal\user\validators of your install directory. The file is
called UserAttributeCompanyNameValidator.
The only thing that needs to change based on the attribute that you want
hidden, is the name of the class and the return type. You will need to create a
similar file in your customization directory and then execute the following
command in a Windchill shell to build it.
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source=
<custom directory structure where the file exists>

For example:
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source=
<Windchill>\prog_examples\principal\group\validators

Note
One validator must be written for each attribute that should be hidden.

12. The validator information should then be included in the <!-group


attribute validators -!> section of the PrincipalAdmin-
service.properties.xconf file, which is located in the codebase\
com\ptc\windchill\principal directory.
Propogate the changes using the xconfManager -Fp command.
Example:
<OptionserviceClass="com.ptc.windchill.principal.group.validators.
GroupAttributeCompanyNameValidator"
cardinality="duplicate" requestor="null" selector="company" />

13. Restart Windchill.

Customizing LDAP Attributes 1999


52
System Configuration Collector
Plugin
Creating a System Configuration Collector Plugin .................................................... 2002

This section contains information on the system configuration collector plugin.

2001
Creating a System Configuration
Collector Plugin
You want to create a new plugin for use with the System Configuration Collector
UI in Windchill that will perform some function that the available plugin lack.
The plugin will likely assist you in debugging Windchill configuration,
installation and runtime issues.

Background
The System Configuration Collector is a Windchill UI page, currently accessed
via the UI navigation path of Site ▶ Utilities ▶ System Configuration Collector when
logged into Windchill as a user from the system administrators LDAP group. The
UI provides functionality that system administrators can use to collect, save and
also send Windchill system and configuration information to both local system
and remote systems, including PTC Technical Support.
The directive of the System Configuration Collector is one that allows a user to
gather as much appropriate information at one time regarding a Windchill system.
The information collected is targeted to consumers who can then more readily use
the information to diagnose any potential system and/or configuration issue with
the Windchill instance.
On the System Configuration Collector page the system administrator can select
categories of problems, such as Performance and/or Runtime related issues. A
number of corresponding plugins will then execute. The list of plugins that will
execute can be seen by expanding each respective category root tree node on the
UI. Each plugin collects a discrete set of about the current Windchill system and
configuration. For example, some plugins collect information such as Windchill
Method Server logs, xconf properties files, JMX Mbean configuration information
and database information.
The plugins are the discrete means to accomplish a task for the System
Configuration Collector categories. These plugins can be designed to accomplish
any task that can be done through Java, including executing SQL and QML
scripts, java command utilities (those which include a main() method) and
Windchill Windu tasks.
The plugins comprise a set of software operations for one or more categories that
adds specific capabilities to the System Configuration Collector. The System
Configuration Collector was designed using plugin architecture such that the
functionality provided could be customized by PTC R&D, PTC Global Services,
PTC Technical Support and PTC customers. The plugin architecture is one that
allows a developer to extend and add new functionality to the System
Configuration Collector on a live Windchill system. Therefore, there is no need to
restart the Windchill servers for the new plugin to be recognized by the System
Configuration Collector. The plugin architecture allows for immediate use of the
developed plugin.

2002 Customization Guide


Due to the plugin architecture and ability of a plugin to operate against other Java
systems, databases, WinDu tasks, scripts, etc, a System Configuration Collector
plugin is a very powerful piece of functionality.
A Plugin is also a JMX Management Bean (MBean). This allows for the
management of plugins via a JMX console such as those delivered with
Windchill; JConsole and VisualVM. Using the MBean interface allows for a
means to more easily manage and deploy plugins.
For more information regarding the System Configuration Collector and its uses
see the “System Configuration Collector” online help topic.
For more information regarding JMX MBeans see the “Windchill MBeans” online
help topic.

Scope/Applicability/Assumptions
The scope is restricted to the System Configuration Collector UI page and creating
plugins that operate on that page.
Assume you have an issue with a Windchill system that you must diagnose and no
current plugin provides the functionality you need to assist you in diagnosing the
issue.
Assume you want to extend the functionality of an existing plugin.

Intended Outcome
Once a plugin is properly designed, created and deployed in Windchill it can be
immediately used with the System Configuration Collector page. The plugin will
then execute whatever functionality it was designed to do to assist you in your
diagnosis.
After creating and deploying a plugin, refreshing the System Configuration
Collector UI will allow a user to make use of the deployed plugin. In the
screenshot below, the plugin has been added to the user defined “Custom Plugins”
category. This category only contains the custom created plugin “Tomcat Property
Config File” For more information see Sample Code on page 2042.

System Configuration Collector Plugin 2003


A user can now make use of this plugin in any category they create and execute
the plugin accordingly.
Another option is to make use of a custom plugin through a JMX console. After
creating and deploying a plugin in a Windchill system a user can load that plugin
through a JMX console and make use of its execution. This is accomplished due
to each plugin also being a JMX MBean.
A user must first run the reloadPlugins() MBean operation on the
CustomerSupport MBean. See the below screenshot. This forces the plugin
architecture to reload all MBeans and will find the custom plugin that was
previously deployed.

2004 Customization Guide


After reloading the plugins, the custom created plugin can be seen in the Plugin
MBean list.

System Configuration Collector Plugin 2005


In this case, the newly loaded plugin is the “TomcatConfigProperties” MBean. For
more information see Sample Code on page 2042.
A user can now edit the attributes of this plugin through the JMX Console or run
operations for this plugin (execute the plugin). Additionally, a user can add the
custom plugin to existing custom categories. For a more information regarding
using JMX MBeans consult the documentation.
For more information regarding JMX MBeans see the “Windchill MBeans” online
help topic.
The created plugin will execute from either the System Configuration Collector
UI or a JMX Console.

Solution
Design, develop, deploy and execute a custom plugin with the System
Configuration Collector UI or a JMX Console.

Prerequisite Knowledge
To apply this solution, you need to have an understanding of the following:

2006 Customization Guide


• Basic development using Java – For developing plugins
• Knowledge of Java Management Beans is helpful – For developing complex
plugins
• Knowledge of Java Jar Service Provider is helpful – To understand plugin
deployment

Solution Elements
Element Type Description

PluginMBean Java Class - Interface As noted earlier, each


plugin is an MBean and
must implement the
PluginMBean interface.
This interface specifies
the contract required to
implement a plugin while
ensuring its use as an
MBean. This class can be
extended into new
interface hierarchies to
provide additional
functionality.
Implementing this class
allows a plugin to expose
attributes and operations
that can be executed from
a JMX console.
This class contains the
primary APIs to
implement MBean
attributes and operations.
AbstractPlugin Java Class - Abstract An abstract class that
wraps much of the
complexity of
implementing the
PluginMBean interface
for a plugin. This class
provides concrete
implementations of
methods that can be used
via inheritance from
classes which extend it.

System Configuration Collector Plugin 2007


Element Type Description
This is the base parent
class for all plugins and
any custom plugin should
extend this class either
directly or hierarchically.
SelfAwareMBean Java Class - Abstract Each plugin is a
SelfAwareMBean, that is,
each plugin is a standard
MBean (as previously
described) that knows its
own MBean ObjectName
allowing it to maintain a
single register of itself in
the MBean registry.
All custom plugins should
implement a call to super
() in the plugin
constructor (Sample Code
on page 2042e) to ensure
that each plugin is
registered as a
SelfAwareMBean. The
AbstractPlugin base class
implements a method call
to register the plugin as a
SelfAwareMBean.
Anecdotally, all plugins
should be
SelfAwareMBeans as
each plugin should
eventually inherit from
the base class
AbstractPlugin which
extends
SelfAwareMBean.
com.ptc.customer Java Package This Java package
support.plugins contains all the PTC
provide plugin
implementations. This
package contains abstract
source files for making
the implementation of

2008 Customization Guide


Element Type Description
numerous plugins easier
by providing default
functionality for many
required methods.
Notably, the package
includes the following
abstract Java classes:
AbstractMultipleFilePlu-
gin
AbstractQMLPlugin
AbstractReportingPlugin
AbstractSQLPlugin
AbstactWinDUPlugin
AbstractXconfPlugin
GatherFilePlugin
GatherFolderPlugin
GatherLogsPlugin
GatherEveryLogPlugin
The functionality of these
plugins can be used
directly through Java
inheritance to provide
easier plugin
implementations for
common plugin
functionality types.
AbstractMultiple Java Class - Abstract This class wraps common
FilePlugin functionality needed for a
plugin to gather a list of
files.
AbstractQMLPlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to execute a QML
(Query Markup
Language) files/scripts.
These scripts usually
contain a .qml file
extension.

System Configuration Collector Plugin 2009


Element Type Description
AbstractReportingPlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to execute plugins
against Windchill
Business Reporting.
AbstractSQLPlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to execute a SQL
(Structured Query
Language) files/scripts.
AbstractWinDUPlugin Java Class – Abstract This class wraps common
functionality needed for a
plugin to execute a
WinDU (Windchill
Diagnostic Utilitiy) task.
AbstractXconfPlugin Java Class – Abstract This class wraps common
functionality needed for a
plugin to recursively
identify referenced xconf
files from a parent xconf
file.
GatherFilePlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to gather a single
file.
GatherFolderPlugin Java Class – Abstract This class wraps common
functionality needed for a
plugin to gather a parent
and all child directories.
GatherLogsPlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to gather a
directory of log files. This
class differs slightly from
the similar
GatherFolderPlugin in
that it operates over a
specified date range for a
file, in particular, the file
modification time.

2010 Customization Guide


Element Type Description
GatherEveryLogPlugin Java Class - Abstract This class wraps common
functionality needed for a
plugin to gather a
directory of log files. This
class differs slightly from
the similar
GatherLogsPlugin in that
it ignores date range for a
file, in particular, the file
modification time. As
such, it operates over
every log file.
CollectorMBean Java Class - Interface A Java MBean interface
that specifies the contract
for how a plugin collects
its targeted data. This
MBean does not need to
be implemented directly
by a plugin as
AbstractPlugin takes care
of the implementation
details.
Collector Java Class The concrete
implementation class for
the CollectorMBean
interface. This is the class
that all plugins essentially
rely on to do their file
collection.
collect(…) Java Method The two collect(…)
methods are part of the
PluginMBean interface
and must be implemented
by all plugins (as all
plugins must implement
the PluginMBean
interface).
These methods specify
the API’s necessary to
interact with the Collector

System Configuration Collector Plugin 2011


Element Type Description
class and ultimately carry
out the work of the
plugin.
In general cases, the
AbstractPlugin and other
Abstract classes (see
above) in the plugin
hierarchy provide default
implementations that can
be relied upon for the
collect(…) methods.
Specifically, the
collectData(…) method
of AbstractPlugin.java
can often simply be called
by the collect(…)
methods. However, more
advanced plugins that
handle very specific
needs may require these
methods to be overridden
and implemented directly.
Generally, these cases are
rare and only occur when
a plugin isn’t simply
collecting files but rather
needs to run some Java
process or invoke some
separate operation that
does processing which
results in a file that then
needs to be collected.
There are plugins in the
com.ptc.customer
support.plugin.* packages
that do this which can be
examined for examples,
specifically, see
MBeanDumpPlugin.java,
WDSPlugin.java and
AbstractWinduPlugin.
java.

2012 Customization Guide


Element Type Description
Note that there are two
collect(…) methods that
must be implemented as
there are essentially two
ways the PluginMBean
interfaces specifies a user
can collect data. One API
requires a callNumber
parameter and the other
requires a topicIdentifier.
Each of these parameters
is used to distinguish
locations that information
is collected to.
This method requires a
specific Map return value.
For greater detail
regarding the return value
and this method see
Abstracting the Plugin in
Customization Points on
page 2027

System Configuration Collector Plugin 2013


Element Type Description
collectData(…) Java Method The collectData(…)
method of
AbstractPlugin.java
wraps much of the
complexity of
implementing the collect
(…) methods of the
PluginMBean interface.
This method sets up the
broadcast message to
marshaled to each server
as determined by the
plugin. It also correctly
builds up the return Map
that is expected. Since
this method hides the
complexity of using the
collection framework
directly, it can often be
relied upon by the collect
(…) methods. One can
simply call this method
with the appropriate
parameter values in most
plugin cases.
This method requires a
specific Map return value.
For greater detail
regarding the return value
and this method see
Abstracting the Plugin in
Customization Points on
page 2027
PluginType Java Class This is a Java enumerated
type class. Each plugin
must specify one of the
enumerated types of
PluginType when
initializing itself so that
the Collector class knows
what do with and where

2014 Customization Guide


Element Type Description
to place the collected
information on the file
system.
PluginUtilities Java Class This is a Java class that
provides utility methods
that may be useful for
creating more advanced
plugins that do not rely on
default behavior of the
collect(…) methods. Of
specific interest is the
getReturnMap(boolean,
String, String) method
that will build up the Map
return value that is
expected by the collect
(…) methods. This will
assist in simplifying the
implementation of
advanced plugins which
implement collect(…)
methods with specific
behavior.
PluginPropertyUtils Java Class This is a Java class that
provides utility methods
for property information
that may be useful for
creating more advanced
plugins. This class
provides methods that
allow a user to obtain
xconf managed property
value information as well
as a means to resolve
tokenized xconf paths
into fully qualified
canonical paths.
*Resource Java Classes Each plugins strings
should be localized so
that they can be viewed in
various locales. The com.

System Configuration Collector Plugin 2015


Element Type Description
ptc.customer
support.mbeans.plugin*
packages contain resource
classes. These resource
Java classes maintain
strings that can be
localized and used in Java
source code.
A plugin can make use of
these or new resource
files to provide localized
strings.

2016 Customization Guide


Element Type Description
<file_name>.jar Java Jar File This is a standard Java .
jar file and can be named
anything. The .jar file is
the standard way to
deploy a custom plugin in
the System Configuration
Collector for use.
The .jar should contain
the compiled .class files
for the plugin and any
helper Java classes along
with the PluginMBean
services file (see below).
The .jar file must
maintain the directory
structure of the package
for the .class files and the
service file.
For more information on
Java Jar files specification
see Additional Resources
on page 2050.
com.ptc.customersupport Java Jar Service File This is a services file
.mbeans.PluginMBean contained in a Java .jar
file that allows the
System Configuration
Collectors Java class
loader to know if a new
plugin has been deployed.
The file structure is rigid
and must be maintained,
otherwise, Java class
loader issues will result
and the plugin will not
load nor be available for
use. The .jar file must
contain the file com.ptc.
customer
support.mbeans.
PluginMBean at location
META-INF\services. The

System Configuration Collector Plugin 2017


Element Type Description
file contents must be of
type:
<java source package>.
<plugin class name>
(without the brackets).
For more information on
Java Service Provider
Interface see Additional
Resources on page 2050

As discussed above, the plugin packages contain a hierarchy of Java inheritance


that a plugin developer can rely on to create plugins. Below is a UML diagram
showing the hierarchical relationship between the abstract classes and MBean
interface APIs.

As seen above, all plugins implement the PluginMBean interface and, eventually,
extend the AbstractPlugin class. A custom plugin can make use of the plugin
hierarchy and the functionality provided by any of the abstract classes.

2018 Customization Guide


Procedures – Creating a Custom Plugin
Foremost, for the complete CustomPlugin.java class that is seen in the following
sections as code snippets, refer to Sample Code on page 2042.
Four distinct phases must be completed before a plugin can be used with the
System Configuration Collector or a JMX Console.
1. Designing the plugin.
2. Implementing the plugin.
3. Compiling the plugin.
4. Deploying the plugin.

Designing the Plugin


There are numerous considerations to take into account when designing a plugin
for the System Configuration Collector.
1. It is highly recommended, although not required, that a plugin class name
include the word “Plugin”. Including the word “Plugin” as a suffix of the class
name easily identifies its purpose. The plugin source file name should be of
the form <ClassName>Plugin.java. For practicality, the <ClassName> should
allude to the plugins purpose as well. For example, PTC provides a
SiteXConfPlugin that collects the <Windchill>/site.xconf file.
2. It is highly recommend that a plugin developer maintain a reasonable Java
package structure for their plugins. The PTC provided plugins generally
maintain package structures relevant to their purpose and PluginType (see
Solution on page 2006 for more information on the PluginType class). Many
of the PTC plugins can be found in the package com.ptc.customersupport.
mbeans.plugins. Placing custom plugins in this package may allow for easier
debugging of custom plugins as well as identifying their locations after
deployment. However, this is not a strict requirement and the package
structure is left to the developer.
3. All plugins must implement the PluginMBean interface. Implementing the
PluginMBean interface class allows a plugin to expose attributes and
operations that be executed from a JMX console. In addition, the
PluginMBean class enforces an API contract that all plugins must adhere to
which is vitally important to the underlying collection framework (see the
CollectorMBean and Collector class as noted in Solution on page 2006).
4. All plugins must extend the AbstractPlugin class. The AbstractPlugin wraps
much of the complexity of implementing the PluginMBean interface. It
provides default implementations for many methods that are common to
creating a plugin. Certainly, the default method implementations can be
overridden to provide varying functionality.

System Configuration Collector Plugin 2019


For example:
public class CustomPlugin extends AbstractPlugin
implements PluginMBean {}

This example shows a CustomPlugin class that implements the PluginMBean


interface and extends the AbstractPlugin class. Note that in this example the
required methods of the interface, namely the collect(…) methods, are not
implemented and this simple class would not compile. See Sample Code on
page 2042 for a complete sample plugin implementation for sample plugins
packaged with Windchill.
5. All plugin object constructors must make a method call to its super class. This
is to ensure that all plugins initialize as SelfAwareMBeans (see Solution on
page 2006 details regarding SelfAwareMBean). Since all plugins must extend
the AbstractPlugin class through the plugin hierarchy, the AbstractPlugin class
will make the appropriate method calls to register a plugin as a
SelfAwareMBean. Therefore, a plugin developer does not need to concern
themselves with the actual plugin MBean registration other than ensuring their
plugin calls the super() operator during construction and that the plugin
inheritance eventually extends AbstractPlugin.java.
For example:
public CustomPlugin() throws NotCompliantMBeanException {
super(null);
// TODO Other initialization of this particular plugin
}

public CustomPlugin(final String displayName,


final String beanName, final String description,
final String pluginVersion)
throws NotCompliantMBeanException {
super(null, displayName, beanName, description, pluginVersion);
// TODO Other initialization of this particular plugin
}

These constructors are implemented to match the constructors of


AbstractPlugin and make calls to AbstractPlugin through the super operator.
This causes the CustomPlugin to be registered as a SelfAwarePlugin.
The constructors call to super takes a Class object. If the concrete class is
known it can be specified, otherwise null can be used. Java will use
Introspection to determine the Class name. For example, since the
CustomPlugin implements the PluginMBean the call to super could
alternatively be:
super(PluginMBean.class);
See for options to rely on inheritance to design more succinct constructors.

2020 Customization Guide


6. Due to implementing the PluginMBean interface and extending
AbstractPlugin, a plugin must implement the two collect(…) methods. These
are methods that essentially organize and hand-off work to the Collector class
and collection framework.
For example:
@Override
public Map<String, Object> collect(final long callNumber,
final long maxAgeInDays,final long minAgeInDays,
final String pathTimeStamp) {
// TODO Do actual collection work and return correct Map
return null;
}

@Override
public Map<String, Object> collect(String topicIdentifier,
final long maxAgeInDays, final long minAgeInDays,
final String pathTimeStamp) {
// TODO Do actual collection work and return correct Map
return null;
}

The collect(…) method implementations shown here do not do anything useful


and are merely presented here for clarity. They should do whatever work the
plugin collection needs to accomplish and return the correct Map<String,
Object> value that is expected.
There are numerous default implementations of the collect(…) methods that
can be relied upon through the Abstract classes. Often, a plugin simply needs
to call the collectData(…) method of AbstractPlugin.java passing through the
parameters of the collect(…) method to the collectData(…) method. The
collectData(…) method wraps the complexity of calling the collection
framework directly in the collect(…) methods. The collect(…) methods are
required by the PluginMBean interface API since the flexibility is necessary to
allow a developer to implement the collect(…) methods as necessary since
very advanced plugins might desire to avoid using the default behavior of
collectData(…). Additionally, the Abstract classes have additional methods
that can be relied upon. Many of these methods are of the form collectXYZ
(…) that can be called by the collect(…) method implementations of specific
plugins. These collect (…) methods wrap the specific collect implementations
for the Abstract type of work the plugin does. For example, the
GatherFolderPlugin.java class has collect(…) methods that are implemented
such that it passes along the specific folder to be collected to the collection
framework, provided that folder was correctly set in the plugin initialization.
The collect(…) methods must return a Map<String, Object>. This return Map
is what is used by the plugin framework to understand on what server a plugin

System Configuration Collector Plugin 2021


was executed and the plugins status. This return value is actually a Map inside
of a Map; Map<String, Map<String, String>>. The outer Map contains the
server information while the inner Map contains the plugin execution status
for that server.
If a customizer does not rely on the default implementations of collect(…)
methods either through using the parent collectData(…) or other collect(…)
methods of Abstract classes one must take extreme care to ensure that the
return Map is correctly built and contains valid values.
See Customization Points on page 2027 for additional detail on using default
collect(…) implementations as well as greater detail regarding the methods
return Map<String, Object> value.
7. The last consideration is what your plugin must do for actual work, and the
most appropriate means to accomplish this. This can be accomplished by
making numerous classes to work in conjunction with each other or wrapping
all execution in one class.
Additionally, there are numerous utility methods and abstract classes, as
discussed in Solution on page 2006which can simplify plugin implementation.
However, plugins can be designed to be very complex or very simple
depending on the task the plugin is supposed to accomplish.
8. In summary, a properly designed plugin is required to have at least these
characteristics:
• Implement the PluginMBean interface.
• Extend the AbstractPlugin class, either directly or through inheritance.
• 2 constructors with super() operator calls which eventually lead to
AbstractPlugin.
• 2 collect(…) methods (if not relying on parent collect(…)
implementations).

Implementing the Plugin


Implementation of a plugin is code that will do the actual work for the plugin. The
main steps are to ensure a plugin is correctly initialized (see the design step above)
and adheres to the required interface. The final step is providing the necessary
method implementations for the plugin to carry out its work.
1. Plugin initialization:
During plugin construction, the object should initialize its MBean attributes
(again, all plugins are MBeans). Using the example from the design phase we
can expand on the constructor method:
public CustomPlugin() throws NotCompliantMBeanException {

2022 Customization Guide


super(null);
// super(PluginMBean.class);
initializeMBeanAttributes();
}

private void initializeMBeanAttributes() {


if (logger.isDebugEnabled()) {
Plugin.");
logger.debug("Initializing " + CUSTOM_PLUGIN_NAME + "
}

// set the plugin display name


setDisplayName(CUSTOM_PLUGIN_NAME);
// set the plugin description
setDescription(CUSTOM_PLUGIN_DESCRIPTION);
// set the plugin MBean name
setMBeanName("TomcatConfigProperties");
// set the plugin enumerated type
setPluginType(PluginType.MISC);
// set the plugin version number
setPluginVersion("1.0");
// set whether the plugin relies on database
// administrator credentials
setDbCredentialsNeeded(false);
// set whether the plugin operates on each
// cluster node
setClusterAware(true);
// set whether the plugin relies on file
// date ranges for data collection
setDateRangeUsed(false);
// set whether the plugin should compress the
// output of its data collection
setCompressOutput(false);
}

Here the constructor has been expanded to include a private method that
initializes all the plugin attributes including the MBean values that are
exposed.
The value of the setMBeanName parameter should be a properly formed
MBean Object Name. To avoid potential MBean loader issues, it is
recommend to avoid using spaces in the string name. For complete details
regarding MBean Object Name syntax refer toAdditional Resources on page
2050 – Related Websites.
2. Plugin collect(…) methods:

System Configuration Collector Plugin 2023


The bulk of the plugin work is contained in the collect(…) methods and the
implementation details are left for the plugin developer to implement. See
Sample Code on page 2042 for examples.
In advanced plugins the work is generally sufficiently large for the collect(…)
methods such that it is reasonable to implement helper Java classes and private
helper methods. This will allow the plugin to have more discrete methods for
easier maintenance. The implementation of any helper method is solely based
on the plugin and the developer’s discretion, and therefore is also specific and
left for the particular implementer of the plugin. Refer to Customization Points
on page 2027 for greater detail regarding the collect(…) methods.
3. Plugin localization:
As Windchill is a distributed application with the potential to have clients in
different locales it is highly recommended that any Java Strings that are
externalized in a plugin should be localized.
The strings of note are the plugin name and plugin description. These values
are presented to the user in the System Configuration Collector UI.
The com.ptc.customersupport.plugins.* packages contain numerous
*Resource.java files that are referenced throughout many of the plugins, and
found in the same packages. These *Resource.java files contain public String
reference values that are localized and read during MBean plugin
initialization.
However, it is not always possible or feasible to localize Java strings. If the
values are not localized the values used are those entered and compiled into
the class files; in the above cases, English.
Using our example from CustomPlugin we add a new plugin member variable:
private static ResourceBundle RESOURCE =
ResourceBundle.getBundle(
CustomPluginResource.class.getName());

This will be our reference to where our localized Java strings reside. Our
CustomPlugin can then make use of this reference to retrieve the localized
values. The refactored setDisplayName(string) and setDescription(string)
methods become:
// set the localized plugin display name
setDisplayName(MBeanUtilities.formatMessage(
RESOURCE.getString(
CustomPluginResource.CUSTOM_PLUGIN_NAME)));
// set the localized plugin description
setDescription(MBeanUtilities.formatMessage(
RESOURCE.getString(
CustomPluginResource.CUSTOM_PLUGIN_DESC)));

2024 Customization Guide


The localized Strings CUSTOM_PLUGIN_NAME and CUSTOM_PLUGIN_
DESC are retrieved from the correctly localized class file.
NOTE: The localized plugin Strings are based on the server locale as the
localized plugin strings are read from the server during plugin initialization.
The localized values will display according to server locale and not the client
locale in the System Configuration Collector UI.
For more information on how to properly localize Windchill strings see
Internationalization and Localization on page 2063.

Compiling the Plugin


After all the plugin files have been implemented they must be compiled into .class
files. Use the Java jdk version running Windchill to ensure proper class file
compatibility. For information on how to compile Java source files using the javac
command see Additional Resources on page 2050 – Related Websites.

Deploying the Plugin


Finally, the plugin packaged files must be bundled and deployed into Windchill.
As mentioned in Compiling the Plugin on page 2025, the System Configuration
Collector makes use of a Java class loader to load all files that are custom plugins.
For the class loader to recognize a plugin, a service file must be created and
deployed with the plugin (see Solution Elements and Related Websites for
information on this file).
The steps to have a functionally deployed plugin are:
1. Package the files.
2. Jar the files.
3. Deploy the Jar.
1. At the root location of your packaged source directory create a directory
named “META-INF”. Inside that directory, create a sub-directory named
“services”. Inside the services directory, create a text file named “com.ptc.
customersupport.mbeans.PluginMBean”. This is the service file which the
class loader will examine for plugin class files. This file must contain each
plugin to be loaded and must follow a strict syntax format. The format for
each plugin entry in the service file is of the form:
<java source package>.<plugin class name> (without the brackets).
For example, returning to the CustomPlugin example the corresponding
service file would appear as, and only contain this one line:
com.ptc.customersupport.mbeans.plugins.CustomPlugin

System Configuration Collector Plugin 2025


Here is an example of the package structure for the CustomPlugin source,
class files and service file.

The items of note are:


• The package structure to the CustomPlugin source, com/ptc/
customersupport/mbeans/plugins is maintained.
• The .class files exist in the /plugins directory. Optionally, the .java source
files can exist there as well.
• The META-INF/services directory exists.
• The /services directory contains the “com.ptc.customersupport.mbeans.
PluginMBean” file with an entry for each plugin to be loaded.
2. After creating the package structure and the services file it is necessary to
bundle the files into a Java .jar file. See Related Websites for complete details
on using Java’s jar command.
Using a Windchill shell, navigate to your root package location and create the .
jar file.
Returning to our example above showing the package structure and using the
command

jar cvfM CustomPlugin.jar ./com ./META-INF


yields CustomPlugin.jar that contains all the contents of the /com and /META-
INF directories, including their subdirectories.
3. Lastly, this .jar file needs to be deployed into the System Configuration
Collector class loader location. Copy this file and place it in <Windchill>/
utilities/SystemConfigurationCollector/plugins
directory.

2026 Customization Guide


Now the plugin can be used in the System Configuration Collector page. To do so,
simply refresh the browser and add the custom plugin to a custom category. See
the help on using the System Configuration Collector for more information on
creating custom categories.
For more information regarding the System Configuration Collector and its uses
see the “System Configuration Collector” online help topic.
Alternatively, you can deploy the plugin for use in a JMX console since all
plugins are MBeans. Using a JMX Console navigate to the CustomerSupport
MBean and run the reloadPlugins() operation. This operation forces the plugin
MBean loader to reload all the available plugins including those at the deployment
location. The below screen shot shows a user invoking the reloadPlugins
CustomerSupport MBean operation.
After invoking the reloadPlugins CustomerSupport MBean operation, the custom
plugin will be displayed under the com.ptc/plugins MBean node in the respective
plugin type subdirectory for which the plugin was defined.
See Intended Outcome for more details and images regarding reloading plugins
from a JMX Console.

Customization Points
Extending the PluginMBean Interface
A plugin does not necessaryily need to implement the PluginMBean interface
directly. Instead a new interface that extends the PluginMBean interface could be
defined and implemented by the concrete plugin implementation. However, the
new plugin interface is still required to inherit the PluginMBean interface.
For example:
public interface XYZPluginMBean extends PluginMBean {}
Here the XYZPluginMBean extends the PluginMBean. This interface can then
further define any required methods or attributes that are to be exposed via MBean
operations.
The concrete implementation would then be:
public class XYZPlugin extends AbstractPlugin implements XYZPluginMBean
{}

Abstracting the Plugin


Similar to Extending the PluginMBean Interface section, a developer can rely on
the numerous abstract classes detailed in Solution Elements, or any abstract class
the developer defines to initialize plugin MBean values to defaults. As previously

System Configuration Collector Plugin 2027


stated, the abstract classes wrap much of the complexity of plugin creation. In
addition to relying on the abstract classes for plugin initialization a developer can
also rely on the abstract implementations of the collect(…) methods.
AbstractPlugin.java API: public AbstractPlugin(final Class mbeanInterface)
throws NotCompliantMBeanException
Parameter Default Possible Req? Description
Value Values
mbeanInter- None Class Yes A class name
face that is the
concrete
implementa-
tion for the
plugin.

AbstractPlugin.java API: public AbstractPlugin(final Class mbeanInterface, final


String displayName, final String mBeanName,
final String description, final String pluginVersion) throws
NotCompliantMBeanException {
Parameter Default Possible Req? Description
Value Values
mbeanInter- None Class Yes A class name
face that is the
concrete
implementa-
tion for the
plugin.
displayName None String Yes A String
representation
of the plugin
name.
mBeanName None String Yes A String
representation
of the plugins
mbean name.
This value
should adhere
to proper Java
MBean
ObjectNames.
See Related
Websites for

2028 Customization Guide


Parameter Default Possible Req? Description
Value Values
MBean Object
Names.
description None String Yes A String
representation
of the plugin
description.
pluginVersion None String Yes A version
number
associated
with this
plugin.

AbstractPlugin.java API: public abstract Map<String, Object> collect(long


callNumber, long maxAgeInDays, long minAgeInDays, String pathTimeStamp);
A developer is required to implement this method as it is Abstract. It is called by
UI layers as an entry point to do the plugin work..
Parameter Default Possible Req? Description
Value Values
callNumber None long Yes This is a long
value that is
associated
with a PTC
Technical
Support call
number. It is
used as a
location to
collect plugin
data to. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
maxAgeIn- None long Yes A long value
Days that is a
starting time
value for if

System Configuration Collector Plugin 2029


Parameter Default Possible Req? Description
Value Values
files are
collected with
respect to
time. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.

2030 Customization Guide


Parameter Default Possible Req? Description
Value Values
minAgeInDays None long Yes A long value
that is an
ending time
value for if
files are
collected with
respect to
time. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
pathTimeS- None String Yes A String
tamp representation
of a directory
timestamp
used as a name
which plugins
collect their
data to. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
A developer can usually pass this methods parameters to the collectData(…)
methods of AbstractPlugin.java. As previously discussed, the collectData(…)
method handles the complexity of calling the collection framework.
A developer can implement the collect methods in a way that does not rely on
collectData(…) or any of the Abstract classes parent collectXYZ(…) method
implementations. In general, this is an exception however. Only advanced plugins
that require specialized work, such as running a Java process that does some work
to build a file to be collected, will probably avoid simply calling the parent collect
(…) method implementations. Even in this situation, after the Java process has
completed and generated its data, parent classes could still be relied on to do the

System Configuration Collector Plugin 2031


actual collection. MBeanDumpPlugin.java and WDSPlugin.java are two plugins
PTC provides that do additional work other than simply call the parent collection
methods, these can be examined in greater detail for those wishing to build highly
complex plugins.
Return Value Possible Values Req? Description
Map<String, A Map of type Yes The return type is a
Object> <String, Object> Map that contains
where Object is of an inner Map.
type Map<String, Map<String,
String> Map<String,
String>>. The
“inner”
Map<String,
String> is a Map
that contains the
plugin execution
status. The outer
Map<String,
Object> is a Map
that contains which
server the plugin
executed on. This
allows the plugin
framework to
report information
across the cluster
for each plugin
executed.
Care must be taken when providing the return type of the collect(…) method. The
collectData(…) method of AbstractPlugin.java wraps all the complexity of
creating a valid return type that the plugin framework will correctly interpret. This
is also why it is recommended to use the collectData(…) method in the collect(…)
method implementation. Not doing so increases the complexity of the
implementation of the collect(…) method greatly.
The Outer Map: Map <String, Object>
The String key must be the server process ID and hostname of the name the plugin
executed on. For example, 5524@DSTUSYNSKI03D. While any String is valid,
the plugin framework will report this to the user which will appear as meaningless
data if it isn’t properly built.
The Object is actually an inner Map of type <String, String>.
The Inner Map: Map <String, String>

2032 Customization Guide


The inner Map should have four key entries, one for each String, “success”,
“path”, “message”, “location”.
Each of these keys values must be another String that corresponds to the
appropriate value for the key. The “success” keys value should be true or false and
is the value that states whether the collection framework was successful in
collecting the plugin data or not. The “path” keys value is generated by the
collection framework and it denotes the last directory in the canonical path for
which the plugin data is collected to for the particular server the plugin executed
on. The “message” keys value is a String message that might accompany the
plugin generated by the collection framework. This is likely a status message of
why a plugin failed. The value null should be used if no message is to be reported.
The “location” keys value is a String representing a partial path to where the
collection framework collects the plugin data.
When not relying on the collectData(…) method of AbstractPlugin.java or other
parent Abstract classes care must be taken to ensure the collect(…) methods return
type adheres to this form such that it can be correctly processed by the plugin
framework. If implementing a plugin and building the return Map<String, Object>
directly examine the MBeanDump.java and WDSPlugin.java implementations for
greater detail. Both of these classes do not rely on the Abstract classes or the
collection framework directly and therefore build the correct return type in their
collect(…) method implementations.
For the advanced plugin that requires the return Map to be built a developer can
rely on the PluginUtilites.getReturnMap(…) method which is discussed further in
this section.
AbstractPlugin.java API: public abstract Map<String, Object> collect(String
topicIdentifier, long maxAgeInDays, long minAgeInDays, String
pathTimeStamp);
A developer is required to implement this method as it is Abstract. It is called by
UI layers as an entry point to do the plugin work.

System Configuration Collector Plugin 2033


Parameter Default Possible Req? Description
Value Values
topicIdentifier None String Yes This is a String
representation
of a directory
used as a
location to
collect plugin
data to. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
maxAgeIn- None long Yes A long value
Days that is a
starting time
value for if
files are
collected with
respect to
time. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.

2034 Customization Guide


Parameter Default Possible Req? Description
Value Values
minAgeInDays None long Yes A long value
that is an
ending time
value for if
files are
collected with
respect to
time. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
pathTimeS- None String Yes A String
tamp representation
of a directory
timestamp
used as a name
which plugins
collect their
data to. This
value should
not need to be
modified by
the collect(...)
method
implementa-
tion.
See the previous collect(…) method for detail on this methods usage.
AbstractPlugin.java API: public Map<String, Object> collectData(String srcPath,
final long callNumber,
final long maxAgeInDays, final long minAgeInDays, String pathTimeStamp) {

System Configuration Collector Plugin 2035


Parameter Default Possible Req? Description
Value Values
srcPath None String Yes This is a String
representation
of a location
that a plugins
source data is
collected from.
This is usually
a tokenized
Windchill
property
string. For
example, the
WindchillLogs
Plugin.java
would pass
$(wt.logs.dir)
as the
parameter.
This value can
also be a
canonical file
path to the
data to be
collected.
However, care
must be
ensured as this
file path will
likely not exist
on each server
the plugin is
executed on. If
a canonical file
path is used
the plugin
should only
execute on one
cluster node by
setting the
plugin

2036 Customization Guide


Parameter Default Possible Req? Description
Value Values
attribute
isClusterAware
to false during
plugin
initialization.
callNumber None long Yes This is a long
value that is
associated
with a PTC
Technical
Support call
number. It is
used as a
location to
collect plugin
data to.
maxAgeIn- None long Yes A long value
Days that is a
starting time
value for if
files are
collected with
respect to
time.
minAgeInDays None long Yes A long value
that is an
ending time
value for if
files are
collected with
respect to
time.
pathTimeS- None String Yes A String
tamp representation
of a directory
timestamp
used as a name
which plugins
collect their
data to.

System Configuration Collector Plugin 2037


This is the method wraps the complexity of using the collection framework
directly for collecting plugin data. Although not strictly required, it is
recommended, that it be called by the collect(…) method implementations for a
plugin. Often, calling this method in the collect(…) method and returning its value
is all that is required of a collect(…) method implementation.
The return value of this method is the same return value as the collect(…)
methods described above.
AbstractPlugin.java API: public Map<String, Object> collectData(String srcPath,
final String topicIdentifier,
final long maxAgeInDays, final long minAgeInDays, String pathTimeStamp) {

2038 Customization Guide


Parameter Default Possible Req? Description
Value Values
srcPath None String Yes This is a String
representation
of a location
that a plugins
source data is
collected from.
This is usually
a tokenized
Windchill
property
string. For
example, the
WindchillLogs
Plugin.java
would pass
$(wt.logs.dir)
as the
parameter.
This value can
also be a
canonical file
path to the
data to be
collected.
However, care
must be
ensured as this
file path will
likely not exist
on each server
the plugin is
executed on. If
a canonical file
path is used
the plugin
should only
execute on one
cluster node by
setting the
plugin

System Configuration Collector Plugin 2039


Parameter Default Possible Req? Description
Value Values
attribute
isClusterAware
to false during
plugin
initialization.
topicIdentifier None String Yes This is a String
representation
of a directory
used as a
location to
collect plugin
data to.
maxAgeIn- None long Yes A long value
Days that is a
starting time
value for if
files are
collected with
respect to
time.
minAgeInDays None long Yes A long value
that is an
ending time
value for if
files are
collected with
respect to
time.
pathTimeS- None String Yes A String
tamp representation
of a directory
timestamp
used as a name
which plugins
collect their
data to.
See the previous collect(…) method for detail on this methods usage.
PluginUtilities.java API: public static Map<String, Object>
getReturnMap(final boolean success, final String path, final String message,

2040 Customization Guide


final String location) {
Parameter Default Possible Req? Description
Value Values
success None boolean Yes The success
value for the
plugin
execution to be
placed in the
inner Map for
the plugin
framework
status.
path None String Yes The path
directory value
which is the
parent
directory for
where the file
is collected to
be placed in
the inner Map
for the plugin
framework
status.
message None String Yes The message
to be placed in
the inner Map
for the plugin
framework
status.
location None String Yes The location
partial file path
to the
PluginType
directory be
placed in the
inner Map for
the plugin
framework
status.

System Configuration Collector Plugin 2041


This method will build up a return value for use with the collect(…) method
implementations provided correct values are passed into this method via it’s
parameters. This method is a utility method that makes the creation of the collect
(…) methods return value easier. Essentially, it wraps the creation of the return
value freeing the implementor of the collect(…) method the need to create the
outer and inner Maps. As each parameters description details, the parameters are
used to generate the inner Map and the method implementation will handle
generating the outer Map<String, Object>. The resulting return value is a
Map<String, Object> where the Object is of type Map<String, String> that can
then be used as the return type of a collect(…) method.
While each of these parameters aren’t strictly required, they should be considered
as such, otherwise the methods return value Map<String, Object> will simply be
incomplete. The inner Map will not contain the correct data required by the plugin
framework for reporting on the plugin execution status.
Note that this method will only be useful as a utility for use when a developer
does not rely on the collectData(…) implementation of AbstractPlugin.java or
other Abstract collectXYZ(…) method implementations.

Limitations
Plugins used on the System Configuration Collector or used as MBeans can be
quite powerful. They can be used to collect files, directories, properties as well as
execute java classes, windu tasks, scripts, and gather database information.
Currently, the plugin execution is limited to SQL and QML scripts, Windu tasks
and Java code.

Sample Code
CustomPlugin.java
package com.ptc.customersupport.mbeans.plugins;

import java.util.Map;
import java.util.ResourceBundle;

import javax.management.NotCompliantMBeanException;

import org.apache.log4j.Logger;

import wt.jmx.core.MBeanUtilities;
import wt.log4j.LogR;

import com.ptc.customersupport.mbeans.AbstractPlugin;
import com.ptc.customersupport.mbeans.PluginMBean;
import com.ptc.customersupport.mbeans.PluginType;
public class CustomPlugin extends AbstractPlugin implements PluginMBean {

2042 Customization Guide


private static ResourceBundle RESOURCE =
ResourceBundle.getBundle(CustomPluginResource.class.getName());

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

public CustomPlugin() throws NotCompliantMBeanException {


super(null);
// super(PluginMBean.class);
initializeMBeanAttributes();
}

public CustomPlugin(final String displayName,


final String beanName, final String description,
final String pluginVersion)
throws NotCompliantMBeanException {
// super(PluginMBean.class, displayName, beanName,
// description, pluginVersion);
super(null, displayName, beanName, description, pluginVersion);
}

@Override
public Map<String, Object> collect(final long callNumber,
final long maxAgeInDays,final long minAgeInDays,
final String pathTimeStamp) {
// TODO Do actual collection work and return correct Map
return null;
}

@Override
public Map<String, Object> collect(String topicIdentifier,
final long maxAgeInDays, final long minAgeInDays,
final String pathTimeStamp) {
// TODO Do actual collection work and return correct Map
return null;
}

private void initializeMBeanAttributes() {


if (logger.isDebugEnabled()) {
logger.debug("Initializing " +
MBeanUtilities.formatMessage(
RESOURCE.getString(
CustomPluginResource.
CUSTOM_PLUGIN_NAME))
+ " Plugin.");
}

// set the localized plugin display name


setDisplayName(MBeanUtilities.formatMessage(
RESOURCE.getString(
CustomPluginResource.CUSTOM_PLUGIN_NAME)));
// set the localized plugin description

System Configuration Collector Plugin 2043


setDescription(MBeanUtilities.formatMessage(
RESOURCE.getString(
CustomPluginResource.CUSTOM_PLUGIN_DESC)));
// set the plugin MBean name
setMBeanName("TomcatConfigProperties");
// set the plugin enumerated type
setPluginType(PluginType.MISC);
// set the plugin version number
setPluginVersion("1.0");
// set whether the plugin relies on database
// administrator credentials
setDbCredentialsNeeded(false);
// set whether the plugin operates on each
// cluster node
setClusterAware(true);
// set whether the plugin relies on file
// date ranges for collection
setDateRangeUsed(false);
// set whether the plugin should compress the
// output of its collected data
setCompressOutput(false);
}
}

CustomPluginResource.java
package com.ptc.customersupport.mbeans.plugins;

import wt.util.resource.RBEntry;
import wt.util.resource.RBUUID;
import wt.util.resource.WTListResourceBundle;

@RBUUID("com.ptc.customersupport.mbeans.plugins.CustomPluginResource")
public class CustomPluginResource extends WTListResourceBundle{

@RBEntry("My Custom Plugin")


public static final String CUSTOM_PLUGIN_NAME = "0";

@RBEntry("A plugin that does xyz.")


public static final String CUSTOM_PLUGIN_DESC = "1";
}

TomcatConfigPropertiesPlugin.java
This is sample code that will collect the config.properties file at location
installedProduct.location.Tomcat which is a wt.property value. The plugin is not
localized for simplicity.
package demo;

import java.util.Map;

import javax.management.NotCompliantMBeanException;

2044 Customization Guide


import org.apache.log4j.Logger;

import wt.log4j.LogR;

import com.ptc.customersupport.mbeans.PluginType;
import com.ptc.customersupport.mbeans.plugins.GatherFilePlugin;

/**
* A sample Plugin that gathers the Tomcat config.properties file.
* The location of this file is controlled by the location of
* Tomcat on an installed system. Generally, this location is
* <Windchill>/tomcat/config.properties. However, there exists a
* wt.property which points to where the tomcat instance is
* installed. This property is installed.Product.location.Tomcat,
* and it is used to build a tokenized path to the location of the
* config.properties file.
* <BR><BR>
* This class extends the
* {@link com.ptc.customersupport.mbeans.files.GatherFilePlugin
* GatherFilePlugin} which is used to provide functionality that is
* already implemented that this Plugin can rely upon for default
* behavior. Most plugins will be able to make use of existing
* Abstract plugin classes for much of their behavior and method
* implementations. See the
* {@link com.ptc.customersupport.mbeans.files.GatherFilePlugin
* GatherFilePlugin} for more infomration on the parent class of
* this Plugin and it's methods.
* <BR><BR>
*/
public class TomcatConfigPropertiesPlugin extends GatherFilePlugin {
/*
* Optionally provide some form of localization for plugin strings.
*
* In order to localize the values like name, description,
* and version, follow these steps:
*
* 1. Create a tomcatConfigPropertiesPluginResource.rbInfo
* file with the correct values.
*
* 2. Get an instance of a ResouceBundle like this: private static
* ResourceBundle RESOURCE =
* ResourceBundle.getBundle(
* tomcatConfigPropertiesPluginResource.class.getName());
*
* 3. Set the name (or other value) like this:
* setDisplayName(MBeanUtilities.formatMessage(
* RESOURCE.getString(
* tomcatConfigPropertiesPluginResource.
* PLUGIN_DISPLAY_NAME)));

System Configuration Collector Plugin 2045


*/

// Set member variables for ease of use.


private static final String TCP_PLUGIN_NAME =
"Tomcat Property Config File";
private static final String TCP_PLUGIN_DESCRIPTION =
"<tomcat_home>/config.properties file.";
/*
* Optionally, provide some logging capabilities. Doing so
* can facilitate easier Plugin debugging or provide
* status/information messages to the running servers.
*/
private static final Logger logger = LogR.getLogger(
TomcatConfigPropertiesPlugin.class.getName());

/**
* Default constructor that sets all the required values.
*/
public TomcatConfigPropertiesPlugin() throws
NotCompliantMBeanException {
/*
* The operator call to super() allows the
* TomcatConfigPropertiesPlugin to rely on the parent class for
* much of the Plugin initialization. This call will set
* default values which are later overridden as necessary. This
* also sets up and initializes this Plugin as a SelfAwareMBean
* as the inheritance hierarchy eventually reaches
* AbstractPlugin.
*/
super();
/*
* This method call is simply for convenience of setting
* all the Plugin values in one place that we are
* overriding the default values for which were set when
* super() was called.
*/
initializeMBeanAttributes();
}

/**
* Initializes all the Plugin values for this specific Plugin.
* Those values which were initially set by parent classes are
* overidden.
*/
private void initializeMBeanAttributes() {
// Log a debug message that the Plugin is being initialized.
if (logger.isDebugEnabled()) {
logger.debug("Initializing " + TCP_PLUGIN_NAME + "" +
" Plugin.");
}

2046 Customization Guide


/*
* Set the attribute values that are common to all Plugins,
* regardless of the PluginType.
*/
// The name that will be used for this Plugin.
setDisplayName(TCP_PLUGIN_NAME);
// The description that will be displayed for this Plugin.
setDescription(TCP_PLUGIN_DESCRIPTION);
// Set the MBean ObjectName.
setMBeanName("TomcatConfigProperties");
/*
* Set the PluginType value. This will control where the
* data is collected to in terms of directory structure.
*/
setPluginType(PluginType.PROPERTY);
// Set the Plugin version information.
setPluginVersion("1.0");

/*
* Set the file name that we want to collect. This value
* overrides the default value set by the parent. The
* GatherFilePluginMBean Interface of the parent class
* specifies this method must be implemented. Since we
* are extending the parent class and want to collect a
* specific file (not the default file the parent specifies)
* we override the value and set it to the location:
* $(installedProduct.location.Tomcat)$(dir.sep)
* config.properties
*
* This is a tokenized wt.property value. When the
* collection framework operates on this Plugin, these
* tokenized values are replaced by their canonicalized
* paths and a file path results. This is how the collection
* framework knows where to find files to collect. Ideally
* tokenized or property values should be used to create
* a path to the file. If hard-coded file paths are used
* the Plugin will not operate across a cluster correctly.
*/
setFileName("$(installedProduct.location.Tomcat)" +
"$(dir.sep)config.properties");
}

/**
* Override the collect methods as needed. Incidentally, this
* Plugin does not dictate the collect(...) methods be
* overridden. The implementation of this method is actually
* the same as the parent implementation. However, for clarity
* of the example the collect(...) methods are shown.
*/
@Override
public Map<String, Object> collect(final long callNumber,

System Configuration Collector Plugin 2047


final long maxAgeInDays, final long minAgeInDays,
final String pathTimeStamp) {
/*
* Here we call the collectData(...) method of AbstractPlugin
* which will handle the actual collecting of the file
* specified as the first parameter. Here the first parameter
* is returned by the getFileName() method of the parent
* class.
*
* The collectData method sets up and hides all the complexity
* of using the collection framework and allows a developer to
* avoid implementing a specific collect(...) implementation.
*
* However, there are instances when certain Plugins require
* specific collect(...) method behavior, these instances
* are usually reserved for very advanced Plugins.
*/
return collectData(getFileName(), callNumber, maxAgeInDays,
minAgeInDays, pathTimeStamp);
}

@Override
public Map<String, Object> collect(final String topicIdentifier,
final long maxAgeInDays, final long minAgeInDays,
final String pathTimeStamp) {
return collectData(getFileName(), topicIdentifier,
maxAgeInDays, minAgeInDays, pathTimeStamp);
}
}

Examples of Usage in Windchill Code


com.ptc.customersupport.mbeans package
This Java package contains the AbstractPlugin and PluginMBean
interface. It also contains additional utility classes that can be utilized in creating
plugins such as the PluginType.java and PluginUtilities.java.

com.ptc.customersupport.mbeans.plugin package
This Java package contains many of the abstract classes seen in the UML diagram
and discussed in Solution Elements. This package includes

com.ptc.customersupport.mbeans.plugin.logs package
This Java package contains concrete plugin implementations that are of
PluginType logs. These plugins are generally responsible for collecting log
files. Log4jFilesPlugin, WindchillLogsPlugin and
WDSLogsPlugin are examples that vary in complexity.

2048 Customization Guide


com.ptc.customersupport.mbeans.plugin.misc package
This Java package contains concrete plugin implementations that are of
PluginType misc. These plugins are generally responsible for collecting
miscellaneous information. UpgradeFolderPlugin,
MigrationReportsFolderPlugin and WtSafeAreaFolderPlugin
are examples that vary in complexity.

com.ptc.customersupport.mbeans.plugin.properties package
This Java package contains concrete plugin implementations that are of
PluginType properties. These plugins are generally responsible for collecting
properties files. DbPropertiesPlugin, DeclarationsXconfPlugin
and IePropertiesPlugin are examples that vary in complexity.

com.ptc.customersupport.mbeans.plugin.third package
This Java package contains concrete plugin implementations that are of
PluginType third. These plugins are generally responsible for collecting third
party product information. ApacheConfFolderPlugin,
ApacheLogsPlugin and CogStartupXmlPlugin are examples that vary
in complexity.

com.ptc.customersupport.mbeans.plugin.util package
This Java package contains concrete plugin implementations that are of
PluginType util. These plugins are generally responsible for collecting utility
information. GatherInfoScriptPlugin, MBeanDumpPlugin and
WDSMBeanDumpPlugin are examples that vary in complexity.
MBeanDumpPlugin.java is a complex plugin that does not rely on the collect
(…) method implementations of the Abstract classes. This plugin can be examined
to provide greater insight into creating complex plugins that implement the collect
(…) methods in a manner that doesn’t make use of the Abstract classes
implementations of collect(…) methods or the collection framework directly.

Packaged Samples
PTC provides packaged plugin sample code at <Windchill>/utilities/
SystemConfigurationCollector/plugins/examples. This
directory contains packaged samples that maintain the com.ptc.customersupport.*
packaging in a sample subdirectory. These can be examined to see how one can
make use of SQL, QML, Java commands, etc inside a plugin.

System Configuration Collector Plugin 2049


Additional Resources
Related Package/Class Javadoc
com.ptc.customersupport.mbeans* package(s) contain the Java plugin interfaces,
numerous abstract plugins that provide common functionality, and concrete plugin
implementations.

Related Windchill Documentation


For more information regarding the System Configuration Collector and its uses
see the “System Configuration Collector” online help topic.

Related Websites
• Java Jar Service Provider Specification :
http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/
guides/jpda/jpda_spis.html
http://java.sun.com/developer/technicalArticles/javase/extensible/
http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes
/guides/jar/jar.html#Service%20Provider
• Java Jar File Specification :
http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes
/guides/jar/jar.html
• Java MBean Object Names :
http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/
best-practices.jsp#mozTocId509360
• Java Compiling :
http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/tooldocs/
solaris/javac.html
• Java Jar Command :
http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/deployment/
jar/build.html

2050 Customization Guide


53
Customizing Modeled Elements
Customizing Column Lengths................................................................................. 2052

This chapter describes how to customize modeled elements.

2051
Customizing Column Lengths
A column length for a modeled attribute can be customized. These column lengths
are obtained through the wt.introspection package. The value of this
property can be overridden by placing entries in the customizations property file
for modeled packages. To change the column length for a modeled attribute,
perform the following steps:
1. Determine customization property for the attribute
2. Override attribute length in appropriate customizations property file
3. Generate the class info objects
4. Verify the customization.
5. Alter the database Tables
6. Restart the method servers if they were running during the procedure.
The following example sets the column length for the name attribute of the
wt.doc.WTDocumentMaster class to hold 350 characters. The following
steps describe how to determine which customizations property file entry contains
the new column length, and how to set the value. The customization is made in a
location parallel with the originally modeled attribute. The default location for
these customizations is $(wt.home)\wtCustom, as defined by the
wt.generation.custom.dir entry in the tools properties. Create this
directory if it does not already exist.

Note
See the descriptions for the tools.properties and
user.properties files in Property Files on page 47.

1. Determine which customization property entry must be added:


a. Obtain an info report for the class by executing the following command
from a Windchill shell:
infoReport wt.doc.WTDocumentMaster
The info report file is created in <Windchill>/temp and is
named doc.WTDocumentMaster.out for this class.
b. Inspect the value of the WTIntrospector.UPPER_LIMIT property
(the value being customized) of the name PropertyDescriptor
getValue( WTIntrospector.UPPER_LIMIT ) : 60
c. Inspect the value of the WTIntrospector.DEFINED_AS property of
the name PropertyDescriptor:

2052 Customization Guide


getValue( WTIntrospector.DEFINED_AS ) :
wt.doc.WTDocumentMaster.name
d. Based on this information, use the following values:
• The customization property file is <Windchill>\wtCustom\wt\
doc\docModel.properties.
• The customization property entry is
WTDocumentMaster.name.UpperLimit.
2. Add the customization property entry to the appropriate customizations
property file. In this example, add the following entry to <Windchill>\
wtCustom\wt\doc\docModel.properties (create this file if it does
not exist):
WTDocumentMaster.name.UpperLimit=350

# Ignore multi-byte database character sets when setting value.


# UpperLimit is constrained by database VARCHAR limit : max value is
4000/wt.db.maxBytesPerChar

3. Generate the class info objects. Update the serialized info object by entering
the following command from a Windchill shell:
ant -f bin\tools.xml custom_column -Dgen.input=wt.doc
This updates introspection information for descendant classes that are
concrete, for example wt.federation.ProxyDocumentMaster in the
case of wt.doc.WTDocumentMaster.
4. Verify the customization. Obtain an info report for the class and inspect the
UPPER_LIMIT value as described in the preceding steps. The value should
reflect the customization. If the info report value is unchanged, verify that the
generate step actually updated the following serialized info file:
<Windchill>\codebase\wt\doc\
WTDocumentMaster.ClassInfo.ser
5. Adjust the length of the customized column by taking the following steps:
a. Execute the Windchill Upgrade Manager to run the Compare Schema step
only.
Start the Windchill Upgrade Manager within a Windchill shell as follows:
UpgradeManager -cs
For further information about the Windchill Upgrade Manager command
options and upgrading data base schema see the following topics in the
Windchill Upgrade Guide :
• “Additional Upgrade Manager Commands”
• “Upgrade Database Schema”

Customizing Modeled Elements 2053


b. Inspect the generated output to find the SQL script(s) related to this
customization in:
<Windchill>\Upgrade\UpgradeReports\CompareSchema\
CompareSchema-<timestamp>.html#AlteredTables -
section 'Tables to be Altered'.
Tables corresponding to descendant classes must also be altered (e.g.
PROXYDOCUMENTMASTER).

Caution
Review the output carefully to ensure the results are what you expect.
You should never execute any SQL that you do not understand, or that
does not seem related to your intended customizations

c. Execute the relevant SQL scripts as Windchill database schema owner.


In this example, WTDocumentMaster.name is also the source for the derived
attribute WTDocument.name. This derived attribute, WTDocument.name,
gets its UpperLimit from the source attribute, WTDocumentMaster.name.
A derived attribute cannot set the UpperLimit property in the annotation.
Therefore, the derived attribute cannot be customized in this manner.

2054 Customization Guide


54
Windchill Design Patterns
The Object Reference Design Pattern ..................................................................... 2056
The Business Service Design Pattern ..................................................................... 2058
The Master-iteration Design Pattern........................................................................ 2061

This section describes design patterns that represent Windchill’s current best
practices regarding development of server logic, most notably the design pattern
on how to develop business services. These patterns have emerged during the
development of the Windchill services and should be used as standards and
guidelines when developing new server logic.

2055
The Object Reference Design Pattern
One of the most basic design patterns is the object reference design pattern.

Object Reference Pattern


This pattern essentially encapsulates details concerning persistable objects and
their unique database query key. The pattern asserts that an object is a derived
attribute aggregated by reference and is not persisted. The object’s unique
database query key is aggregated by value, is persisted, and is write-protected
against the attempt of any other package class to set its value.
In cases where database performance and storage are issues, object references
persist only their object identifiers, and can be used in place of actual objects and
acted upon via their identifiers. However, when the actual object is required, it can

2056 Customization Guide


be gotten from the object reference which may or may not be currently holding the
object. If the object reference does not hold the object and the object is asked for,
the object is refreshed via its query key from the database.

Windchill Design Patterns 2057


The Business Service Design Pattern

This pattern has the following major kinds of abstractions:


• Type
• Cookie
• Helper
• Service
• ServiceEvent
• ServiceException
• ServiceFactory

2058 Customization Guide


Type
The Type abstraction provides an interface for means to type an object as being of
a particular kind. This interface is what the service expects to deal with in terms of
input and output, other than additional information. An object that does not
specify it is of a certain type cannot statically be used by the service and thus is
rejected at compile-time. In general, a Type is a kind of persistable object.

Cookie
The Cookie abstraction provides a class that is used to specify the information to
be associated with and stored as a part of the typed object. When an object asserts
itself as being a Type, the Cookie and its attributes, including all nested attributes,
are code generated into the object along with applicable accessors. If a Cookie’s
cardinality is 0..1, the Cookie and all its nested attributes can be stored as null if
none of the Cookie’s attributes are required. If any of the simple, or structured,
attributes of the Cookie are constrained to be non-null in the database, the Cookie
is forced to be non-null.

Helper
The Helper abstraction provides a class representing the service’s external
interface from which all visible functionality can be invoked. The helper is
intended to specify only static methods and attributes which any other class can
access without having to create any instances. The static methods are typically
Cookie accessors.

Service
The Service abstraction provides an interface that specifies the main functionality
of the service itself, which may or may not be invoked remotely if the interface is
annotated with the @RemoteInterface. Otherwise, the service’s interface will
be available only locally in the server. This interface must be adhered to and
implemented for the service to function properly. Additionally, a standard
implementation of the service’s methods exists. This standard implementation is a
singleton executing on the server and is the default for all Windchill services.

ServiceEvent
The ServiceEvent abstraction provides a common definition of an event that can
be emitted from the service and cause another service to be notified of the event.
This event specifies one or more kinds of occurrences that are used to generate
keys for listeners. Because these specific kinds of occurrences are extremely
simple in nature, only one event per service that defines all occurrences is
specified.

Windchill Design Patterns 2059


ServiceException
The ServiceException abstraction provides a common definition of an exceptional
condition that may occur as a result of abnormal behavior in the service. This
exception, along with the service’s resource bundle, can be used exclusively to
throw any and all kinds of errors. However, it may be appropriate, but not
necessary, to specialize this exception for more explicit and applicable errors.

ServiceFactory
The ServiceFactory is a utility to look up implementations of Windchill service
interfaces. The ServiceFactory is primarily intended for remotely invokable
services, but can also be used for server-side services (such as
PersistenceManagerSvr).

2060 Customization Guide


The Master-iteration Design Pattern
The design pattern that you must adhere to for all versioned data is the master-
iteration design pattern.

Master-Iteration Pattern
This pattern typically establishes two objects that work in concert with one
another. Without one, the other should not exist and is certainly invalid. At the
root are the basic abstractions:
• Mastered
• Iterated
The Mastered interface provides an abstraction of a plug-and-play component in
conjunction with the Iterated interface. The intent is that, in a business model, an
object would assert that it is a master by inheriting the Mastered interface. With
this assertion, the business object can then be mastered through the version control
service’s API. The business object must assert itself as being a kind of mastered
object in order for its instance to be iterated.

Windchill Design Patterns 2061


The Iterated interface provides an abstraction of a plug-and-play component in
conjunction with the Mastered interface. The intent is that, in a business model, an
object would assert that it is an iteration (instance) by inheriting the Iterated
interface. With this assertion, the business object can then be incrementally
superseded, rolled back, and rolled up through the version control service’s API,
provided it has a master. The business object must assert itself as being a kind of
Iterated object in order for it to be incrementally changed.
The next level of master-iteration pairs defines abstract entities that start pulling
together (that is, assert) all applicable capabilities from a general [virtual]
enterprise perspective. The level below starts becoming more concrete where the
EnterpriseItemMaster is concrete but the EnterpriseItem is not. It is at this level
where the association between master and iteration is overridden with the exact
named roles. However, it should be noted that cardinality of the iterations within a
master can be specialized to be further constrained. Also, this association again
specifies itself as a foreign key and the master can be auto-navigated from the
iteration. Thus, when an iteration is fetched from the database, its master is
fetched as well in one SQL statement via a database view.
Note that the iteration at this level need not be concrete for an association of this
kind with the foreign key, and auto-navigation on the concrete class can have the
other side as an abstract class.
At the very bottom, all of the concrete specializations of the EnterpriseItem exist.
All of these specializations inherit the foreign key, auto-navigate association from
EnterpriseItem. And thus, each is generated with a specific database view such
that three database views are generated for EnterpriseItem1, EnterpriseItem2, and
EnterpriseItem3.

2062 Customization Guide


55
Internationalization and
Localization
Background .......................................................................................................... 2064
The Windchill Approach ......................................................................................... 2065
Localizing Text Visible to the User........................................................................... 2067
Resource Info (.rbInfo) Files ................................................................................... 2071

Internationalization is the process of designing and developing an application that


can be easily adapted to the cultural and language differences of locales other than
the one in which the application was developed. Localization is the process of
adapting an application to fit the culture and language of a specific locale.
All Windchill applications are fully internationalized and ready to be localized.
Windchill applications are delivered with a default locale of US English (en_US).
This chapter describes how to localize text visible to the user by using resource
bundles.

2063
Background
Changing an application for use in another country or culture is often thought of
as merely translating the language that appears in the user interface. There are
many other aspects, however, that you should consider when developing a global
application.
• How will you identify the preferred language and geographic location of the
user-
You may want to design into the application (or underlying product
architecture) the ability to determine the locale and present the appropriate
version from a collection of different localized versions.
• What data used within your application is sensitive to locale-
Consider the use of decimals within numbers, currency symbols, date formats,
address styles, and system of measurement.
• How should data be formatted-
Consider the order in which text and numbers are read by different audiences.
Languages that display numbers from left to right and text from right to left
affect the layout of menu bars and text entry fields. The grammar of a
language may dictate different placement of variables in error messages.
• Collation of sortable lists
Consider how different alphabets affect the collation sequence and how
collation of typical list elements is done in the locales of potential users of
your application.
• Non-Roman alphabets
Your application must be able to accommodate different fonts and different
sizes of fonts. This again can affect the layout of menu bars and text entry
fields.
• What are the cultural sensitivities toward graphics and use of color-
When designing icons or other graphics, and deciding on background and
other colors, consider whether they may be objectionable in another culture
Both client and server developers need to be aware of these factors. You must be
able to localize not only the GUI, but also feedback messages and exceptions that
might be displayed to the user.

2064 Customization Guide


The Windchill Approach
Rather than try to keep all these preceding factors in mind and accommodate them
individually as you develop an application, the best approach is to isolate any
language- or locale-dependent code from the language-independent code (that is,
the application’s executable code). Windchill is designed to allow you to do this.
Windchill takes advantage of many Java features that support international
applications:
• Locale class
Each locale-sensitive object maintains its own locale-specific information. The
initial default for locale is specified in the system but users can specify a
preference in the Web browser.
• Resource bundles
In a resource bundle, you define pairs of keys and values, where the values are
strings and other language-dependent objects for a specific locale. Within
code, you use the key to indicate where the corresponding string or object
should be inserted. For example, Windchill uses resource bundles in its online
help and to identify button names, field names, and other elements of graphic
user interfaces. The default or preferred locale specifies which resource bundle
to use and, therefore, determines which strings and objects to display. (An
example is shown later in this chapter.)
Windchill uses a structured properties file format to manage much of the
localizable text. Unlike the java.util.PropertyResourceBundle properties files,
these resource info files are not used at runtime. They are more like java.util.
ListResourceBundle java files, where they are used to manage the information,
and runtime resource bundles are built from them. These resource info files
have a .rbInfo file extension. This format is required for managing the
localizable information for EnumeratedTypes and display names for metadata,
since these localizable resources are updated by generation tools. The resource
info format can be used for storing other localizable text, but it is not
mandatory.
• Unicode
This is a 16-bit international character-encoding standard. A character
encoding is a numeric representation of alphanumeric and special text
characters. A multi-byte encoding is necessary to represent characters such as
those used in Asian countries. The intent of Unicode is to be able to represent
all written languages in the world today.
• Localized text manipulation

Internationalization and Localization 2065


The Java classes java.io.inputStreamReader and java.io.OutputStreamWriter
provide the mechanism to convert standard character encodings to Unicode
and back, thus enabling the translation of characters to and from platform and
locale-dependent encoding.
• Handling local customs
The java.text package provides classes that convert dates and numbers to a
format that conforms to the local conventions. This package also handles
sorting of strings.
○ java.text.NumberFormat. formats numbers, monetary amounts, and
percentages.
○ java.text.DateFormat contains the names of the months in the language of
the locale and formats the data according to the local convention. This
class is used with the TimeZone and Calendar classes of the java.util
package. TimeZone tells DateFormat the time zone in which the date
should be interpreted and Calendar separates the date into days, weeks,
months, and years. All Windchill dates are stored by the server in the
database based on a conversion to Greenwich Mean Time.
To display Timestamps in the correct Timezone, the application
programmer should use wt.util.WTContext to set the Timezone in the
DateFormat as follows:
DateFormat df = DateFormat.getDateTimeInstance(
DateFormat.SHORT,
DateFormat.SHORT,WTContext.getContext().getLocale()
);
df.setTimeZone(WTContext.getContext().getTimeZone());
System.out.println("The current time is: " +
df.format(new Timestamp(current_time_millis)));
○ java.text.Collator can compare, sort, and search strings in a locale-
dependent way.

2066 Customization Guide


Localizing Text Visible to the User
Windchill provides internationalized applications with US English (en_US) as the
default locale. We recommend that you provide a localized resource bundle for
every other locale that you support.
Resource bundles are used to hold information, generally text, that you may want
to modify based on your locale. A resource bundle is a hash table of key/value
pairs, where the values are specific to the locale. Every package should have a
resource bundle. The Windchill naming convention is as follows: <your
package name>.<pkg>Resource.class
Implementation classes have a generated constant, RESOURCE, to identify their
fully qualified resource bundle class.
Resource bundles are loaded at runtime based on the system setting or user-
specified preference for locale. To load the resource bundle, a Java program calls
java.util.ResourceBundle.getBundle, specifying the base name of the desired
ResourceBundle. For example, the algorithm to find a ResourceBundle
named fc.fcResource is as follows:
1. Search for a class with the name fc.fcResource_language_country_variant.
2. Search for a class with the name fc.fcResource_language_country.
3. Search for a class with the name fc.fcResource_language.
4. Search for a class with the name fc.fcResource.
All Windchill resource bundles are provided for the default locale en_US.
Because these resource bundles are specified by the base name, they have no
extension.
Because IDEs may generate code to handle graphical components and
interactions, do not put references to resource bundles in sections that have been
generated. If you make any changes and regenerate the code, those references will
be lost. Instead, create a localize method that overrides the hard-coded label with
the appropriate label from a resource bundle and put it outside the generated code
area.
The following example shows how to make visible text locale dependent. For
example, within the localize method, the line:
lblUser.setText(RB.getString("lblUser") + ":");
associates the label defined internally as lblUser with the string found in the
resource bundle that corresponds to the lblUser key; that is,
{"lblUser","User"},
The string "User" is then displayed in this label.
static ResourceBundle RB;

public void addNotify() {

//Localize

Internationalization and Localization 2067


localize();

//{{DECLARE_CONTROLS

//}}

//{{DECLARE_MENUS

//}}

private void localize() {

RB=ResourceBundle.getBundle("wt.clients.administrator.LabelsRB"
,getLocale());

lblUser.setText(RB.getString("lblUser") + ":");
btnSearch.setLabel(RB.getString("btnSearch"));
btnCreate.setLabel(RB.getString("btnCreate"));
btnUpdate.setLabel(RB.getString("btnUpdate"));
btnAddUsertoGroup.setLabel(RB.getString
"btnAddUsertoGroup"));
btnView.setLabel(RB.getString("btnView"));
btnDelete.setLabel(RB.getString("btnDelete"));
btnClose.setLabel(RB.getString("btnClose"));
try {
//MultiList column headings
java.lang.String[] tempString = new java.lang.
String[4];
tempString[0] = RB.getString("Full Name");
tempString[1] = RB.getString("UserID");
tempString[2] = RB.getString("Web Server ID");
tempString[3] = RB.getString("E-Mail");
lstUsers.setHeadings(tempString);
}
catch (PropertyVetoException e) {}

}
(If using rbInfo files, See Resource Info section below.)
package wt.clients.administrator;

import java.util.ListResourceBundle;

public class LabelsRB extends java.util.ListResourceBundle

2068 Customization Guide


{

public Object getContents()[][] {


return contents;
}

static final Object[][]contents = {


//Labels
{"lblAdministrative","Administrative"},
{"lblAllGroups","All Groups"},
{"lblAttach","Attach"},
{"lblAuthorization","*Web Server ID"},
{"lblBelongs","Groups User Belongs to"},
{"lblCity","City"},
{"lblCountry","Country"},
{"lblCreate","Create"},
{"lblCreated","Created"},
{"lblDelete","Delete"},
{"lblDescription","Description"},
{"lblEmail","E-Mail"},
{"lblFullName","Full Name"},
{"lblGroup","Group"},
{"lblGroupName","Group Name"},
{"lblID","*ID"},
{"lblLocale","Locale"},
{"lblModify","Modify"},
{"lblName","Name"},
{"lblRead","Read"},
{"lblState","State"},
{"lblStreet1","Street1"},
{"lblStreet2","Street2"},
{"lblTitle","Title"},
{"lblUse","Use"},
{"lblUser","User"},
{"lblUserName","User Name"},
{"lblZip","Zip"},
//Button Labels
{"btnAdd","Add>>"},
{"btnAddAll","Add All>>"},
{"btnAddRemove","Add/Remove Members"},
{"btnAddUsertoGroup","Add User to Group"},
{"btnApply","Apply"},
{"btnCancel","Cancel"},
{"btnClear","Clear"},
{"btnClose","Close"},
{"btnCreate","Create"},
{"btnDelete","Delete"},
{"btnGenerate","Generate Now"},
{"btnNewGroup","New Group..."},
{"btnNewUser","New User..."},

Internationalization and Localization 2069


{"btnOK","OK"},
{"btnRefresh","Refresh"},
{"btnRegenerate","Regenerate"},
{"btnRemove","<
{"btnRemove","<
To create a different localization for this resource bundle, for example, French,
you would create a new class in the wt.clients.administrator package
called LabelsRB_fr. This class would contain the same label keys, such as
"lblAdministrative" but its value would be "administratif" rather
than "Administrative". All the other values would likewise be changed to
their French counterparts. You would compile the new class; then the Java runtime
would be able to find a French resource bundle for the Administrator client.

2070 Customization Guide


Resource Info (.rbInfo) Files
wt.L10N.complete
Resource Info files are an alternative to storing localizable text in
ListResourceBundle source code files. They are structured properties files that
facilitate easy manipulation by automated tools.
Resource info (or rbInfo for short) files are resource files used to store localizable
strings of Java programs. The primary purpose of the rbInfo files is to provide an
easier and more manageable way to handle localizable strings than resource
bundles. RbInfo files offer a number of advantages over resource bundles:
• Resource bundle files are Java source files, so that a single misplaced curly
bracket, missing double quote or extra comma will cause a syntax error and
break the compile and integration process. RbInfo files have much simpler
format, it is easier to localize and more difficult to introduce syntax errors.
• Because of the simpler format of the rbInfo files, it is easier to handle them
with localization tools; perform change tracking, change propagation and so
on.
• It is more difficult to abuse the rbInfo file format and introduce ’tricky’
resource types. Java resource bundles can hold any type of objects, but rbInfo
files can handle strings only. (This may appear to be a limitation, but it is not.
It makes localization easier.)
RbInfo files are converted to compiled Java class files in the integration process,
so that the same naming convention rules apply to rbInfos as resource bundles.
(Localized versions are kept in separate files; there is one resource file per
language, the name of the locale is appended to the name of the localized files.)
The format of the rbInfo files is PTC-specific. It was designed primarily for
Windchill, but can be used in other Java-based products as well. The migration
from resource bundles to rbInfo files is seamless; there is no need to change the
source code. Old resource bundles can be converted to rbInfo format using a
relatively straightforward process. To find out more about the migration, refer to
the Windchill Upgrade and Migration Guide.

Resource Info Categories


Localizable text is considered to be in one three categories for the purpose of
resource info file usage.

Internationalization and Localization 2071


Resource Type Source File Run-Time File
Message Text *RB.rbInfo*Resource. *RB.class*Resource.class
rbInfo
Modeled Metadata <package>ModelRB.rbInfo <package>ModelRB.RB.ser
(Display Names)
EnumeratedType <EnumType>RB.rbInfo <EnumType>RB.RB.ser
Options Definition

General Resource Info File Usage Rules


• A line beginning with ’#’ is considered a freeform comment.
• Each file must contain a header line that categorizes the file.
• Only String values are supported.
• Since values are assumed to be Strings, they should not be in quotes.
• Each entry must exist on a single line, and the following escaped characters
are supported: \\, \n, \r, \t, \f, \".
• Key cannot contain ’=’, since it is the key/value separator.
• Key cannot contain "#", since it is a comment character, but the character is
allowed in the value.

Resource Entry Format


The following keys define the structure of resource entries.
Key Description Usage
<key>.value The localizable text that Required
will be displayed.
<key>.constant A string that will be used Message text: Optional
to generate a constant Metadata: Unused
field into the runtime
resource bundle, which EnumeratedType: Unused
can be used by code that
does resource lookups.
<key>.comment A comment describing Optional
the entry.
<key>.argComment<n> A comment for each Optional
substitution argument of
the value string.
<key>.customizable Indicates whether the Optional
resource entry is

2072 Customization Guide


Key Description Usage
customizable.
<key>.deprecated Indicates (to the Optional
developer) whether the
resource entry is
deprecated.
<key>.abbreviatedDisplay Reserved for future use. Unused
<key>.fullDisplay Reserved for future use. Unused
<key>.shortDescription Reserved for future use. Unused
<key>.longDescription Reserved for future use. Unused
<key>.order Explicit sort order for the Message text: Unused
value, unused for alpha Metadata: Unused
ordering.
EnumeratedType:
Optional
<key>.defaultValue Specifies the value is the Message text: Unused
default value for the Metadata: Unused
Enumerated Type.
EnumeratedType:
Optional
<key>.selectable Specifies if the value Message text: Unused
should be allowed to be Metadata: Unused
selected.
EnumeratedType:
Optional

Resource Info File Descriptions by Category

Message Text
The Message Text category most commonly contains error messages and labels
for user interface actions, but is the general category for any localizable text that
does not fall into one of the other categories. The Message Text files are
completely user-maintained, while the maintenance of the entries in the other two
categories is automated via various generation tools. Since this category is not
maintained by automated tools, and since the resulting run-time bundle is the
same ListResourceBundle subclass that it would be if the information were stored
in a ListResourceBundle source code file, the use of .rbInfo file format is optional
for Message Text.
The following sections describe the resource info files for Message Text.

Internationalization and Localization 2073


Message Text Resource Info Header
Each resource info file must contain the following lines that define certain file
level information.
ResourceInfo.class=wt.tools.resource.StringResourceInfo
ResourceInfo.customizable=false
ResourceInfo.deprecated=false
The first line classifies the resource info and should never be changed. The values
of the second and third lines can be changed by the owner of the package, if the
file can be customized, and/or the file is deprecated.

Message Text Resource Entry Examples


//Labels

lblAdministrative.value=Administrative
lblAdministrative.constant=LBL_ADMIN
lblAdministrative.comment=administrative ui label

lblAllGroups.value=All Groups
lblAllGroups.constant=LBL_ALL_GROUPS

//Button Labels
btnAdd.value=Add>>
btnAdd.constant=BTN_ADD
btnAddAll.value=Add All>>
btnAddAll.constant=BTN_ADD_ALL

//MultiList column headings


Class.value=Class
Created On.value=Created On

Modeled Metadata (Display Names)


Resource Info files for modeled metadata are generated by the Windchill System
Generation Tool.

EnumeratedType Options Definition


Resource Info files for enumerated types are described in Enumerated Types on
page 1973 .

Building Runtime Resource Bundles for Resource


Info Files
Since the information is not stored in Java source code files, a tool other than the
Java compiler is needed to build the runtime resource bundles. This tool can be
executed by using the ResourceBuild script.

2074 Customization Guide


56
The Enterprise Layer
Enterprise Abstractions.......................................................................................... 2076
Document Abstractions.......................................................................................... 2083
Part Abstractions................................................................................................... 2086
Change Abstractions ............................................................................................. 2093

This chapter describes the classes and interfaces available in four packages:
• wt.enterprise
• wt.doc
• wt.part
• wt.change2
The classes provided in these packages were designed and intended for you to
extend as you customize Windchill for your own use.

2075
Enterprise Abstractions
The wt.enterprise package provides the basic business objects used in the
Windchill system. Most business classes you construct will be extended from the
enterprise classes or their subclasses.

The enterprise Package


Business classes should be extended from one of the abstract classes included in
the wt.enterprise package to take advantage of the capabilities and services they
offer. This diagram shows convenience classes designed to consolidate a basic set
of features that various business classes might require. Most of the business
classes in your model are expected to extend one of these classes and simplify
your implementations.

2076 Customization Guide


Simple Business Class
A simple business class is a first class information object that is subject to
business rules, such as access control. These objects have no managed life cycle
and are not organized into folders. Because these objects are not visible via
folders, they tend to be more administrative in nature (that is, created by
administrators but referenced by end users).

Simple Business Class

Folder Resident Business Class


A folder resident business class is a business object that resides in a folder.
Because these objects are accessible in folders, they are visible to users in the
Windchill Explorer. These objects are subject to access control rules.

The Enterprise Layer 2077


FolderResident business objects are not subject to life cycle management.
Therefore, they are more administrative in nature. All FolderResident objects
automatically record the principal (user) who created them.

Folder Resident Business Class

2078 Customization Guide


Managed Business Class
Managed business class objects are subject to a controlled life cycle. They reside
in folders for organizational purposes. They are non-revisable objects that the
system manages and controls via access control. These objects record the principal
(user) who created them. The creator can be used as a role in certain processing
for life cycle and workflow operations.

Managed Business Class

Revision Controlled Business Class


RevisionControlled business objects are identified by a revision identifier. They
are managed and changed via a checkin/checkout mechanism. They are subject to
life cycle management and other forms of management by the enterprise. They

The Enterprise Layer 2079


have a creator by virtue of being a Workable object (which is an Iterated object).
Because the class is also Versioned, there can be multiple business versions of the
Master object, such as revision A and revision B of a single document.

Revision controlled business objects are managed as two separate classes:


• Master
• Represents the version independent idea of a business concept. It contains the
information that identifies the business objects. Typically this is information
such as a name and number that remains constant for all versions (or, more
accurately, is the same for all versions).
• Revision controlled
Represents the successive changes to the business objects as it is developed
over time. A RevisionControlled object represents an official version (for
example, revision A or B) but also provides access to previous iterations of
that version. The previous iterations are considered a history of work-in-
progress activity (checkouts and checkins) for the object.

2080 Customization Guide


Iterated Folder Resident Business Class
IteratedFolderResident business class objects reside in folders where they are
visible to users of the Windchill Explorer. Users create new iterations of these
objects using checkout/checkin operations. They are also subject to access control
and automatically record the principal (user) who created them.
IteratedFolderResident objects are similar to RevisionControlled objects.
However, they are lighter weight objects in that they are neither versioned nor life
cycle-managed, as is the case with RevisionControlled objects.

Iterated Folder Resident Business Class

The Enterprise Layer 2081


Cabinet Managed Business Class
Cabinet managed business class objects are non-iterated, life cycle-managed
objects. Because cabinet managed business objects are not Foldered, they do not
reside in folders and are not visible to users of the Windchill Explorer. They are,
however, associated with cabinets for reasons of access control and local search.

Cabinet managed business class

2082 Customization Guide


Document Abstractions
The wt.doc package provides a standard implementation of managed documents.
A simplification of the document model is shown below. This simplification
shows some of the core interfaces that make up WTDocument and
WTDocumentMaster. These objects actually implement a number of interfaces to
acquire their behavior. To see the full scope of interfaces that are implemented by
these two objects go to the Javadoc for wt.doc.WTDocument and wt.doc.
WTDocumentMaster.

Doc Package
The document classes are implemented based on the pattern established for
revision controlled objects in the wt.enterprise package. These classes,
WTDocumentMaster and WTDocument, provide concrete classes exhibiting the
management characteristics established in wt.enterprise and add specifics for
documents. The properties of a document are specified on the WTDocument class.
Then, for normalization purposes, the sum of the properties are stored on the
WTDocumentMaster. More specifically, WTDocument implements Format
ContentHolder to give it a primary content item and multiple secondary content

The Enterprise Layer 2083


items. WTDocument can create two types of relationships to other documents.
The first, WTDocumentUsageLink, is similar to the WTPartUsageLink in that it
also subclasses IteratedUsageLink. It does not have a quantity.
WTDocumentUsageLink is used to create uses relationships between documents
or document structure. Documents should use this if a document is made up of
sub-documents and the sub-documents can be reused by other documents, or need
to be controlled separately. Similar to the part implementation, the
WTDocumentService has convenience methods for navigating this relationship
and there is a WTDocument ConfigSpec to filter results. The second,
WTDocumentDependencyLink implements IteratedDescribeLink which is also
implemented by WTPartDescribeLink. This is a version-specific relationship
between two documents. This relationship is shown in the client as references. A
reference between two documents can be created to show a dependency on
another document. A document may reference some information in another
document, so during a create or update, a reference to that document is added. The
references relationship has a comment attribute that can be used to explain why
the reference exists or what the dependency is. WTDocument Service also has
convenience methods for navigating the WTDocumentDependencyLink.
The doc package is an example of implementing a Revision Controlled Business
subclass. The concrete document business classes inherit from the Revision
Controlled Business model (Master and RevisionControlled) template in the
enterprise model. Document inherits most of its functionality from the enterprise
object RevisionControlled. RevisionControlled pulls together many plug and play
functionality interfaces. To see the full list of interfaces go to wt.enterprise.
Revisioncontrolled in the javadoc. In particular, it includes interfaces from the
content package. This means that a WTDocument is a content holder; that is, it
can have files or URLs included in it.
Attributes are on either WTDocumentMaster or WTDocument. Attributes on
WTDocumentMaster have the same value for all versions and iterations. If an
attribute on the master changes after several versions and iterations have been
created, the change is reflected in all the versions and iterations. Attributes on
WTDocument can generally have different values for each iteration, so changes
impact only one iteration. This is why content holder is implemented on
DocumentIteration.

Attributes Specific to Windchill Foundation & PDM


The docType attribute of a document is held in common for all iterations and
versions. It is stored in the WTDocument merely to allow for database partitioning
based on the document type attribute. Customers wishing to create new document
types will add values to the DocumentType resource bundle.
The DocumentType resource bundle defines all the types of documents. When
users construct documents, they may pick a document type from the enumerated
list. Customers may add new document types to the list by putting additional

2084 Customization Guide


values in the resource bundle. A "$$" prefix on a document type means it is a
Windchill-provided document type. The "$$" prefix should not be used for
customer types.
Using the DocumentType resource bundle, it is possible to construct new types of
documents that users can pick from. This has the following impacts from an
administrative perspective:
• Administrative rules do not recognize the new document types. Therefore, all
document types are the same from an administrative perspective; they receive
the same access control and indexing rules.
• From a workflow point of view, the docType property can be used as an
activity variable for workflow branching logic.
To add new document types that can have different administrative controls, the
WTDocument class must be extended. Subclassing of WTDocument also is
preferable if there are specific associations in which only some documents can
participate. These kinds of rules are difficult to specify without subclassing
WTDocument. Use the following rules when extending WTDocument:
• For every new child of WTDocument, you must make a corresponding entry
in the DocumentType resource bundle. This ensures that the
WTDocumentMaster object for each WTDocument child knows the type for
its document version.
• When adding new classes of documents, it is not necessary to extend the
WTDocumentMaster class, only the WTDocument class. All children classes
of WTDocument can share the same WTDocumentMaster class.
• Follow the constructor pattern established in WTDocument. Override the
appropriate initialize methods from WTDocument, invoking super.initialize()
and then performing your class specific logic. Specifically, invoke the method
initialize(number, name, type) where type is substituted for a value that has
been added to DocumentTypeRB.java.
Department is implemented as an enumerated type attribute or a valid value list.
The valid values are defined in the wt.doc.DepartmentListRB.java file. The values
in DepartmentListRB.java can be changed, the file compiled, and replaced in the
codebase. For further information, seeEnumerated Types on page 1973.

The Enterprise Layer 2085


Part Abstractions
The wt.part package provides a standard implementation of parts. A part is an
item that can be produced or consumed, such as, an engine, a bolt, or paint. Parts
can be assembled to produce other parts; for example, the drive train of an
automobile can be thought of as a part composed of an engine, transmission, shaft,
differential, and so on.

Design Overview
The following figure illustrates the basic concepts encapsulated by the Windchill
part reference implementation.

Part Reference Implementation


The part classes are implemented based on the pattern established for revision
controlled objects in the wt.enterprise package. These classes, WTPartMaster and
WTPart, provide concrete classes exhibiting the management characteristics
established in wt.enterprise and add specifics for parts. The properties of a part are
specified on the WTpart class. Then, for normalization purposes, the sum of the
properties are stored on the WTPartMaster.
The part package is an example of implementing a Revision Controlled Business
subclass. The concrete part business classes inherit from the Revision Controlled
Business model (Master and RevisionControlled) template in the enterprise
model. Part inherits most of its functionality from the enterprise object
RevisionControlled. RevisionControlled pulls together the following plug and
play functionality: Foldered, Indexable, Notifiable, DomainAdministered,
AccessControlled, BusinessInformation, LifeCycleManaged, Version, Workable,
and Changeable.

2086 Customization Guide


Attributes are on either WTPartMaster or WTPart. The WTPartMaster, as a
Mastered object, represents the part’s identity. As such, "number" and "name"
have been placed on it. The part’s number is the stamp the enterprise recognizes
and uses for tracking purposes. The name is the human-readable component.
These properties of the part are assigned carefully and rarely changed.
Attributes on WTPartMaster have the same value for all versions and iterations. If
an attribute on the master changes after several versions and iterations have been
created, the change is reflected in all the versions and iterations.
The WTPart, as a Versioned and Workable object, undergoes change that is
recorded in its versions and iterations as a result of a check-out and check-in
process. Attributes on WTPart can generally have different values for each
iteration, so changes impact only one iteration.
An iteration occurs every time a part is checked out and in. It can be viewed as a
working copy of the part. Iterations are assumed to happen many times between
versions. Versions, however, represent a business increment; that is, an approved,
major change to a part. A typical scenario is that version A of a part is approved
and put into production. Then a change is determined to be necessary. The part
goes through many iterations while the change is being investigated and tested.
Finally, version B is approved.
Also, being ViewManageable, WTPart can be assigned to views, allowing it to
progress through stages of development, such as engineering and manufacturing
stages. It resides in folders, is subject to access control, progresses through life
cycles, and is part of the change process as a consequence of being
RevisionControlled. It can also be assigned to baselines to preserve a specific
implementation and its versions can be made effective to indicate to a
manufacturing process what to build.
Although shown in the preceding figure, WTPart is no longer a ContentHolder by
default. The capability to hold files and URLs still exists, but it is no longer
exposed to the user.
The WTPart also contains as aggregated properties a source and a type (as shown
in the following figure).

WTPart Properties

The Enterprise Layer 2087


The source can be used to indicate how the part is procured, for example by being
made or bought. The type specifies how it can be decomposed, for example by
being separable (is assembled from components that can be taken apart to be
serviced), inseparable (is assembled, but can not be disassembled), or component
(is not assembled). The values of these properties can be altered by editing their
resource bundles.
Also, note that number and name are modeled as derived and are implemented to
set and get the real values from its WTPartMaster. The DerivedFrom property in
the Windchill tab of the attribute specification has been used to indicate that it has
been derived from the master’s attributes by specifying the database derivation;
also, the getters and setters have been overridden in a manner similar to the
following:
((WTPartMaster) getMaster()).get/set...(...)

WTParts can use other parts to build assemblies using the WTPartUsageLink as
shown in the following figure.

Building Assemblies with the WTPartUsageLink


The WTPartUsageLink is a type of IteratedUsageLink, an association defined to
be used to build structures. The WTPartUsageLink’s aggregated Quantity can be
used to indicate the amount of the component that is being consumed. The
QuantityUnit’s values can be altered by editing its resource bundle.
The WTPartUsageLink can be navigated using the PersistenceManager’s navigate
APIs, or even the StructService’s navigateUses and navigateUsedBy APIs. Be
aware that navigating the usedBy role results in the returning of all part iterations;
StructService’s navigateUsedBy API returns only versions. However, the
StructService’s APIs navigate using the IteratedUsageLink as its target; the
WTPartUsageLink might not be the only IteratedUsageLink in a customization.
We recommend using the APIs in the following figure.

2088 Customization Guide


Navigating the WTPartUsageLink
getUsesWTParts navigates to the WTPartMaster and resolves WTParts from the
masters using a WTPartConfigSpec, returning a QueryResult of Persistable[]’s in
which the WTPartUsageLink is in the 0th position and the WTPart/WTPartMaster
in the first getUsesWTPartMasters simply navigates the WTPartUsageLink and
returns a QueryResult of WTPartUsageLinks. Finally, getUsedByWTParts returns
a QueryResult of WTParts (the versions, not simply all iterations) representing the
implementations that call out the part.
WTParts can also reference documents (see the following figure).

WTPartReferenceLink and Navigate API


Parts generally reference documents for one of two reasons:
• The part is not the logical owner of a document. An example of such a
document is a standards document. A standards document is independent of a
part, but may be used to verify conformance to the document.
• A document (file) is conceptually owned by the part, but must be separately
life cycle managed, checked in and out independently of the file, and so on.
Note that the WTPartReferenceLink may not be appropriate if the document’s
versions are not necessarily interchangeable from the perspective of the
WTPart. If a specific version of a document should be linked to a specific
version of a part, use the DescribedBy link (as described later in this section)
instead.
The WTPartReferenceLink can be navigated using the WTPartService’s
getReferencesWTDocumentMasters API.
A WTPart can also be linked to a document that describes it on a version-specific
level using WTPartDescribedByLink. An example of such a document is a CAD
drawing that shows exactly how a specific version of a part is designed and should
be built. If a change is made to the part and a new version created, the revised
version of the CAD drawing, that reflects that change, should be linked to the new
part using the DescribedBy functionality.

The Enterprise Layer 2089


To summarize, a reference should be considered supplemental information that is
useful but not required. It is likely to have its own life cycle and change
independently of the part referencing it. A document linked to a part by a
DescribedBy link contains information you may need specifically for that version
of the part. A specific version of the document is linked to a specific version of
the part.
The WTPartConfigSpec was alluded to by the getUsesWTParts API. It is used by
the Product Structure Explorer during its navigations. It consists of three
ConfigSpecs: the WTPartStandardConfigSpec, the WTPartEffectivityConfigSpec,
and the WTPartBaselineConfigSpec (as shown in the following figure).

WTPartConfigSpec
A concept of zones has been added to the WTPartConfigSpec to determine which
ConfigSpec is active at any given time. The WTPartConfigSpec is stored, one per
principal, using the WTPartService’s APIs listed in the following figure.

Finding and Saving the WTPartConfigSpec


The ConfigSpecs aggregated by the WTPartConfigSpec have the following
behavior:
WTPartStandardConfigSpec
When active, WTParts are filtered based on their state and their view
membership. workingIncluded can be used to allow users to toggle between
their working copies and their checked-out versions.
WTPartEffectivityConfigSpec
When active, allows the user to see structures based on effectivity and view.
Only WTParts designated as effective are shown (see the wt.effectivity
package for additional information).

2090 Customization Guide


WTPartBaselineConfigSpec
When active, displays only those WTParts assigned to the specified baseline
(see the wt.vc.baseline package for additional information).
Parts can often be replaced by other parts, either globally or in the context of an
assembly. This interchangeability is used to indicate that one part is equivalent to
another in a given situation. The WTPartAlternateLink (shown in the following
figure) is used to indicate global interchangeably, while the WTPartSubstituteLink
indicates interchangeability within the context of an assembly. Note that the
WTPartSubstituteLink is copied whenever the WTPartUsageLink is copied.

Alternate and Substitute Links


Both of these links can be navigated using the Persistence Manager’s navigate
APIs. In addition, the WTPartService offers getAlternatesWTPartMasters and
getAlternateForWTPartMasters methods for navigation of WTPartAlternateLinks
and getSubstitutesWTPartMasters and getSubstituteForWTPartUsageLinks
methods for navigation of WTPartSubstituteLinks. Both WTPartAlternateLinks

The Enterprise Layer 2091


and WTPartSubstituteLinks are access controlled, so permission to perform
operations such as creation and deletion of links is defined using the access
control service.
The Part, PartMaster, and PartIteration classes modeled in the wt.part package (see
the following figure) are placeholders for future functionality.

Placeholders

2092 Customization Guide


Change Abstractions
The change2 package includes the basic service methods and change item classes
necessary to support change management. The change management module
provides the means by which users can identify, plan, and track changes to the
product information managed by the Windchill product data management system.

Note
The change2 package replaces the change package available in releases prior
to Release 4.0.

The following figure shows the five conceptual steps in the change management
process.

Change management process


To understand the Windchill change management object model, it is important to
understand these conceptual steps, as described below. Although the order of these
steps is not fixed, they are presented here in a logical sequence.
Describe symptoms
The symptoms of a perceived problem are recorded. The person experiencing
the symptoms could be an internal employee, a customer, or any other end
user or person. This person records the symptoms.
Pursue formal change
At some point, the group of symptoms is evaluated. A formal decision is made
to investigate the symptoms.

The Enterprise Layer 2093


Identify problem pause
By investigating the symptoms and performing analysis, the root cause of the
problem is determined. As part of this work, the person investigating the
problem may identify relevant parts or documents.
Propose solution
A course of action to fix the problem is proposed. As part of this work, the
person preparing a solution may identify relevant parts or documents.
Implement solution
A solution is chosen and implemented. As part of the implementation work,
the users of the change process identify part or document revisions, both old
revisions (that is, those that require a change) and new revisions (that is, those
that have been changed). This step includes the incorporation of the solution
into production, if appropriate.

Change Item Classes


The following figure shows the model for the change classes provided by
Windchill’s change management module.

Change Management Class Model

2094 Customization Guide


The following figure shows the relationship between the change item classes and
the change management process shown earlier.

Change Management Process and Related Classes


Following are descriptions of the available change objects:
Change issue
A change issue holds information about the problem’s symptoms. A change
issue can be thought of as a suggestion box.
Change request
A change request is the object that organizes the other change objects. It
represents a formal, traceable change. This object can be associated with
product data versions (for example: parts, products, product instances,
documents, or CAD documents).
Change investigation
A change investigation organizes the information pertaining to the root cause
of the problem. It is used when the root cause is not trivial or obvious. If the
research to determine the root cause is very detailed or complicated, analysis
activities are used to organize the effort into logical work breakdowns.
Change proposal
A change proposal organizes the information pertaining to a solution for the
problem. It is used when the problem solution is not trivial or obvious. If the
research to determine the solution is very detailed or complicated, analysis
activities are used to organize the effort into logical work breakdowns.

The Enterprise Layer 2095


Analysis activity
An analysis activity is used in conjunction with either a change investigation
or a change proposal. When the cause of the problem is complex, an analysis
activity helps to further organize a change investigation. When the solution to
a problem is complex, an analysis activity helps to further organize a change
proposal. This object can be associated with product data versions that are
relevant to the analysis work.
Change order
A change order is created if a change proposal is chosen for implementation.
Change activity
A change activity serves as the work breakdown for a change order. This
object can be associated with product data versions for two distinct reasons:
the product data is defective or otherwise must be changed, or the product data
version is a result of a change. This allows users of the system to track the
reason for change to product data.

Associations with Product Information


A changeable is a PDM object whose changes can be tracked by the change
management system. These are referred to as product data versions to the end
user. The term product data version appears on the Change Management user
interface rather than the term "changeable." At this release, Windchill parts,
products, product instances, documents, and EPM documents are the only
changeables, as shown in the following figure.

Changeable Objects

2096 Customization Guide


The change management model defines four distinct relationships between change
objects and changeables. Any number of changeables can be associated with each
of the relationships. In the following figure, one part and one document is
associated to the change object in each case. Also shown is a relationship between
a change request and a product master, which is not changeable.

Relationships to Product Information


The following are the four relationships between change objects and changeables
and the relationship between a change request and a product master.
Relevant request data
The relevant request data association identifies changeables that are relevant
the change request for any reason.

The Enterprise Layer 2097


Relevant analysis data
The relevant analysis data association identifies changeables that are relevant
to the analysis for a change investigation or change proposal.
Affected activity data
The affected activity data association identifies changeables that must be
changed to satisfy a change activity.
Change record
The change record association identifies changeables that have been changed
as a result of a change activity.
Subject product
The subject product association identifies product masters that are the subject
of the change request. Product masters are not changeables and may not be
directly affected by the change request.
To summarize, relevant request data and relevant analysis activity data identify
versions that might change, affected activity data identifies old (or defective)
revisions which have been superseded, and change record identifies new (or
improved) revisions. Also, subject product identifies product masters that are the
subject of a change request, but are not necessarily affected themselves. The
following figure shows a UML class diagram representing these associations:

Associations Class Diagram

2098 Customization Guide


Change Item Modeling Approach
Each change management object is modeled using a three-tiered approach:
interface, abstract class, and concrete class, as shown in the following figure:

Change Item Modeling Approach


Interface layer
The interface classes simply implement the Persistable interface to indicate
that the change management classes are objects stored by Windchill.
Abstract classes
The abstract classes implement various Windchill plug and play interfaces and
enterprise package classes to obtain standard Windchill functionality. Each
abstract class implements ContentHolder, which provides the ability to attach
files. In addition, each abstract class extends either Managed or
CabinetManaged (see the enterprise package, earlier in this chapter for an
explanation of these classes). The abstract classes also contain modeled
associations among change objects, and between change objects and product
information objects.
Concrete classes
The concrete classes contain modeled business attributes.

Change Items Classes


The following sections show the models for the change item classes. Because
many attributes are common, descriptions of all the attributes defined on these
items are shown at the end of this section under Change Item Attribute
Descriptions on page 2105.

The Enterprise Layer 2099


Change issue
The following figure shows the model for change issues:

Change Issue Model

2100 Customization Guide


Change Request
The following figure shows the model for change requests:

Change Request Model

The Enterprise Layer 2101


Change Investigation
The following shows the model for change investigations:

Change Investigation Model

2102 Customization Guide


Change Proposal
The following figure shows the model for change proposals:

Change Proposal Model

Analysis Activity
The following figure shows the model for analysis activities:

The Enterprise Layer 2103


Analysis Activity Model

Change Order
The following figure shows the model for change orders:

Change Order Model

2104 Customization Guide


Change Activity
The following figure shows the model for change activities:

Change Activity Model

Change Item Attribute Descriptions


The following is a list of the attributes on change manager items:
category
The category to which the change object belongs. The category identifies the
general reason for the suggested change (for example, a cost reduction, quality
improvement, or safety issue).
complexity
The complexity of the change object.
description
A description of the change object.
issuePriority or requestPriority
The priority of the change object.
name
The summary of the change object. This attribute is displayed on the user
interface as “summary.”
needDate
The target date by which the change object should be resolved and closed.

The Enterprise Layer 2105


number
The automatically generated number of the change object.
requester
The user who created the change object.
results
The results of the change investigation or change proposal.

2106 Customization Guide


57
Persistence Management
Persistence Datastore Sequence Customization...................................................... 2108

This chapter describes persistence management.

2107
Persistence Datastore Sequence
Customization
Objective
You want to create a new datastore sequence for use in Windchill.

Background
Windchill uses datastore schema objects to implement a sequence. In Oracle, this
is implemented directly as a sequence schema object. In SQLServer, this is
implemented as a table and access stored procedure.

Scope/Applicability/Assumptions
• This documentation assumes that you have access to the Windchill datastore
directory, <WindchillHome>/db, and access rights to execute DDL scripts
in the target datastore.
• For the modeled customization procedure, it is assumed that the Windchill
Java Annotations support for sequences has been successfully installed and
configured.

Intended Outcome
The end result of this solution is the creation of a datastore sequence.

Solution
Model a sequence class usingWindchill Java Annotations.

Solution Elements
Element Type Description
<MySequence> Java class The class for representing
a datastore sequence in
Windchill.

Procedure - Creating a Modeled Datastore Sequence


1. Create a class <MySequence> in <MyPackage> that extends
<MySequence> .
2. Specify the “GenAsDatastoreSequence” annotation and sequence
properties as the annotation’s arguements. Specify the initial seed and

2108 Customization Guide


increment values if the defaults are not sufficient. For example, for seed value
1000 and increment 100, the resulting Java source file would be as follows:
import com.ptc.windchill.annotations.metadata.GenAsDatastoreSequence;

@GenAsDatastoreSequence (objectName="mySequence", seed=1000, increment=100)


public class MySequence extends _MySequence {
}
3. Compile the <MySequence>.java class in <MyPackage>.
4. Generate the DDL scripts.
5. Execute the sequence DDL. From a Windchill shell execute:
<WindchillHome>/db/execute_sql_script.bat
<MyPackage>/create_<MySequence>_ sequence.sql

Customization Points

Procedure — Creating a Non-modeled Datastore Sequence


in Oracle
When a non-modeled sequence is created, the database schema objects are not
included in the Windchill introspection information. Therefore, some tools that
rely on this information (e.g.Windu, upgrade tools) will treat these objects as
unrelated to Windchill.
1. Create the sequence DDL script "create_<MySequence>_
sequence.sql" in "<WindchillHome>/db/sql" directory. For multi-
byte systems, use directory, "<WindchillHome>/db/sql3".
2. Add the following lines to this script, substituting <MySequence>,
<MySequenceSeed>, and <MySequenceIncrement>.
exec WTPK.createSequence('<MySequence>', <MySequenceSeed>,
<MySequenceIncrement>)
3. Execute the sequence DDL. From a Windchill shell, execute :
<WindchillHome>/db/execute_sql_script.bat create_
<MySequence>_sequence.sql

Procedure – Creating a Non-modeled Datastore Sequence


in SQLServer
When a non-modeled sequence is created, the database schema objects are not
included in the Windchill introspection information. Therefore, some tools that
rely on this information (e.g.Windu, upgrade tools) will treat these objects as
unrelated to Windchill.

Persistence Management 2109


1. Create the sequence DDL script "create_<MySequence>_sequence.sql" in
"<WindchillHome>/db/sqlServer" directory.
2. Add the following line to this script, substituting <MySequence>,
<MySequenceSeed>, and <MySequenceIncrement>.
CREATE TABLE wt_sequence_<MySequence>(dummy
CHAR(1),
value BIGINT IDENTITY(<MySequenceSeed>, <MySequenceIncrement>))
go
CREATE PROCEDURE wt_get_next_sequence_<MySequence>
@returnValue BIGINT OUTPUT
AS
INSERT wt_sequence_<MySequence> (dummy) VALUES ('x')
SELECT @returnValue = SCOPE_IDENTITY()
go
3. Execute the sequence DDL. From a Windchill shell, execute
<WindchillHome>/db/execute_sql_script.bat create_
<MySequence>_sequence.sql <DB_USERNAME> <DB_PASSWORD>

Procedure - Obtaining the Next Value in a Modeled


Sequence
In the primary procedure above, a sequence class was created. To obtain the next
value in this sequence, use the
PersistenceManager.getNextSequence(Class) method passing
<MyPackage>.<MySequence>.class.

Procedure - Obtaining the Next Value in a Non-Modeled


Sequence
In the non-modeled procedures above, a sequence was created directly in the
datastore. To obtain the next value in this sequence, use the
PersistenceManager.getNextSequence(String) method passing
the string constant <MySequence>.

Limitations
None.

Sample Code

Examples of Usage in Windchill Code


Sequence values are used in many areas within Windchill code. See sub-class of
wt.fc.DatastoreSequence in Where-Used Tool and/or Javadoc.

2110 Customization Guide


Packaged Samples
None.

Non-modeled Sample Scripts


Oracle
The following is a sample script for a partNumber sequence that begins with 1 and
has an interval of 20.
exec WTPK.createSequence('partNumber', 1, 20)

SQL Server
The following is a sample script for a partNumber sequence that begins with 1
and has an interval of 20.
CREATE TABLE wt_sequence_partNumber (dummy
CHAR(1), value BIGINT IDENTITY(1,20))
go
CREATE PROCEDURE wt_get_next_sequence_partNumber @returnValue BIGINT OUTPUT
AS
INSERT wt_sequence_<MySequence> (dummy) VALUES ('x')
SELECT @returnValue = SCOPE_IDENTITY()
go

Related Package/Class Javadoc


• Foundation module
wt.fc

Persistence Management 2111


58
Advanced Query Capabilities
QuerySpec ........................................................................................................... 2114
SearchCondition ................................................................................................... 2122

This section describes advanced query capabilities supported in the wt.query


package. These capabilities support advanced SQL queries and you are assumed
to be familiar with the functionality and behavior of advanced SQL statements.

Note
See your installed Windchill Javadoc entries for the wt.query package for
further information, including database-specific support for SQL functions and
keywords.

2113
QuerySpec
The QuerySpec contains the following attributes and APIs for building complex
query expressions.

Descendant Query Attribute


By default, when a query contains a class, all concrete, persistable subclasses (that
is, all classes that have an associated table in the database) are queried. Use the
boolean descendant query attribute to control this behavior. When this attribute is
false, only the specified class in the query is queried in the database. Note that an
exception is thrown if the class is not concrete and persistable. Use this feature
only when it is necessary to perform a query against a single table.

Single Column Expression in SELECT Clause


When a class is selected in the query result set, every column of that class is
included in the SELECT clause so that a full object can be built and returned in
the QueryResult. In some cases, only single columns are needed in a result set.
When possible, single columns should be used since this is much more efficient
and offers better performance. The following API supports single column
expressions in the SELECT clause: appendSelect(ColumnExpression
a_column, int[] a_fromIndices, boolean a_selectOnly)
The fromIndices parameter is used to associate the column expression to
classes in the query, if applicable. In general, a ColumnExpression may be
associated with zero or more classes in the From clause. See the following table to
determine the size of the a_fromIndices array based on the type of
ColumnExpression. For example, a single ClassAttribute would
require one from index. A SQLFunction with two ClassAttribute arguments
and a ConstantExpression argument would require two from indices. If no
fromIndices are required, a null value can be passed as the argument. The
selectOnly parameter controls whether the column expression should be
returned as a result object. If true, the column expression is included only in the
select and is not returned as a result.

2114 Customization Guide


The ColumnExpression parameter specifies the query column to append to
the select clause. The following are concrete ColumnExpression implementations:
Column Expression Description Required From
Indices
ClassAttribute This class represents a 1
class attribute that can be
used in a SQL statement.
Introspection information
is used to determine the
associated table and
column.
SQLFunction This class represents a 0 or more. This number is
SQL function within a based on the sum of the
SQL statement. required from indices of
all arguments.
ConstantExpression This class represents a 0
constant in a SQL
statement.
KeywordExpression This class represents an 0
expression that evaluates
to a SQL keyword that
can be used in a SQL
statement.
TableColumn This class represents a 0
table column that can be
used in a SQL statement.
The exact table and
column name specified
are used directly in the
SQL statement.

The following example builds a query for part numbers:


QuerySpec qs = new QuerySpec();
int classIndex = qs.appendClassList(wt.part.WTPart.class, false);
ClassAttribute ca = new ClassAttribute(
wt.part.WTPartclass, wt.part.WTPart.NUMBER);
qs.appendSelect(ca, new int[] { classIndex }, false);
Note that when the WTPart class is appended to the query, the selectable
parameter is false. The full object is not returned; only the number column is
returned.
Results are still returned in the QueryResult object. Each element of the
QueryResult corresponds to a row and is an Object array (that is, Object[]).
In this example, the number column is at index 0 for each element. The actual
Java type for each result is based on the table column and the JDBC SQL-to-Java
type mapping.

Advanced Query Capabilities 2115


The behavior of queries for parent classes (that is, classes that have one or more
persistable, concrete subclasses) is to execute SQL for each table. When only
ColumnExpressions are included in the SELECT clause, all of these SQL
statements are implicitly executed as a single UNION statement instead of
multiple separate database queries.
Queries that include only column expressions still have Access Control applied.
Internally, columns are added to the query to retrieve information needed for
Access Control. This behavior is important to understand when using aggregate
SQL functions. When these are used, the SELECT clause must contain only
expressions with aggregate SQL functions (or the expression must be included in
the GROUP BY clause. If Access Control is applied to such a statement, then it
will result in invalid SQL.

Table Expression in FROM Clause


When a class is added to a query, the generated SQL includes the associated table
for the class in the FROM clause of the query. It is also possible to append a
TableExpression to the FROM clause as shown below: appendFrom(
TableExpression a_tableExpression )
The following are concrete TableExpression implementations:
ClassTableExpression This class represents a class
specification of a table that can be used
in a SQL FROM clause. Introspection
information is used to determine the
associated table.
ClassViewExpression This class represents a "view" of a class
table that can be used in a SQL FROM
clause. All descendent classes are part
of this view (however, no additional
sub-class columns are included). This
class is useful for queries involving
outer joins or group by because all sub-
classes are treated as a single "table".
SubSelectExpression This class represents a subselect that
can be used in a SQL statement. The
subselect is specified via a
StatementSpec attribute.
ExternalTableExpression This class represents a table that can be
used in a SQL FROM clause. The exact
table name specified is used directly in
the SQL statement.

The following example builds a query against a non-modeled table named dual:
QuerySpec qs = new QuerySpec();

2116 Customization Guide


int fromIndex = qs.appendFrom(new
ExternalTableExpression("dual"));
TableColumn dummyColumn = new TableColumn("dual", "dummy");
SQLFunction currentDate = SQLFunction.new
SQLFunction(SQLFunction.SYSDATE);
qs.appendSelect(dummyColumn, new int[] { fromIndex }, false);
qs.appendSelect(currentDate, null, false);

Expression in WHERE Clause


The most common type of WHERE clause expression is a SearchCondition.
However, other expressions can also be used. The following APIs support
expressions in the WHERE clause:
appendWhere(WhereExpression a_expression, int[] a_fromIndicies)
appendWhere(WhereExpression a_expression, TableExpression[]
a_tableExpressions, String[] a_aliases)

The following are concrete WhereExpression implementations:


SearchCondition This class represents a search condition
on a query. When appended to a
QuerySpec, the values will be used in
the SQL WHERE clause.
ExistsExpression This class represents an EXISTS
expression in a WHERE clause. A
StatementSpec instance is used for the
subselect.
CompositeWhereExpression This class represents a number of
WHERE expressions connected using a
logical operator (i.e. AND/OR).
NegatedExpression This class represents a negation of an
expression in a WHERE clause. This
class contains an aggregated
WhereExpression that is preceded with
a NOT when this expression is
evaluated.
The fromIndices parameter is used to associate the WHERE expression
operands with tables in the FROM clause. Similar to the appendSelect()
method, the fromIndices array is based on the types of WhereExpression
and ColumnExpressions used in those WhereExpressions. For example,
a SearchCondition with a ClassAttribute and a
ConstantExpression would require a single from index. A
CompositeWhereExpression containing three SearchConditions
would require fromIndices array with size equal to the sum of the size needed
for each SearchCondition.

Advanced Query Capabilities 2117


The following example demonstrates the proper usage of the fromIndices.
This code queries for parts and their associated alternate parts. A composite where
expression is used with several criteria: the second through fourth characters of
the associated part numbers are equivalent, the part name begins with "E", or the
alternate part name begins with "E". This first section of code sets up the classes
in the query, the select items, and the joins between the classes.
QuerySpec qs = new QuerySpec();
int partIndex = qs.appendClassList(wt.part.WTPartMaster.class, false);
int alternatePartIndex = qs.appendClassList(wt.part.WTPartMaster.class, false);
int linkIndex = qs.appendClassList(wt.part.WTPartAlternateLink.class, false);

// Define the attributes in the query


ClassAttribute partName =
new ClassAttribute(wt.part.WTPartMaster.class,
wt.part.WTPartMaster.NAME);
ClassAttribute alternatePartName =
new ClassAttribute(wt.part.WTPartMaster.class,
wt.part.WTPartMaster.NAME);
ClassAttribute partNumber =
new ClassAttribute(wt.part.WTPartMaster.class,
wt.part.WTPartMaster.NUMBER);
ClassAttribute alternatePartNumber =
new ClassAttribute(wt.part.WTPartMaster.class,
wt.part.WTPartMaster.NUMBER);

// Define constants used in the criteria


ConstantExpression subStringStart = new ConstantExpression(new Long(2));
ConstantExpression subStringEnd = new ConstantExpression(new Long(4));
ConstantExpression wildcardExpression = new ConstantExpression("E% [ ]");

// Add items to the select and join the classes


qs.appendSelect(partName, new int[] { 0 }, false);
qs.appendSelect(alternatePartName, new int[] { 1 }, false);
qs.appendJoin(linkIndex, wt.part.WTPartAlternateLink.ALTERNATES_ROLE, partIndex);
qs.appendJoin(linkIndex, wt.part.WTPartAlternateLink.ALTERNATE_FOR_ROLE,
alternatePartIndex);
In this next section, the criteria are constructed and appended to the query. Note
that the first SearchCondition uses two ClassAttribute instances. The
corresponding indices must be added to the fromIndices array that is used in
the appendWhere. Likewise, the second SearchCondition references the
part class and the third SearchCondition references the alternate part class.
Therefore, four fromIndices are required and each array element must
correspond to the appropriate SearchCondition.
CompositeWhereExpression orExpression =
new CompositeWhereExpression(LogicalOperator.OR);
orExpression.append(new SearchCondition(
SQLFunction.newSQLFunction(SQLFunction.SUB_STRING,
partNumber, subStringStart, subStringEnd),
SearchCondition.EQUAL,

2118 Customization Guide


SQLFunction.newSQLFunction(SQLFunction.SUB_STRING,
alternatePartNumber, subStringStart, subStringEnd)));
orExpression.append(new SearchCondition(
partName, SearchCondition.LIKE, wildcardExpression));
orExpression.append(new SearchCondition(
alternatePartName, SearchCondition.LIKE, wildcardExpression));

qs.appendWhere(orExpression, new int[] {


partIndex, alternatePartIndex, partIndex, alternatePartIndex });
The last API explicitly specifies table expressions and aliases for the WHERE
expression operands. This API is used for correlated subselects. When using
subselects, it is common to use correlated columns (that is, a join between a
column in the outer select and a column in the subselect). This is supported using
the appendWhere() API in which TableExpressions and aliases are
passed explicitly. For WhereExpressions that do not involve a subselect, the
TableExpressions and aliases are derived implicitly using the QuerySpec
FROM clause and the specified indices.
The following example builds a query using an EXISTS clause and a correlated
subselect. The query will return all PartMasters for which an alternate
PartMaster does not exist. An alternate is represented by the
WTPartAlternateLink class, which is a many-to-many association between
PartMasters. The role A of the WTPartAlternateLink class specifies the
current PartMaster and the role B specifies the alternate PartMaster.
Following is the SQL for this query:
SELECT A0.*
FROM WTPartMaster A0
WHERE NOT (EXISTS (SELECT B0.ida2a2
FROM WTPartAlternateLink B0
WHERE (A0.ida2a2 = B0.ida3a5)))
The following code constructs the query specification. The outer select will return
PartMaster objects.
QuerySpec select = new QuerySpec();
int partIndex = select.appendClassList(wt.part.WTPartMaster.class, true);
The following code constructs the subselect. The alias prefix is changed to avoid
conflicts with the outer select.
QuerySpec subSelect = new QuerySpec();
subSelect.getFromClause().setAliasPrefix("B");
int altIndex = subSelect.appendClassList(wt.part.WTPartAlternateLink.class,
false);

subSelect.appendSelect(new ClassAttribute(

wt.part.WTPartAlternateLink.class, WTAttributeNameIfc.ID_NAME),

new int[] { altIndex }, true);

Advanced Query Capabilities 2119


The following code explicitly sets up the TableExpressions and aliases,
which are passed as arrays. The join will be from the outer select to the subselect
so the outer select values are placed in the arrays at index 0 and the subselect
values are placed in the array at index 1. The arrays are then used to append the
SearchCondition.
TableExpression[] tables = new TableExpression[2];
String[] aliases = new String[2];
tables[0] = select.getFromClause().getTableExpressionAt(partIndex);
aliases[0] = select.getFromClause().getAliasAt(partIndex);
tables[1] = subSelect.getFromClause().getTableExpressionAt(altIndex);
aliases[1] = subSelect.getFromClause().getAliasAt(altIndex);

SearchCondition correlatedJoin = new SearchCondition(


wt.part.WTPartMaster.class, WTAttributeNameIfc.ID_NAME,
wt.part.WTPartAlternateLink.class,WTAttributeNameIfc.ROLEA_OBJECT_ID);
subSelect.appendWhere(correlatedJoin, tables, aliases);
Finally, the negated EXISTS clause is appended to the outer select.
select.appendWhere(new NegatedExpression(new
ExistsExpression(subSelect)), null);

Bind Parameters
Bind parameters are a database/JDBC feature to take advantage of database
statement preparsing and optimization. Bind parameters are a mechanism for
replacing constants in a SQL statement with replacement parameters at execution
time. For example, the following WHERE clause expression uses the constant
’Engine’: WTPartMaster.name = ’Engine’
This expression can be replaced with the following in the static SQL:
WTPartMaster.name = ?
and the value ’Engine’ can be bound to the parameter ? at execution time.
On a subsequent execution, a new value, such as Cylinder, can be bound to that
same parameter. If these two statements had used the constant value directly in the
static SQL, each statement would have been parsed, optimized, and precompiled
separately. When bind parameters are used, a single static SQL statement can be
reused multiple times.
This bind parameter feature is implicitly supported when using the QuerySpec,
SearchCondition, and other query classes. However, the bind parameters can also
be explicitly accessed using the following APIs:
• getBindParameterCount()
• getBindParameterAt(int a_index)
• setBindParameterAt(Object a_value, int a_index)

2120 Customization Guide


Query Limit
A QuerySpec attribute, "queryLimit", can be used to limit the results
returned from a query. As the database results are processed, a count is kept for
each item in the result set. This count includes items filtered out due to Access
Control. If the limit is reached, then a PartialResultException will be
thrown. This exception will contain a QueryResult with the items that have been
processed. This could be used in a situation where a client may choose to display
these results after issuing a message that a query limit was reached.

Advanced Query Capabilities 2121


SearchCondition
A SearchCondition represents a SQL WHERE clause expression of the
following form: <left side operand> <operator> <right side operand>
The following are examples:
MyTable.Column1 = 5
MyTable.Column2 LIKE "E%"
MyTable.Column3 = JoinTable.Column1
Operands can also be more complex, such as SQL functions or subselects.
SearchCondition can use arbitrary RelationalExpression operands.
The operands can be specified using the SearchCondition constructor or
setter methods. The following are concrete ColumnExpression
implementations:
ClassAttribute This class represents a class attribute
that can be used in a SQL statement.
Introspection information is used to
determine the associated table and
column.
SQLFunction This class represents a SQL function
within a SQL statement.
SubSelectExpression This class represents a subselect that
can be used in a SQL statement. The
subselect is specified via a
StatementSpec attribute.
ConstantExpression This class represents a constant in a
SQL statement.
KeywordExpression This class represents an expression that
evaluates to a SQL keyword that can be
used in a SQL statement.
RangeExpression This class represents a range in a SQL
WHERE clause.
DateExpression This class represents a date constant in
a SQL statement. This subclass of
ConstantExpression is necessary to
provide the special handling for date
values.
ArrayExpression This class represents an array of
constants in a SQL IN clause.

2122 Customization Guide


TableColumn This class represents a table column
that can be used in a SQL statement.
The exact table and column name
specified are used directly in the SQL
statement.

The following example builds a complex query to determine the


WTPartMaster object with the oldest modify timestamp after a specified date
cutoff. Following is the SQL for this query:
SELECT A0.*
FROM WTPartMaster A0
WHERE (A0.modifyStampA2 IN (SELECT MIN(B0.modifyStampA2)
FROM WTPartMaster B0
WHERE B0.modifyStampA2 > ’cutoff’) )
The following code constructs the query specification:
Class targetClass = wt.part.WTPartMaster.class;
QuerySpec subSelect = new QuerySpec();
subSelect.getFromClause().setAliasPrefix("B");
int subIndex = subSelect.appendClassList(targetClass, false);
int[] fromIndicies = { subIndex };
ClassAttribute subModifyStamp =
new ClassAttribute(targetClass,WTAttributeNameIfc.MODIFY_STAMP_NAME);
SQLFunction minFunction = SQLFunction.new SQLFunction(SQLFunction.
MINIMUM, subModifyStamp);
subSelect.appendSelect(minFunction, fromIndicies, false);
subSelect.appendWhere(new SearchCondition(subModifyStamp,
SearchCondition.GREATER_THAN, DateExpression.newExpression(cutoff)),
fromIndicies);

QuerySpec select = new QuerySpec();


int index = select.appendClassList(targetClass, true);
select.appendWhere(new SearchCondition(modifyStamp,SearchCondition.IN,
new SubSelectExpression(subSelect)), new int[] { index });

Compound Query
A compound query is a SQL statement that combines more than one component
query into a single SQL statement via a set operator. Set operators include
UNION, UNION ALL, INTERSECT, and MINUS. A compound query is
composed by specifying a set operator and adding component queries. The
component queries are StatementSpec objects so nesting of compound
queries is also supported.
The following example builds a compound query to return a specific
PartMaster number and the numbers of all of its alternates. Note that only
numbers are selected, not full objects. This is necessary because, if all subclasses

Advanced Query Capabilities 2123


are considered, the compound query statement must include all subclass tables.
These subclass tables may contain additional columns that would make the select
list for each statement incompatible with other component statements. SQL
requires that each component query in a compound statement must have the same
number and corresponding type in the select list. Following is the SQL for this
query:
SELECT A0.number
FROM WTPartMaster A0
WHERE (A0.name = ‘ENGINE')
UNION
SELECT A2.number
FROM WTPartMaster A0,WTPartAlternateLink A1,WTPartMaster A2
WHERE (A0.name = ‘ENGINE') AND
(A0.idA2A2 = A1.idA3A5) AND (A2.idA2A2 = A1.idA3B5)
The following code constructs the query specification. The first select constructed
is for PartMasters with the name ENGINE.
QuerySpec partSelect = new QuerySpec();
int partIndex = partSelect.appendClassList(wt.part.WTPartMaster.class, false);
partSelect.appendWhere(new SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });
The next select is constructed for returning PartMaster alternates. An alternate
is represented by the WTPartAlternateLink class, which is a many-to-many
association between PartMasters. A join must be specified across this
association from the original part to its alternates.
QuerySpec altSelect = new QuerySpec();
partIndex = altSelect.appendClassList(wt.part.WTPartMaster.class, false);
int altIndex = altSelect.appendClassList(W wt.part.WTPartAlternateLink.class,
false);
int altPartIndex = altSelect.appendClassList(wt.part.WTPartMaster.class,
false);

altSelect.appendSelect(new ClassAttribute(
wt.part.WTPartMaster.class, wt.part.WTPartMaster.NUMBER),
new int[] { altPartIndex }, false);

altSelect.appendWhere(new
SearchCondition(wt.part.WTPartMaster.class,
WTPartMaster.NAME, SearchCondition.EQUAL, "ENGINE"), new int[]
{ partIndex });

altSelect.appendJoin(altIndex, wt.part.WTPartAlternateLink.ALTERNATES_ROLE,
partIndex);
altSelect.appendJoin(altIndex, wt.part.WTPartAlternateLink.ALTERNATE_FOR_ROLE,
altPartIndex);
Finally, the compound statement is constructed using the two previous queries and
the UNION set operator.
CompoundQuerySpec compound = new CompoundQuerySpec();

2124 Customization Guide


compound.setSetOperator(SetOperator.UNION);
compound.addComponent(partSelect);
compound.addComponent(altSelect);

Access Control Consideration


The use of some advanced SQL APIs can bypass Access Control. These situations
are detected and an AdvancedQueryAccessException will be thrown. The
following advanced query uses will cause this exception:
• Sub-selects (wt.query.SubSelectExpression)
• MINUS or INTERSECT Compound Statements (wt.query.
CompoundQuerySpec)
• External Tables (wt.query.ExternalTableExpression)
• Aggregate Functions (wt.query.SQLFunction)
AVERAGE
MAXIMUM
MINIMUM
SUM
COUNT
• ROWNUM keyword (wt.query.KeywordExpression)
This is done to ensure that Access Control is not bypassed unknowingly. In some
cases, the use of these advanced SQL features that bypass Access Control is
legitimate. For these cases, the advanced checking can be disabled at runtime.
Query specification classes support an "advancedQueryEnabled" attribute
that can only be set from server side code. If applicable, the attribute should be set
to true on the query instance that is passed to the PersistenceManager
query/find API to allow these queries to be executed without throwing an
exception.
// Use advanced APIs to build query.
// Disable checking of advance features statement.setAdvancedQueryEnabled(true);
// Execute query with access control
PersistenceHelper.manager.find(statement);

The find() method executes the statement with access control. Therefore,
Access Control related columns may be implicitly added to the select. For some
advanced features, such as aggregate functions, INTERSECT, and MINUS, the
addition of these columns can affect the expected results or cause a SQL
exception. In these cases, to successfully execute the query, the server side, non-
access controlled query() method should be used.
PersistenceServerHelper.manager.query(statement);

Advanced Query Capabilities 2125


Sorting
Queries can be used to sort the result data at the database level. However, in
general, database sorting should only be applied to paging queries and queries that
involve only ColumnExpressions. Other types of queries may be
implemented as several separate SQL statements so the sorting is only applied to
the individual statements and not the complete query. Any
ColumnExpression can be used as a sort column. The OrderBy item is used
to pass the ColumnExpression to the StatementSpec. The OrderBy also
indicates the sort order (ascending or descending) and optionally a Locale. If a
Locale is specified, then any character based attributes are sorted with respect to
that Locale using the database language support. For Oracle, this is the National
Language Support (NLS) (see Oracle documentation for more information). Java
Locale values are mapped to Oracle NLS linguistic sort names via
dbservice.properties entries.
Sorting is supported for standard and compound queries via QuerySpec and
CompoundQuerySpec methods.
QuerySpec.appendOrderBy(OrderBy a_orderBy, int[] a_fromIndicies)

CompoundQuerySpec.appendOrderBy(OrderBy a_orderBy)
The QuerySpec method validates the ColumnExpression contained in the
OrderBy against the QuerySpec’s FROM clause. The CompoundQuerySpec
method does not validate. Note that neither method handles appending the
ColumnExpression to the SELECT clause of the statement. This still must be
done via the appendSelect() method. In both cases, it is recommended that a
column alias be set for each ColumnExpression that is contained in an
OrderBy. Depending on the type of query and the number of subclasses
involved, the actual SQL statements may not be valid if a column alias is not used.
Note that the column alias must not be a SQL reserved word (e.g., "number").
The following example builds a compound query using sorting. The names of
parts and documents are returned sorted by name. Following is the SQL for this
query:
SELECT A0.bname sortName
FROM WTPart A0
UNION
SELECT A0.bname sortName
FROM WTDocument A0
ORDER BY sortName DESC
The following code constructs the query specification. The first component query
is for Parts. Note the setting of the column alias.
String sortName = "sortName";

QuerySpec partQuery = new QuerySpec();


int classIndex = partQuery.appendClassList(wt.part.WTPart.class, false);
ClassAttribute partName = new ClassAttribute(wt.part.WTPart.class,
wt.part.WTPart.NAME);

2126 Customization Guide


partName.setColumnAlias(sortName);
partQuery.appendSelect(partName, new int[] { classIndex }, false);
This next section constructs the Document portion of the query. The same column
alias is used.
QuerySpec docQuery = new QuerySpec();
classIndex = docQuery.appendClassList(wt.doc.WTDocument.class, false);
ClassAttribute docName =
new ClassAttribute(wt.doc.WTDocument.class, wt.doc.WTDocument.NAME);
docName.setColumnAlias(sortName);
docQuery.appendSelect(docName, new int[] { classIndex }, false);
Finally, the compound query is constructed using these two component queries.
The OrderBy is appended to the overall query. The default locale is used to sort
the names with respect to the user’s language.
CompoundQuerySpec query = new CompoundQuerySpec();
query.setSetOperator(SetOperator.UNION);
query.addComponent(partQuery);
query.addComponent(docQuery);
query.appendOrderBy(new OrderBy(partName, true

));

Join Support
Query joins are used for associating data contained in separate tables. Joins can be
accomplished by using the PersistenceManager navigate methods or
through adhoc WhereExpressions. The QuerySpec class also provides
explicit support for appending a join to a query using link classes and roles
defined in the Rose model. This offers the flexibility of the QuerySpec along
with the simplicity of specifying query joins using model information. The
following QuerySpec methods can be used.
appendJoin(int a_linkIndex, String a_role, Persistable a_source)
appendJoin(int a_linkIndex, String a_role, int a_targetIndex)
The following example builds a query that joins together the SubFolder and
Part classes via the FolderMembership link. The query returns all folders
and all of the associated parts that are contained in the folder. The following code
constructs the query specification. The first section adds the classes and the
attributes that should be returned. The final two lines of code join together the
classes using the modeled roles for the FolderMembership link class.
QuerySpec query = new QuerySpec();

int folderIndex = query.appendClassList(wt.folder.SubFolder.class,


false);
int linkIndex = query.appendClassList(wt.folder.FolderMembership.class,
false);
int partIndex = query.appendClassList(wt.part.WTPart.class, false);
query.appendSelect(new ClassAttribute(wt.folder.SubFolder.class,
wt.folder.SubF

Advanced Query Capabilities 2127


older.NAME),
new int[] { folderIndex } , false);
query.appendSelect(new ClassAttribute(wt.part.WTPart.class,
wt.part.WTPart.NAME),
new int[] { partIndex }, false);
query.appendJoin(linkIndex, wt.folder.FolderMembership.FOLDER_ROLE,
folderIndex);
query.appendJoin(linkIndex, wt.folder.FolderMembership.MEMBER_ROLE,
partIndex);

2128 Customization Guide


59
Import Export Framework
How to Write an IX Application................................................................................ 2130
How to Write Exp/Imp Handlers .............................................................................. 2146
Navigating Through an Object’s Structure with ObjectSet Application ........................ 2160
Product Design eXchange (PDX) Support for Export ................................................ 2181
Adding Export Functionality in the Project Plan Table ............................................... 2188

This section describes the Import Export (IX) Framework and explains how to
customize and use it for various solutions.
The basic unit of job for the framework is importing or exporting a single object.
The framework understands the transactional nature of import and encapsulates a
session of individual imports into one database transaction.

2129
How to Write an IX Application
The export starts with Export application. The code of the application that invokes
export should look as follows:
ExportHandler appHandler = new ExportHandler ();
Exporter exporter = IxbHelper.newExporter(handle,
IxbHelper.STANDARD_DTD,
clientSettingsElement,
policyFile==null?(File)null:policyFile.getFile());

Iterator iter = objectSet.iterator();


while (iter.hasNext()) {
Persistable ob = (Persistable)iter.next();
exporter.doExport(ob);
}
exporter.finalizeExport();
appHandler.cleanUp ();

Create an Application Export Handler (appHandler). This is an instance of a


class either implementing ApplicationExportHandler interface or
extending the abstract class ApplicationExportHandlerTemplate. In
the export application in StandardIXBService, the appHandler extends
ApplicationExportHandlerForJar, a subclass of
ApplicationExportHandlerTemplate
The job of the appHandler is:
• To create a file to store exported objects (e.g. a JAR file).
• To store logs to be sent back to the client (optional).
• To clean up temporary files and do other clean-up jobs (advised, but optional).
To create, the following methods must be implemented in appHandler:
• storeLogMessage(...) methods are used to send logs back to clients. It
is up to the developer how to implement the mechanism to send the logs back.
If you do not want to send any log messages, make your Export Handler
extend ApplicationExportHandlerTemplate. This class has the
default storeLogMessage() (empty method).
• It is optional to have clean up and other concluding tasks here, and these jobs
must be called explicitly after exporter.finalizeExport().
The Application Export Handler may also contain methods to perform tasks of
transforming the output if the application needs to modify the exported XML. For
example, PDXExportHandler has methods for XSL transformation to PDX
format. These methods must be called explicitly after
exporter.finalizeExport().

2130 Customization Guide


The existing implementations of the Application Export Handler is:
• PDXExportHandler extends
ApplicationExportHandlerTemplate. This class performs specific
tasks connected with export to PDX format. This includes creating additional
XML attributes/elements and XSL transformation to PDX format.

Create an instance of the Exporter class, and use it to export objects by calling
exporter.doExport(obj), where obj runs through all WT objects collected
for export.
After this, call exporter.finalizeExport(), perform any additional tasks
(for example, transformation to another format), call methods of appHandler to
clean up after the export process, send log messages to client.
The methods doExport(…), doExportImpl(…) and the inner class
ExportHandler in StandardIXBService are examples of one export
application. Please see the details of the example in Export Application on page
2168.

Prerequisite
In order to create the export jar at a client specific location, the following
prerequisite needs to be satisfied before calling the doExport api of
StandardIXBService:
• The context key ISBStreamer.CLIENT_SAVE_AS_FILE needs to be set
with the complete client side file path:
WTContext.getContext().put(IXBStreamer.CLIENT_SAVE_AS_FILE,CLIENT
JAR);

Where CLIENT_JAR is the complete client side file path, e.g.c:\\


mydocuments\\impex.jar.

Exporter Class
The details of the exporter class are as follows:
Definition:
public class Exporter extends ExpImporter{…};

Constructor:
Exporter (ApplicationExportHandler _applicationExportHandler,
WTContainerRef _sourceContainer,
String targetDTD,
File localMappingRuleFile,
File policyRuleFile,
String actionName)

Import Export Framework 2131


throws WTException {
super ("export", ( localMappingRuleFile==null?null:
localMappingRuleFile.getAbsolutePath() ));
//assign Container
sourceContainer = _sourceContainer;
// -- init expActionTuner --
applicationExportHandler = _applicationExportHandler;
dtd = targetDTD;

this.expImpContextData = new ExportContextData();

expActionTuner = new ExportActionTuner (policyRuleFile, actionName);


}

An explanation of the arguments follows:


• _applicationExportHandler - an instance of any class that either
implements the interface ApplicationExportHandler, extends the
abstract class ApplicationExportHandlerTemplate or extends the
abstract class ApplicationExportHandlerForJar.
• The class ApplicationExportHandlerForJar extends the class
ApplicationExportHandlerTemplate. The class
ApplicationExportHandlerForJar provides methods for storing
XML and content files in export jar file. It handles both ApplicationData
content and content residing in local file system.
• _applicationExportHandler has a job of creating a Jar file (or any
other way of storing) of the resulting collection of XML pieces (exported
objects). It must implement two methods:
storeContent (ApplicationData);

storeDocument (IxbElement );
sourceContainer: Reference of container.
• targetDTD: string that specifies what DTD must be used for export process.
The IX framework will find appropriate handlers for objects and Document
Type Definition for objects based on this DTD string. The DTD string for
Windchill Release 10.X is standard20.dtd.
Generally the intent was to be able to export objects in any DTD. As you will
see below the class export handlers are resolved using the DTD identifier. The
string targetDTD is also written to the XML file of exported objects, so
the import process could know what DTD should be used to import objects.
• localMapppingRules: XML file or XSL file that is used to override,
change or exclude certain attributes objects when the export process takes
place.

2132 Customization Guide


The following XML rule file overrides the Team Template attribute, and no matter
what team an object belonged to when it was exported, its team template attribute
will be “Change Team” in the “/System” domain.
<?xml version="1.0" encoding="UTF-8"?>
<userSettings>
<mappingRules>
<COPY_AS>
<tag>teamIdentity</tag>
<value>*</value>
<newValue>Change Team (/System)</newValue>
</COPY_AS>
</mappingRules>
</userSettings>

The XSL rule file tests if the exported object has the name of “part_c”, it will
override the Team Template attribute and version information, and tests if the
exported object has the name of “PART_B”, it will override the Team Template
attribute.
If you don’t want to override anything, just pass “null” for the argument
localMapppingRules.
policyRuleFile: XSL file that is used to override, change or exclude certain
attributes objects when the export process takes place.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@* | node()" priority="-9">
</xsl:template>
<xsl:template match="WTPart">
<xsl:choose>
<xsl:when test="name='part_c'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
<versionInfo>
<versionId>B</versionId>
<iterationId>2</iterationId>
<versionLevel>1</versionLevel>
</versionInfo>
</newInfo>
</xsl:when>
<xsl:when test="number='PART_B'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
</newInfo>
</xsl:when>

Import Export Framework 2133


<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

For example the policy rule file specifies that check out exported WTPart objects
in the database after exporting them. If an exported WTDocument object has the
number of “TESTDOC-1”, check it out after exporting it. With all other exported
WTDocuments, lock them in the database after exporting them.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform
version="2.0">
<xsl:output method="xml" indent="no" encoding="UTF-8"/>

<!--
The syntax of Export Policy is standard XSL syntax. The output of
XSLT using the XSL policy file
must only have at most one element of the form:

<actionInfo>
<action>...</action>
</actionInfo>
-->

The following is a sample of a well-formed xsl. In the cases, where


there are no specific actions to be performed, nothing needs to be
done, which is the default action that would transpire as shown in
the uncommented section below.
-->

<xsl:template match="@* | node()" priority="-9">


</xsl:template>

<xsl:template match="WTPart">
<actionInfo>
<action>Checkout</action>
</actionInfo>
</xsl:template>

<xsl:template match="WTDocument">
<actionInfo>
<xsl:choose>
<xsl:when test="number='TESTDOC-1">
<action>Checkout</action>
</xsl:when>

2134 Customization Guide


<xsl:otherwise>
<action>Lock</action>
</xsl:otherwise>
</xsl:choose>
</actionInfo>
</xsl:template>

-->

<!-- Do nothing by default -->


<xsl:template match="@* | node()" priority="-9">
</xsl:template>

</xsl:stylesheet>

If you don’t want to override anything, just pass “null” for the argument
policyRuleFile.
actionName : Action name
An instance of the Exporter must be created via the factory method
newExporter() of the class IxbHelper. For example:
IxbHelper.newExporter (…..);

Import Export Framework 2135


Using the Exporter to Export Objects
After you create an instance of the class Exporter, for example exporter, you
can use it to export top-level objects. The call to export the object ‘obj’ would be
exporter.doExport(obj);
This is actually making a call to the method doExport (Object obj,
String targetDTD, String targetElem) in the class Exporter.
In this method, the real Export handler for the object obj will be created.

Note
A list of available export handlers is created based on XML files in the folder
<Windchill>\registry\ixb\handlers. If you pass a wrong DTD in
the constructor of Exporter (a DTD that is not available in the system), you
will not get the handler, so you cannot export the object. Please refer to How
to Write Exp/Imp Handlers on page 2146 for information how to add entry for
an Export handler to XML files.

If you have more than one object, you have to pass them to the exporter in a
collection.
exporter.doExport(collection)

After you export all objects, you must call exporter.finalizeExport();


You can call clean-up methods of appHandler (if there are any). Now the
export is finished.

Note
A sample file with comments is distributed along with installation
information.

2136 Customization Guide


How Import Works
To import objects from XML files in a jar file, import application must do the
following:
1. Create a tool to read the imported jar file and extract the list of XML files that
are contained in the jar file. Please see the class IXBJarReader for an
implementation example.
2. Prepare the String ruleFileName to be passed into an instance of the class
Importer. The String ruleFileName can be obtained from an
IxbStreamer, from the user, assigned the value null or obtained from
somewhere else, depending on the structure of the import application.
3. Process policyFile (if it is not null) to create an XSL StreamSource that
contains the import policy.
4. Create an Application Import Handler appHandler. This is an instance of
any class that either implements the interface
ApplicationImportHandler or extends the abstract class
ApplicationImportHandlerTemplate.
5. Create an instance of the class Importer (importer).
6. Get the list of XML files in the jar file.
7. Create IxbDocuments from those XML files.
8. With each IxbDocument, do the following:
• If there is an action name passed to the application and the policyFile
is null, apply the action name into the IxbDocument. If the
policyFile is not null, apply action name and action information in the
policyFile into the IxbDocument.
• Feed them to the importer one by one by calling the import process:
○ importer.doImport(IxbDocument Doc);
○ importer.finalizeImport();
9. Clean up (if needed).
10. Send log messages to client.
The methods doImport(...), doImportImpl(...) and the inner class
ImportHandler in the StandardIXBService are an example of one
import application. Please see the Import Application on page 2170 for details.
Versioned objects can be imported in any of ten different manners decided by
action name and action information that are written to the IxbDocument fileXML
of each importing object. Developers who write import applications must know
about action names and their meanings to apply them correctly, but object
handlers don’t have to worry about the Actor classes. A list of all available action
names can be found in the file <Windchill>\codebase\registry\ixb\
handlers\actor.xml.

Import Export Framework 2137


All of the actions are different from each other in three crucial methods:
previewObject, createObject and storeObject. In the classes
ClassExporterImporterTemplate and
ExpImpForVersionedObject, based on action name and action information
that are passed into the IxbDocument fileXML, appropriate actor will be created
and this actor’s methods will be called to serve the purpose of previewing,
creating and storing versioned objects.
Here is the list by actor names for information.
1. PickExistingObject : Find if an object with the same ufid or same
(name, number, version, iteration) with the object in XML file exists in
database. If such an object exists, the framework will update the object if the
actor believes the object is candidate for update, or do nothing. Otherwise,
import the object in XML file.
2. NewIteration : Import object in XML file as the next available iteration in
the database.
• For example: If there is no version/iteration in the database for the object
which is in the XML file, the imported object will get the version /
iteration specified in the XML file. If the latest version / iteration of the
object in the database is B.2, the imported object will be B.3.
3. NewVersion : Import objects from the XML file as the next available
version in the database.
• For example: If there is no version / iteration in the database for the object
which is in the XML file, the imported object will get the version /
iteration specified in the XML file. If the latest version / iteration of the
object in the database is B.2, the imported object will be C.1.
4. CheckOut : Find any version/iteration of the object in the XML file (Check
the existence of the master object in the database). If there is no version of the
object in the XML file, throw an error. Otherwise, find an instance of the
object in the database that has the same version (iteration can be different) as
the object in the XML file. If such an object exists, check out the latest
iteration of the object in the database, update it with information from the
XML file. I agree Otherwise, throw an error. It is now checked in
5. ImportNonVersionedAttr : Find an object with the same ufid or same
(name, number, version, iteration) with the object in the XML file. If such an
object exists, update it with information from the XML file. Otherwise, throw
an error.
6. UpdateInPlace : Find an object with the same ufid or same (name,
number, version, iteration) with the object in XML file exists in database. If
such an object exists AND it is checked out, update it with information from
the XML file. Otherwise, throw an error.

2138 Customization Guide


7. UnlockAndIterate : Find an object in the database with the same ufid or
same (name, number, version, iteration) as the object in the XML file. If such
an object exists AND it is locked, unlock and iterate it, then update it with
information from the XML file. Otherwise, throw an error.
8. CreateNewObject : Create a brand new object with new name, new
number, new version, new iteration provided in Import Policy file. Other
information will be extracted from the XML file. This functionality cannot be
used alone.

Note
This option cannot work without a policy file to specify the new object
identities.

The format of new information that must be provided in ImportPolicy file


is:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<!--
The syntax of Import Policy is standard XSL syntax. The output of XSLT using
the XSL policy file must only have at most one element of the form:

<actionInfo>
<action>...</action>
</actionInfo>

The following is a sample of a well-formed xsl. In the cases, where there are
no specific actions to be performed, nothing needs to be done, which is
achieved by the following:
<xsl:template match="@* | node()" priority="-9">
</xsl:template>

-->

<xsl:template match="@* | node()" priority="-9">


</xsl:template>

<xsl:template match='WTPart'>
<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

Import Export Framework 2139


<xsl:template match='WTDocument'>
<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

<xsl:template match='EPMDocument'>
<actionInfo>
<action>PickExistingObject</action>
</actionInfo>
</xsl:template>

</xsl:stylesheet>

Note
• <actionInfo> must always exist.
• Criteria can be any valid attribute of the object in XML file.
• Between <xsl:choose>, there can be many <xsl: when test ....> with different
criteria and different action names.
• Only CreateNewObject and SubstituteObject can have action params, and
there are only four action params <newName>, <newNumber>,
<newVersion>, <newIteration>, all of them must be provided.
• SubstituteObject: Substitute the object in the XML file for an object in
the database that has the name, number, version, and iteration provided in the
ImportPolicy file. If such an object doesn't exist, throw an exception. Format
of tag and params for this case is exactly the same with CreateNewObject,
but the <action> is SubstituteObject.
• Ignore: Do not import the object in the XML file. This action doesn't require
any actor.

Importer class
Definition: public class Importer extends ExpImporter
Constructor:
Importer ( ApplicationImportHandler _applicationImportHandler,
WTContainerRef _targetContainer,
String _dtd,
String _ruleFileName,
String _xslPolicyFileName,
String _containerMappingFileName,

2140 Customization Guide


String _actorName,
Boolean _overrideConflicts,
Boolean _validate

) throws WTException

Parameters explanation:
• applicationImportHandler: an instance of a class that either
implements the interface ApplicationImportHandler or extends the
abstract class ApplicationImportHandlerTemplate
• applicationImportHandler has a job of extracting from the Jar file
that stores XML, and its class must implement two methods:
getContentAsInputStream (String contentId);
getContentAsApplicationData (String contentId);

The later method may always return null to indicate that the file does not exist
in the Windchill DB.

Note
Please see the ApplicationExportHandlerForJar for an example
of implementation of an application import handler.

• targetContainer: Container where objects have to be imported


• targetDTD: string that specifies what DTD must be used for import process.
The IX framework will find appropriate handlers for objects and Document
Type Definition for objects based on this DTD string if the imported file does
not specify any. The DTD string used in Windchill Release 10.X is
standardX20.dtd.
• ruleFileName: Mapping rule file can be XML file (like in previous
versions) or XSL file, so this parameter is String. The constructor that uses
IxbElement _localMappingRules is deprecated. In the case you do
not have mapping rule file and want to put it to null, please do not put the
“null” value directly in the constructor, because it will cause one ambiguous
reference error. Instead of doing that, you should use a string, assign null value
to it, and pass it as ruleFileName. Mapping rule file is used to change,
override or exclude certain attributes objects when the import process takes
place.
For example, the rule file overrides the Team Template attribute, and no matter
what team an object belonged to when it was exported, its team template attribute
is replaced by “Change” in the “/System” Domain on import.
<?xml version="1.0" encoding="UTF-8"?>
<userSettings>

Import Export Framework 2141


<mappingRules>
<COPY_AS>
<tag>teamIdentity</tag>
<value>*</value>
<newValue>Change Team (/System)</newValue>
</COPY_AS>
</mappingRules>
</userSettings>

An example for XSL mapping rule file:


<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="WTPart">
<xsl:choose>
<xsl:when test="name='part_c'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design</folderPath>
<versionInfo>
<versionId>B</versionId>
<iterationId>2</iterationId>
<versionLevel>1</versionLevel>
</versionInfo>
</newInfo>
</xsl:when>
<xsl:when test="number='PART_B'">
<newInfo>
<teamIdentity>Default (/System)</teamIdentity>
<folderPath>/Design<folderPath>
</newInfo>
</xsl:when>
<xsl:otherwise>

</xsl:otherwise>
</xsl:choose>

</xsl:template>
</xsl:stylesheet>

This XSL file says that whenever the import process meet a WTPart named part_
c, then change its team identity template to Default (/System), change its folder
part to /Design, and change its version to B.2, whenever the import process meet a
WTPart with the number PART_B, then change its team identity template to
Default (/System), change its folder part to /Design

2142 Customization Guide


If you don’t want to override anything, just pass “null” for the argument
localMapppingRules.
• _xslPolicyFileName : Policy file name
• _containerMappingFileName : Container mapping file name Sample
container mapping file is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<container-info>
<container>
<source-container>/wt.inf.container.OrgContainer=
Demo Organization/wt.pdmlink.PDMLinkProduct=
DemoSourceProduct</source-container>
<target-container>/wt.inf.container.OrgContainer=
Demo Organization/wt.pdmlink.PDMLinkProduct=
DemoTargetProduct</target-container>
</container>
</container-info>
• _actorName : Name of actor to be used
• _overrideConflicts: boolean value specifies whether the import
process should override “overridable” conflicts.
• _validate: boolean value specifies whether the import process should
validate the XML file of the imported object against the DTD.
An instance of the class Importer must be created via the method
newImporter() of the class IxbHelper. For example:
Importer importer = IxbHelper.newImporter(…);

Use Importer to import object from XML files


After you create an instance of the class Importer (importer) you can use it to
import objects from XML files. If you have more than one XML files to import,
you have to give IxbDocument-s that created from XML files to the importer
one by one.
As mentioned above, the Import Application server must call two methods to do
the import:
importer.doImport(IxbDocument doc);

importer.finalizeImport();

• doImport (doc) : This method doesn’t really import the object, but inserts
the XML document that represents the object in to a list to be imported later.
After all XML documents representing all the imported objects are inserted in

Import Export Framework 2143


the import list, the real import process starts with the call to
finalizeImport().
• finalizeImport(): The import process is actually performed in this
method. It will call to:
doCheckConflicts() - check conflicts for imported objects.
doRealImport () - do the real import for the list of objects by calling
importElement (IxbElement doc) for each XML document
representing each object in the list.
ImportElement(...) calls importElements(...) : In the method
importElements(…) the import handler for a particular type of the object is
created by calling getImportHandler(tag).
The method getImportHandler(…) finds the appropriate handler for the
importing object as follows.
1. Try to get an import handler by using the DTD string in the <dtd> tag of the
XML file of the imported object.
2. If the handler is null, try again using current DTD in the importer. This current
DTD is calculated using version of the current Windchill. For Windchill
Release 10.X it is standardX20.dtd.
After getting the handler for the element, the importElements(…) calls the
following methods:
handler.importElements(…) to do the import task.

handler.outputLog(…) to send log to user.

All handlers for non-versioned objects (for example ReportTemplate ... )


extend the class ClassExporterImporterTemplate, all handlers for link
objects (for example, PartUsageLink...) extend the class
ExpImpForLinkObject, and and all handlers for versioned objects (for
example Parts, Documents, EPMDocuments ...) extend the class
ExpImpForVersionedObject.

Note
Handlers for non-versioned objects act like the previous versions.

If the real handler doesn’t implement the method importElements(…), then


the call invokes the default method importElements(…) of the class
ClassExporterImporterTemplate. In this class, the importElement(…)
method calls to findAmongExistingObjects (elements,
importer);.

2144 Customization Guide


If it finds that the object in the XML file currently exists in the database, it will
not import the object. Otherwise, it will call the following methods:
createObjects ( elements, importer);
importObjectsAttributes (elements, importer);
storeObjects (elements, importer);
importObjectsAttributesAfterStore (elements, importer);
finalizeImprtObjects(isNewObject, elements, importer);

Some of these methods should be implemented in the handler, and it is how and
when the real handler comes to do its job.

Note
Handlers for versioned objects act different.

If the real handler doesn’t implement the method importElements(…), then


the call invokes the default method importElements(…) of the class
ExpImpForVersionedObject. In this class, despite the object in the XML
file exists in the database or not, the importElements(…) method always
calls to:
createObject (elements, importer);
importObjectsAttributes (elements,
importer);
storeObjects (List<ElementObjectPair> pairs, importer);
importObjectsAttributesAfterStore (List<ElementObjectPair> pairs,
importer);

Then, the Import Application can do a clean-up, and send messages to the client.
The import process is finished.

Import Export Framework 2145


How to Write Exp/Imp Handlers
Writing Export Handlers for the Export Process
To create an export handler for a class, one needs to know three things:
1. How to use XML files that contain handlers information.
2. How to update DTD files that contain information about objects that will be
exported/imported.
3. How to write a handler.

XML files that contain handlers information


These XML files reside in the folder <Windchill>\codebase\registry\
ixb\handlers. The whole folder is processed as the root element of XML
tags, and the contents of XML files in this folder are processed as child elements.
So, the XML files in this folder are not well formed, and they have contents
similar to the following:
<classExporter>
<class>
[class name of the object that will be exported with full path name]
</class>
<dtd>
[String DTD, specifies where DTD for the class is stored]
</dtd>
<targetTag>default</targetTag>
<handler>
[class name of the handler that is used to export the object]
</handler>
</classExporter>

For example:
<classExporter>
<class>wt.part.WTPart</class>
<dtd>standardX20.dtd</dtd>
<targetTag>default</targetTag>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</classExporter>

All handlers with the <dtd> tag “standard.dtd” are handlers for export object in
Windchill Release 10.X.
For example:
<classExporter>
<class>wt.part.WTPart</class>

2146 Customization Guide


<dtd>standardX20.dtd</dtd>
<targetTag>default<targetTag>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart60</handler>
</classExporter>

So we know that the class


wt.ixb.handlers.forclasses.ExpImpForWTPart is a handler for
exporting the class wt.part.WTPart in Windchill Release 10.X format.
The class IxbHandlersManager contains all necessary methods to
manipulate handlers.

DTD Files
In the folder <Windchill>\codebase\registry\ixb\dtds\
standardX20.dtd there is a file named coreobjects.dtd that is the DTD
file for all objects that will be exported/imported.

How to Write a Class Export Handler


1. Create a Class that extends ClassExporterImporterTemplate
2. Implement exportAttributes(Object obj, Exporter exp)
method, which retrieves the data from the object and adds it to the XML DOM
Document. The following is an example of this method for the object of
“MyClass”:
public void exportAttributes (Object object, Exporter exporter) throws WTException {
try {

MyClass ob = (MyClass)object;
// export the local id
IxbHndHelper.exportAttribute(
ExpImpForLocalIdAttr.class, ob, fileXML, exporter);
// export other attributes that are specific to
// MyObject; e.g. name, number
IxbHndHelper.exportAttribute(
ExpImpForMyObjectAttr.class, ob, fileXML, exporter);
// export version information
IxbHndHelper.exportAttribute(
ExpImpForVersionAttr.class, ob, fileXML, exporter);
// export content
IxbHndHelper.exportAttribute(
ExpImpForContentAttr.class, ob, fileXML, exporter);

}
catch (Exception e) {
LogHelper.devExc ( e,
"exportAttributes: could not export
object=<"+object+">");
}
}

Import Export Framework 2147


3. Override getRootTag() method, which returns the desired root tag for the
object type to be exported. The following is an example of this method for the
object of “MyClass”:
protected String getRootTag() {
return "MyClass";
}

4. Add an entry in the handlers XML file (<Windchill>\registry\ixb\


handlers\coreX10.dtd) that specifies the class being exported (com.
mycompany.MyObject), the XML DTD for core Windchill objects
(standardX20.dtd), and the handler for the class
(wt.ixb.handlers.forclasses.ExpImpForMyObject). An
example entry follows:
<classExporter>
<class>com.mycompany.MyObject</class>
<dtd>standardX20.dtd</dtd>
<targetTag>default</target>
<handler>wt.ixb.handlers.forclasses.ExpImpForMyObject</handler>
</classExporter>

How to Write an Attribute Export Handler


If there is an attribute that is required to be exported the same way for different
classes or if you simply decide to handle it is a separate handler, you can create an
attribute handler. The steps to follow are:
1. Create a Java class extending AttrExporterImporterTemplate.
2. Implement exportAttribute(Object ob,IxbElement fileXML,
Exporter exporter) method, which retrieves the attribute data from the
object and adds it to the XML DOM Document. The following is an example
of this method for the object “MyObject”. This method gets the part type and
the part source of the object.
public void exportAttribute (
Object obj,
IxbElement fileXML,
Exporter exporter) throws WTException {
try {
MyClass ob = (MyClass) obj;
LocalizableMessage localMessage1 = ob.getDisplayType();
Locale locale1 = new Locale("English", "US");
String dispType = localMessage1.getLocalizedMessage(locale1);
fileXML.addValue(IxbHndHelper.XML_ATTR_PARTTYPE, dispType);
fileXML.addValue(
IxbHndHelper.XML_ATTR_SOURCE,ob.getSource ().toString() );
}
{ catch (Exception e)
LogHelper.devExc (e,

2148 Customization Guide


"Exception in ExpImpForLTPartAttr, ob=<"+obj+">");
}
}
3. After adding this, the export handler for class may call this method to have the
part attribute exported.

Import Export Framework 2149


How to Write Handlers for the Import Process
To create import handlers for a class, there are two things to know:
1. XML files that contain handlers information.
2. How to write a handler.

XML files that contain handlers information


These XML files are in the folder <Windchill>\codebase\registry\
ixb\handlers.
The whole folder is processed as the root element of XML tags, and the contents
of XML files in this folder are processed as child elements. So the XML files in
this folder are not well formed, and their contents are similar to the following:
<elementImporter>
<tag>
[class name of the object that will be imported without full path name ]
</tag>
<dtd>
[String DTD, specifies where DTD for the class is stored]
</dtd>
<handler>
[class name of the handler that is used to import the object]
</handler>
</elementImporter>

For example:
<elementImporter>
<tag>WTPart</tag>
<dtd>standardX20.dtd</dtd>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</elementImporter>

All handlers with the <dtd> tag “standardX20.dtd” are handlers for import
object in Windchill Release 10.X.
For example::
<elementImporter>
<tag>WTPart</tag>
<dtd>standardX20.dtd</dtd>
<handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler>
</elementImporter>

So we know that the class


wt.ixb.handlers.forclasses.ExpImpForWTPart is handler for
import of the class wt.part.WTPart in Windchill Release 10.X.
The class IxbHandlersManager contains all methods to manipulate handlers.

2150 Customization Guide


How to Write a Class (Element) Import Handler
Import handlers for classes can be divided in to two types:
• Import handlers for versioned objects.
• Import handlers for non-versioned objects.

Handler for Non-Versioned Object


1. Create a Java class that extends ClassExporterImporterTemplate
2. Implement method: public Object createObject (IxbElement
fileXML, Importer importer)
3. Override the following methods if necessary:
public Object importObjectsAttributes ( List<ElementObjectpair> pairs,
Importer importer);
public ObjectstoreObjects (
List<ElementObjectPair> pairs,
Importer importer);
public Object,importObjectsAttributesAfterStore(
List<ElementObjectPair> pairs,
Importer importer);
public Object findAmongExistingObjectsInternal (IxbElement fileXML,
Importer importer);

Note
An object is imported by the following sequence: createObject(),
importObjectsAttributes(), storeObjects(),
importObjectsAttributesAfterStore().
• createObject(): if the object doesn’t exist in database (is not found
by findAmongExistingObjects), it will be created, and all the Ufid
attribute of the object is imported.
• importObjectsAttributes(): import all attributes of the object
storeObjects(): the method storeObjects() will call to
PersistenceHelper.manager.store().
• importObjectsAttributesAfterStore() imports all attributes
that must be imported after the object is stored.

4. Add an entry to the handlers registry file (<Windchill>\registry\


ixb\handlers\coreX10). The entry specifies the class being imported
(MyObject), XML DTD for core Windchill objects (standardX20.dtd),
and the handler for the class

Import Export Framework 2151


com.ptc.mypackage.ExpImpForMyObject. An example entry
follows:
<elementImporter>
<tag>MyObject</tag>
<dtd>standardX20.dtd</dtd>
<handler>com.ptc.mypackage.ExpImpForMyObject</handler>
</ elementImporter >

Handler for Link Object


1. Create a Java class that extends ExpImpForLinkObject.
2. Implement method: public Object createObject (IxbElement
fileXML, Importer importer)
3. Override the following methods:
protected abstract Class getLinkClass();
protected abstract String getLinkRoleATag();
protected abstract String getLinkRoleBTag();
protected abstract LinkStoreOwnershipType getLinkStoreOwnershipType();
protected abstract Persistable getRoleAObject(IxbElement, Importer);
protected abstract Persistable getRoleAObject(IxbElement, Importer);
protected abstract Object createLinkObject(IxbElement, Importer,
Persistable roleAObj, Persistable roleBObj);
4. Override following methods if necessary.
public Object importObjectAttributes ( Object ob,
IxbElement fileXML,
Importer importer);
public Object storeObjects (List<ElementObjectPair> elements,
Importer importer);
public Object importObjectAttributesAfterStore(IxbElement fileXML,
Importer importer);
public Object findAmongExistingObjectsInternal (IxbElement fileXML,
Importer importer);
Import handlers for non-versioned objects (Link objects) are quite straightforward,
and any of the following classes can be referred as example:
• ExpImpForWTPartDescribeLink
• ExpImpForWTPartReferenceLink

Handler for Versioned Object


1. Create a Java class that extends ExpImpVersionedObject
2. Implement the following methods:
• public List<IxbHndHelper.ElementObjectPair>
getMasters(Collection<IxbElement>, Importer,

2152 Customization Guide


WTcontainerRef) : returns the list of ElementObjectPair if
there is any version of the importing object/s in the database.
3. Override the following methods if necessary:
public Object importObjectsAttributes ( List<IxbHndHelper.ElementObjectPair>,
Importer importer);
public Object importObjectsAttributesAfterStore(
List<IxbHndHelper.ElementObjectPair>,
Importer importer);
public Object findAmongExistingObjectsInternal (
IxbElement fileXML,,Importer importer);

Import Export Framework 2153


Note
An object is imported by the following sequence: createObject(),
importObjectAttributes(), storeObjects(),
importObjectAttributesAfterStore().
• createObject()
This method is implemented in the class
ExpImpForVersionedObject. The creation of objects will be
delegated to Actor classes, depends on the actor name in the XML file
(The actor name is writen into the XML file by import application).
Particular object handlers don’t have to worry about createObject()
and Actor.
• importObjectAttributes()
• Import all attributes of the object that can be imported before the object is
stored.
• storeObject()
This method is implemented in the class
ExpImpForVersionedObject. The store of objects will be delegated
to Actor classes, depends on the actor name in the XML file (The actor
name is writen into the XML file by import application). Particular object
handlers don’t have to worry about storeObject() and Actor.
• importObjectAttributesAfterStore()
Import all attributes of the object that must be imported after the object is
stored
ExpImpForWTPart, ExpImpForDocument,
ExpImpForEPMDocument are examples of import handlers for
versioned objects.

4. Add an entry to the handlers registry file (<Windchill>\registry\


ixb\handlers\coreX10.xml). The entry specifies the class being
imported (MyObject), XML DTD for core Windchill objects
(standardX20.dtd ), and the handler for the class
com.ptc.mypackage.ExpImpForMyObject. An example entry
follows:
<elementImporter>
<tag>MyObject</tag>
<dtd>standardX20.dtd</dtd>
<handler>com.ptc.mypackage.ExpImpForMyObject</handler>
</ elementImporter >

2154 Customization Guide


How to Write an Attribute Import Handler
If there is an attribute that is required to be imported the same way for different
classes or if you simply decide to handle it is a separate handler, you can create an
attribute handler. The steps to follow are:
1. Create a Java class that extends AttrExporterImporterTemplate.
2. Override the following methods if needed:
• prepareForCheckConflicts(Importer importer): prepares
for conflict checking. It is likely never be implemented by a particular
handler.
• checkConflictForAttribute( Object existingOb,
IxbElement fileXML, Importer importer) : This method does
the conflict checking for particular attribute, so if the imported attribute
can potentially have conflicts with an attribute that exists in the database,
this method must be overridden.
importAttribute
Object object, (

IxbElement fileXML,

Importer importer):

Retrieves the attribute data from the XML DOM Document and set it to
the imported object. This method must be overridden to suit particular
attribute.
Here is an example for importAttribute() for the attribute MyAttr to the
object MyObject:
public Object importAttribute
(
Object object,
IxbElement fileXML,
Importer importer)
throws WTException {
String myAttr;
try{
myAttr = fileXML.getValue(IxbHndHelper.XML_ATTR_MYATTR);
// XML_ATTR_MYATTR tag must be defined in IxbHndHelper
}
catch (Exception exc){
// The paragraph bellows allows the import process continue,
// even when the import of MyAttr fails. If the programmer
// wants the import process to stop when the import of
// MyAttr fails, please assign ob=null and throw exception
System.out.println(
"Exception when getting MyAttr in importAttribute");
System.out.println("MyAttr attribute is not imported");

Import Export Framework 2155


return object;
}

MyObject ob = (MyObject) object;


try {
MyObjectHelper.service.setMyAttr(ob, myAttr);
}
catch (Exception e) {
if (! importer.
attributeExporterImporterManager.
overrideConflicts) {
ob = null;
throw e;
}
else{
// override the conflict by doing something here…
}
}
finally{
return ob;
}

Multi Threading Considerations


Starting in Windchill 10.2 M010, you can export and import Windchill package
delivery files using multiple threads. Multiple threads provide one option that may
be used to optimize performance. The use of multiple threads for the export of
Windchill package delivery files is controlled using the
wt.ixb.export.maxThreads property. The use of multiple threads for the
import of Windchill received delivery files is controlled using the
wt.ixb.import.maxThreads property.

Multi Thread Properties

Note
The import multithreading property only applies to import of a received
delivery for importable packages.

2156 Customization Guide


Property Description
wt.ixb.import.batchSize Sets the batch size for a thread.
Batch size has lower impact on
received delivery import performance.
The property can be set to determine
the number of objects in each import
batch. By default, this property is set to
10000.
wt.ixb.import.maxThreads Number of threads for import. The job
list will be distributed over the number
of threads you define.
Using multiple threads has the most
significant impact on received delivery
import performance. The threads share
the same database connection, which
can impact performance if the threshold
is reached. The number of objects can
also impact performance; the greater
the number or objects, the greater the
performance improvement when using
multiple threads. In general, one thread
will be sufficient for incremental
package deliveries. An initial package
delivery may benefit from multiple
threads, particularly if the import time
window is small. By default, this
property is set to 1.

Import Export Framework 2157


Property Description

Note
The value of the
wt.ixb.import.maxThreads
property is used in conjunction with
the
wt.ixb.import.noOfParal
lelImportPaths property,
which determines the number of
transactions used for import.
• Single Transaction Scenario: If
the
wt.ixb.import.noOfPar
allelImportPaths
property is set to 1, the value of
the
wt.ixb.import.maxTh
reads property is the total
number of threads used for
import.
• Multiple Transaction Scenario:
If the value of the
wt.ixb.import.noOfPar
allelImportPaths is set to
more than 1, the value of the
wt.ixb.import.maxTh
reads property is the number
of threads used per import
transaction.
wt.ixb.import.objPer Sets the number of objects included in
ThreadGuidance each thread.
wt.ixb.export.maxThreads Sets the maximum number of threads
used for export. If there are fewer
objects, the number of threads
decreases accordingly. The
recommended number is two.
wt.ixb.export.objPer Sets the number of objects included in
ThreadGuidance each thread.

2158 Customization Guide


Related Documentation
For more information about this and other available properties that can affect
Windchill package delivery file export performance, see the “Best Practices for
Working with Packages” topic in the Windchill Help Center. For more
information about properties related to Windchill received delivery import
performance, see the “Best Practices for Working with Received Deliveries” topic
in the Windchill Help Center. For more information about authoring export and
import handlers with support for multiple threads, see the “How to Write Exp/Imp
Handlers” topic in the Windchill Help Center. Tip: Enter the topic name in the
Windchill Help Center search field to easily navigate to the topic.

Import Export Framework 2159


Navigating Through an Object’s Structure
with ObjectSet Application
In import/export, a new optional <loadCondition> element under navigation
<rule> element has been added. These rules reside in XML files under
<Windchill>\codebase\registry\ixb\object_set_handlers.
The <loadCondition> element will have a fully qualified <className>
and <methodName>. Object Navigation framework will call the specified
method using reflection. The method must be static and must return boolean and
must not have arguments. If the specified method returns a true only then the rule
will be loaded. In case <loadCondition> is not present, the rule will be
loaded by default.
If the <loadCondition> element is present, the framework first calls the
specified method to decide if the rule should be loaded or not.
The element looks like:
<loadCondition>

<className>xxxx</className>

<methodName>yyy</methodName>

</loadCondition>

Example:
<loadCondition>

<className>wt.ixb.objectset.ObjectSetHelper</className>

<methodName>isPDMLinkInstalled</methodName>

</loadCondition>

Object Collection
When an object is given to the export process, the ObjectSet application does
the job of navigating through the object's structure and collecting all of its related
objects.
The definition of the navigation is taken from a set of XML files known as
navigation?rule files. Additionally, the ObjectSet application uses Java classes
known as generators and filters to collect a set of objects that will be exported
when simple navigation is not enough and some programming logic needs to be
applied.

2160 Customization Guide


The navigation rule files reside in the folder <Windchill>\codebase\
registry\ixb\object_set_handlers.

Navigating Rules
There are two types of navigating rules: Generator and Filter.
• Generators are rules that are used by the application to traverse through the
object’s structure and get all of its objects to be exported, such as “uses”,
“described by”, “reference”, etc.
• Filters are rules that are applied to objects to be exported to exclude certain
objects from the export process. For example, with “Filter By Time”, we can
choose to export objects that were modified during a specified period. This is
the only OOTB filter currently available.
Available GeneratorIds are defined in XML files in the folder <Windchill>\
codebase\registry\ixb\object_set_handlers with the tag
<setGenerator>. A list of these Generator Ids can be obtained by calling to
IXBHelper.service.getGeneratorList() passing the first argument
as false. . The call returns all available Generators in the system.
IXBHelper.service.getGeneratorList() passing the first argument
as true returns a list of Generators that will be displayed to the GUI for end-user
selection. This helps to hide Generators that you don’t want the end-user to see.
To hide these Generators, the XML files for these Generators, should have the
<display> tag set to false.
For example: a paragraph of XML file for WTPart from <Windchill>\
codebase\registry\ixb\object_set_handlers\product_
struct.xml.
<setGenerator>
<id>productStructureNavigator</id>
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>
<dialogClassName>
wt.clients.ixb.exp.NavigatorSearchDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>PRODUCT_STRUCTURE_NAME</key>
</localizedString>
</localizedName>

Import Export Framework 2161


Tags
• <id>: Generator Id
• <handler>: Navigator – Java class that helps navigating through the object
structure. In the example, to navigate through WTPart structure.
• <dialogClassName>: Java class of the dialog that must be called from the
GUI to search the top-level object of this class in database (in this example, to
search WTPart).
• <localizedName> and its sub tags are for internationalization purpose.
The string resource for displaying the Generator to the GUI will be defined in
the resource bundle file for different locales.
If you don’t want this GeneratorId to be displayed to the GUI, but only to be used
programmatically in your application, add the tag <display> like this:
<setGenerator>
<id>productStructureNavigator</id>
<display>false</display>
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>
<dialogClassName>
wt.clients.ixb.exp.NavigatorSearchDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>PRODUCT_STRUCTURE_NAME</key>
</localizedString>
</localizedName>

Available Filter Ids are defined in XML files in the folder <Windchill>\
codebase\registry\ixb\object_set_handlers with the tag
<setFilter>. A list of these Filter Ids can be obtained by calling to
IXBHelper.service.getFilterList() passing the first argument as
false. It returns all available Filters in the system.
IXBHelper.service.getFilterList() passing the first argument as
true returns a list of Filters that will be displayed to the GUI for user selection.
This function helps to hide filters which you don’t want the end user to see. To
hide such Filters, set the value of the <display> tag to false in the XML files of
these Filters.

2162 Customization Guide


Note
If the tag <display> is set to true, the Generator will be included in the
result of the method
ObjectSetHelper.getListOfObjectSetGenerators () and it
will be displayed in the GUI irrespective of the argument passed to this
method. If the tag <display> is not specified, or set to false and the
argument passed to the method
ObjectSetHelper.getListOfObjectSetGenerators() is true,
the Generator will not be included in the result of this method , and it will not
be displayed to the GUI. To get all Generators in the system, use this method
by passing the argument as false.

All the methods get…Generators and get…Filters of


ObjectSetHelper return Vectors that contain a list of the handler IDs. These
IDs can be passed as arguments generatorIds and filterIds for the
method doExport() in the StandardIXBService.

Object Navigation
The mechanism is an XML-rule-driven “navigator” of Windchill objects. Given a
seed (top level) object the mechanism uses specified rules to navigate from object
to object. The navigation can be performed through a DB link, a foreign key, or a
specified method. Here is an example of rule definition of WTPart. The seed is a
Folder object.
<Windchill>\codebase\registry\ixb\object_set_handlers\
product_struct.xml
<handler>
wt.ixb.objectset.handlers.navigator.ProductStructureNavigator
</handler>
...
<schema>
...
<rule>
<for>wt.part.WTPart</for>
<go>
<byMethod>
<method>navigateFromWTPartToDescribeByDoc</method>
</byMethod>
</go>
</rule>

<rule>
<for>wt.part.WTPartDescribeLink</for>
<go>

Import Export Framework 2163


<fromForeignKey>
<targetClass>wt.doc.WTDocument</targetClass>
<getMethodName>getDescribedBy</getMethodName>
</fromForeignKey>
</go>
</rule>
...
</schema>
The example above shows both possible types of navigation: From WTPart it
navigates to wt.part.WTPartDescribeLink by a navigate method and
from there using the method getDescribedBy to get the WTDocument that
the WTPart is described by. Then, non-trivial semantic steps can be made.
After collecting, the objects can be filtered out by a set of defined filters. The filter
definition is stored in the same object set registry. The following is an example of
a date/time filter:
<Windchill>\codebase\registry\ixb\object_set_handlers\
filter_by_time.xml
<setFilter>
<id>filterByTime</id>
<handler>wt.ixb.objectset.handlers.FilterByTime</handler>
<dialogClassName>
wt.clients.ixb.exp.FilterByTimeDialog
</dialogClassName>
<localizedName>
<localizedString>
<class>wt.ixb.objectset.objectSetResource</class>
<key>FILTER_BY_TIME_NAME</key>
</localizedString>
</localizedName>
<parameters>
</parameters>
</setFilter>
The filtering mechanism, as well as the object collection are coupled with the
export application at the level of StandardIXBService. They can be
separated.

2164 Customization Guide


Adding New Navigators
To implement new Navigator, in most cases you will have to do the following
steps:
1. Implement the XML rule file describing the logic of the navigation. See
<Windchill>\codebase\registry\ixb\object_set_
handlers\product_struct.xml for an example.
2. Implement a subclass of
wt.ixb.objectset.handlers.navigator.GeneralNavigator.
You may need to implement the following methods:
• public boolean canBeUsedAsTopLevelObject(Persistable obj)
• public String getTopLevelObjectLocalizedImage(Persistable obj)

Note
You must implement all methods that are specified in the rule files.

Such navigation methods take the object to navigate from as a parameter, and
return Enumeration, which will be added to the export set. For example, if you
specify the following rule:
<byMethod>
<method>navigateFromObject1ToObject2</method>
</byMethod>

Then, you must implement the following Java method:


public Enumeration navigateFromObject1ToObject2 (Persistable ob)
throws WTException

List of Existing Generators and Filters

Import Export Framework 2165


This appendix provides help for the GUI developer who will be using the IX
Object Collection mechanism by calling:
ObjectSetHelper.computeObjectSetForGivenGeneratorsAnd
Filters(generatorIds, generatorParams, filterIds,
filterParams);

Examples

Part With all Children


genId[0] = “productStructureNavigator”;
genParams[ 0] = “wt.part.WTPart:6789”;
WTHashSet objects = (WTHashSet) ObjectSetHelper.
computeObjectSetForGivenGeneratorsAndFilters(
genIds,
genParams,
new String [0 ],
new String [0 ]);

All Objects in the Cabinet and Folder (Including Subfolders)


genId[0] = genId[ 1] = “folderContent”;
genParams[ 0] = “wt.folder.Cabinet:1865”;
genParams[ 1] = “wt.folder.Subfolder:5674”;
WTHashSet objects = (WTHashSet) ObjectSetHelper.
computeObjectSetForGivenGeneratorsAndFilters(
genIds,
genParams,
new String [0 ],
new String [0 ]);

Note
Warning, if there are no filters, you can pass new String[0] for
filterIds and filterParams (Don’t pass null, an exception is thrown)

To get String constants for GUI, see <Windchill>\DevModules\IXLoad\


src\wt\ixb\objectset\objectSetResource.java.

2166 Customization Guide


Generators list
String id Description Localized name Parameters as
– En (for GUI) String
folderContent Collects all objects Cabinet and Folder <class name: oid>,
in a given Cabinet/ Contents like:
Folder (including wt.folder.
subfolders) Subfolder: 1234 or
wt.folder.Cabinet:
1234
productStructure- Collects all Product Structure <class name: oid>,
Navigator children of a given built with active like:
Part (e.g. Parts, configuration wt.part.
which it uses and specification WTPart:123 4 for
Documents which the top-level
describe it) object. This object
must be instance of
WTPart
productStructure- Collects all CAD Document / <class name: oid>,
NavigatorEPM children of a given Dynamic like:
CAD Document Document wt.epm.EPMDocu
Structure (built ment:1234 for the
with latest top-level object.
configuration This object must
specification) be instance of
EPMDocument
productStructure- Collects all Product Structure <class name: oid>,
NavigatorWi- children of a given with CAD like:
thEPM Part including Documents / wt.part.
related CAD Dynamic WTPart:123 4 for
Documents Documents (built the top-level
with active object. This object
configuration must be instance of
specification) WTPart
singleDocument Takes only given Document <class name: oid>,
document like:
wt.doc.
WTDocume
nt:1234

Import Export Framework 2167


Note
Actually <class_name:oid> is object local id
There are other generators available which are installation-specific.

Filters list
String id Description Localized name Parameters as
- En (for GUI) String
filterByTime Filters out objects Filter based on <timeFrom#time-
with modification modification time To >, where
time before/after timeFrom and
the given interval timeTo = “null” or
Timestamp.
toString ()

Examples about Exp/Imp Application:

Export Application
The current Windchill Export OOTB GUI and the StandardIXBService is
an Export Application.
The OOTB Windchill Export GUI is Export Application (client) that calls export
process in StandardIXBService (Export Application (server)) via
IXBHelper.
ObjectExportParameters exportParam = new ObjectExportParameters ();

exportParam.setActionName(actorName);
exportParam.setClientFileName(jarFileName);
exportParam.setContainer(container);
exportParam.setDetailedLog(detailedLog);
exportParam.setGuiId(reqGUIid);
exportParam.setPolicyFile(policyFile);
exportParam.setPreviewOnly(isPreview);
exportParam.setRuleFile(ruleF);
exportParam.setValidation(false);
exportParam.setGenerators(generators);
exportParam.setFilters(filters);
exportParam.setLocale(RB.getLocale());
exportParam.setJarInJarFlag(jarInJar);
exportParam.getContextData().setIXApplicationContext(appContext);

2168 Customization Guide


try{
String formatType = WTProperties.getAppletProperties().
getProperty("wt.ixb.export.formatType");
if(formatType != null){
exportParam.setFormatType(ExportImportFormatType.
toExportImportFormatType(formatType));
}
}catch(Exception e){
}

IXBExpImpStatus status = IXBHelper.service.doExport ( exportParam);

• IXBHelper is a class in wt.ixb.clientAccess. It calls methods


doExport(…) of the class StandardIXBService to do export process.
• IXBExpImpStatus is a class in wt.ixb.clientsAccess containing
information about the Exp/Imp process and is used to pass Exp/Imp status
between the server and client.
• generatorIds – see definition above.
• generatorParams is an array of Object Ids of top-level objects that will be
exported. From the current Exp GUI, those objects will be chosen by using
NavigatorSearchDialog. After the selection is done, this dialog will
return a list of IXBSelectedNavInfo with Navigator Id and Generator Id,
and seed object as an objectId. Given an object obj, we can get the Object Id
by using IXBHelper.service.getObjectId(obj).
• filterIds - see definition above
• filterParams is an array of objects attributes to set the objects to be
excluded from export process, or to be included in export process, depends on
the type of filters.
• ruleFile is the rule file for export process. This file is provided to Exporter
to create a tuner for export process.
• guiId is the id of the GUI from which the export process is called. See the
method recordGuiIdInContext() of the class
wt.clients.ixb.util.ExpImpServerRequest for an example how
to create the GUIid.
• detailLog indicates whether the status message should be in details or not.
• stDtd specifies which version of the Exp/Imp handlers will be used. This is
used to support backward compatible. If stDtd is null or empty (“”), the
STRING_DTD will be calculated based on the current Windchill.
• When the method IXBHelper.service.doExport(…) is called, it will
call to the method doExportImpl(…) in the StandardIXBService.
This method:
○ Creates a general export handler ExportHandler handler. This is an inner
class of StandardIXBService.

Import Export Framework 2169


○ Gets a list of objects that will be exported by calling

ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters (
generatorIds,
generatorParams,
filterIds,
filterParams);

○ Creates an instance of Exporter, the class that does the export.


○ Depending on isPreview (true/false) the exporter will do a
preview or real export by calling methods of Exporter class mention in
the section Exporter class of this document.
○ Calls clean-up methods of the ExportHandler handler.

Import Application
The current Windchill Import GUI and StandardIXBService are the Import
Application. The current Windchill Import OOTB GUI is Import Application
client that calls import process in StandardIXBService (Import Application
server) via IXBHelper.
ObjectImportParameters importParam = new ObjectImportParameters ();

importParam.setActionName(actorName);
importParam.setContainer(container);
importParam.setDataFile(dataF);
importParam.setDetailedLog(detailedLog);
importParam.setGuiId(reqGUIid);
importParam.setPolicyFile(policyFile);
importParam.setPreviewOnly(isPreview);
importParam.setRuleFile(ruleF);
importParam.setValidation(true);
importParam.setLocale(RB.getLocale());
importParam.setOverrideConflicts(overrideC);
importParam.setContainerMappingFile(containerMappingFile);
importParam.getContextData().setIXApplicationContext(appContext);

IXBExpImpStatus status = IXBHelper.service.doImport (importParam );


It calls methods doImport(…) of the class StandardIXBService to do
the import process.
IXBExpImpStatus is a class in wt.ixb.clientsAccess containing
information about Exp/Imp process and used to pass Exp/Imp status between
server and client.
ruleFile is the rule file for export process. This file is provided to Importer to
create a tuner for import process.
dataFile is the jar file that contains XML files of objects that will be imported.

2170 Customization Guide


overrideConflicts specifies whether overridable conflicts must be
overridden or not.
isPreview specifies whether the process should do real import, or check
conflicts and display what objects will be imported.
guiId is the id of the GUI from which the export process is called. See the
method recordGuiIdInContext() of the class
wt.clients.ixb.util.ExpImpServerRequest for an example how to
create the GUIid.
detailLog indicates whether the status message should be in details or not.
creatorName specifies how top-level imported objects (for example
EPMDocument, WTDocument, WTPart) are created.
stDtd specifies which version of Exp/Imp handlers will be used. This is used to
support backward compatible. If stDtd is null or empty (“”), the STRING_DTD
will be calculated based on version of current Windchill system.
When the method IXBHelper.service.doImport(…) is called, it will
call to the method doImportImpl(…) in StandardIXBService.
This method:
• Puts creator name in WTContext to be used by import handler.
• Creates a general import handler ImportHandler handler.
• Gets a list of XML files from the Jar file to be imported by calling
jar.getFileNamesByExtension ("xml");
• Creates an instance of Importer, the class that does the import job.
• Depending on isPreview (true/false), the method
doImportImpl(…) calls the appropriate methods of Importer to do a
preview or the real import:
○ importer.doImport(stream);
○ importer.doPreview(stream);
• The others (importer.doImport(fn, tag) and
importer.doPreview(fn,tag)) are for optimization, and they depend
on how XML files are named. This feature is just for a particular Exp/Imp
Application (wt.clients.ixb and StandardIXBService).
• Sends log messages back to client.

Import Export Framework 2171


Simple Export Handler Code Sample
import java.io.File;
import java.io.PrintStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;

import wt.pom.Transaction;
import wt.content.ApplicationData;
import wt.content.ContentItem;
import wt.content.Streamed;

import wt.ixb.publicforapps.ApplicationExportHandlerTemplate;

import wt.ixb.publicforhandlers.IxbElement;
import wt.ixb.publicforapps.Exporter;
import wt.ixb.publicforapps.IxbHelper;

import wt.ixb.objectset.ObjectSetHelper;

import wt.util.WTException;
import wt.util.WTMessage;

import wt.ixb.clientAccess.IXBJarWriter;

import wt.fc.Persistable;

public class SimpleApplicationExportHandler extends ApplicationExportHand


lerTemplate{

private File targetDir = null;


private PrintStream log = null;

private IXBJarWriter jw = null;


private File resJar = null;
private int fileNum = 0; //counter for exported content files
private HashSet contentFileNames = new HashSet(); //to handle
content files with the same name

public static final String NAME_IS_TAG = "TAG";


public final static String CONTENT_SUBDIR = "CONTENTS";

2172 Customization Guide


public SimpleApplicationExportHandler(File tmp_storeDir, PrintStream a_log)
throws WTException{
if (!tmp_storeDir.exists()){
tmp_storeDir.mkdirs();
}
targetDir = tmp_storeDir;
log = a_log;
}

public String storeContent (Object ob) throws WTException


{
String storeName = null;
if(ob instanceof ApplicationData)
{
ApplicationData obj = (ApplicationData)ob;
String fileName = obj.getFileName();

try
{
storeName = this.computeUniqueFileName(fileName);
Streamed sd = (Streamed)obj.getStreamData().getObject();
InputStream is = sd.retrieveStream();
jw.addEntry(is, storeName);

}
catch (IOException ioe)
{

throw new WTException(ioe);


}
}
return storeName;
}

public String storeDocument(IxbElement elem, String dtd)


throws WTException
{
try {
String tag = elem.getTag();
String fn = NAME_IS_TAG+"-"+tag+"-"+(fileNum++)+".xml";
File file = new File(targetDir,fn);
FileOutputStream stream
= new FileOutputStream (file);
elem.store(stream, dtd); stream.close();

jw.addEntry(file);
file.delete();
}
catch (IOException ioe){
throw new WTException(ioe);

Import Export Framework 2173


}
}

public void storeLogMessage(String resourceBundle,


String messageKey,
Object[] textInserts)
throws WTException{
WTMessage m = new WTMessage(resourceBundle, messageKey, textInserts);
String s = m.getLocalizedMessage();
log.println(s);
}
public void storeLogMessage(String resourceBundle, String messageKey,
Object[] textInserts, int importanceLevel)
throws WTException{
storeLogMessage (resourceBundle, messageKey, textInserts);
}

public void exportObjectContent (Object obj, Exporter exporter, Content


Item item, String exportFileName)
throws WTException {
if (item instanceof ApplicationData) {
ApplicationData ad = (ApplicationData) item;
Streamed streamedIntfc = (Streamed) ad.getStreamData().getObject();
try{
InputStream is = streamedIntfc.retrieveStream();
jw.addEntry(is, exportFileName);
}
catch (IOException ioe){
throw new WTException(ioe);
}
}
}
private String computeUniqueFileName (String fn) throws IOException {
//compute file name in jar (should be unique)
if (contentFileNames.contains(fn)) {
// if simple content's name already has been used then look for
// name in form name-123.ext
// As a result will have names like: design.doc, design-23.doc,
design-57.doc, ...
int i = fn.lastIndexOf('.');
String fn_n = ( i>0 ? fn.substring(0, i) : fn);
String fn_t = ( i>0 ? fn.substring(i+1) : "" );
while (true) {
fn = (i>0 ?
fn_n + '-' + (fileNum++) + '.' + fn_t :
fn_n + '-' + (fileNum++)
);
if (!contentFileNames.contains(fn)) break;
}
}
contentFileNames.add(fn);

2174 Customization Guide


String fnInJar = CONTENT_SUBDIR + "/" + fn;
return fnInJar;
}

public File doExport( WTContainerRef container,


String[] generatorIds,
String[] generatorParams,
String[] filterIds,
String[] filterParams,
File ruleFile,
File policyFile,
String actionName,
String stDtd,
File resultingJar)
throws WTException{

//init jar file


resJar = resultingJar;
try{
jw = new IXBJarWriter(resultingJar);
}
catch (IOException ioe){
throw new WTException(ioe);
}

//adopt incoming rule file


IxbElement clientSettingsElement = null;
if (ruleFile!=null) {
try{
InputStream clientSettingsStream = new FileInputStream(ruleFile);
clientSettingsElement = IxbHelper.newIxbDocument
(clientSettingsStream,
false);
}
catch(IOException ioe){
throw new WTException(ioe);
}
}

//create exporter
Exporter exporter = null;
if ( policyFile==null ) { // policy rule is null; export action is
expected ...
exporter = IxbHelper.newExporter (this, IxbHelper.STANDARD_DTD,
clientSettingsElement, null, actionName );
}
else{
exporter = IxbHelper.newExporter (this, IxbHelper.STANDARD_DTD,
clientSettingsElement, policyFile, null );
}

Import Export Framework 2175


//gen set of items to export
Set res = ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFil
ters (generatorIds, generatorParams, filterIds, filterParams);

Iterator iter = res.iterator();

Transaction trx = new Transaction();


try {
if ( !(actionName != null && actionName.equals(wt.ixb.tuner.Exp
ortActionHelper.NO_ACTION_CMD) )){
trx.start();
}
while (iter.hasNext()) {
Persistable ob = (Persistable)iter.next();
exporter.doExport(ob);

}
exporter.finalizeExport();
if ( !(actionName != null && actionName.equals(wt.ixb.tuner.Exp
ortActionHelper.NO_ACTION_CMD) )){
trx.commit();
}
trx = null;
}
finally {
if (trx != null) {
if ( !(actionName != null && actionName.equals(wt.ixb.tuner.
ExportActionHelper.NO_ACTION_CMD) )){
trx.rollback();
}
trx = null;
}
}
try{
jw.finalizeJar();
}
catch(IOException ioe){
throw new WTException (ioe);
}

return resJar;

}
}

2176 Customization Guide


Simple Import Handler Code Sample
import java.io.File;
import java.io.PrintStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;

import wt.pom.Transaction;

import wt.content.ApplicationData;
import wt.content.ContentItem;
import wt.content.Streamed;

import wt.ixb.publicforapps.ApplicationImportHandlerTemplate;

import wt.ixb.publicforhandlers.IxbElement;
import wt.ixb.publicforhandlers.IxbHndHelper;
import wt.ixb.publicforapps.IxbDocument;
import wt.ixb.publicforapps.Importer;
import wt.ixb.publicforapps.IxbHelper;

import wt.ixb.objectset.ObjectSetHelper;

import wt.ixb.actor.actions.IxbActionsHelper;

import wt.util.WTException;
import wt.util.WTMessage;

import wt.ixb.clientAccess.IXBJarReader;

import wt.fc.Persistable;

import javax.xml.transform.stream.StreamSource;

public class SimpleApplicationImportHandler


extends ApplicationImportHandlerTemplate{

private IXBJarReader jr = null;


private PrintStream log = null;

public SimpleApplicationImportHandler(PrintStream a_log){


log = a_log;

Import Export Framework 2177


public InputStream getContentAsInputStream (String contentId)
throws WTException {
try{
return jr.getStreamByName (contentId);
}
catch(IOException ioe){
throw new WTException(ioe);
}
}
public void storeLogMessage(String resourceBundle,
String messageKey, Object[] textInserts)
throws WTException{
WTMessage m = new WTMessage(resourceBundle, messageKey, textInserts);
log.println(m.getLocalizedMessage());
}
public void doImport(WTContainerRef container,
File ruleFile,
File dataFile,
boolean _overrideConflicts,
String actorName,
File policyFile,
File containerMappingFile)
throws WTException{

try{
jr = new IXBJarReader(dataFile);
}
catch(IOException ioe){
throw new WTException (ioe);
}
//prepare rule file
String ruleFileName = (ruleFile!=null)? ruleFile.getAbsolutePath(): null;

//prepare container mapping file


String containerMappingFileName = (containerMappingFile!=null)?
containerMappingFile.getAbsolutePath(): null;

//prepare policy file


String policyFileName = (policyFile!=null)?policyFile.
getAbsolutePath(): null;

StreamSource xslPolicyFile = null;


if (policyFile!=null) {
xslPolicyFile = new StreamSource(policyFile.getAbsolutePath());
}
Boolean overrideConflicts = new Boolean (_overrideConflicts);
Importer importer = IxbHelper.newImporter(this,
container,
IxbHelper.STANDARD_DTD,
ruleFileName,
policyFileName,

2178 Customization Guide


containerMappingFileName,
actorName,
overrideConflicts,
null /*validate*/);

String [] fns = jr.getNonContentFileNamesByExtension ("xml");

boolean validate = IxbHndHelper.getIxbProperty("import.parser.validate",


false);

for (int i=0; i<fns.length; i++) {

String fn = fns[i];
InputStream stream = null;
try{
stream = jr.getStreamByName (fns[i]);
}
catch (IOException ioe){
throw new WTException (ioe);
}
IxbDocument doc = IxbHelper.newIxbDocument(stream, validate);

//if policyFile == null, apply actorName to XML Document before pass


it to importer
if (policyFile == null){
IxbElement rootElem = doc.getRootElement();
//XML_ACTION_KEY = "actionInfo/action"
IxbElement actionElement =
doc.getElement(IxbActionsHelper.XML_ACTION_KEY);
if (actionElement == null){
rootElem.addValue(IxbActionsHelper.XML_ACTION_KEY,
actorName);
}
else {
rootElem.removeChildElement( actionElement);
rootElem.addValue(IxbActionsHelper.XML_ACTION_KEY,
actorName);
}
}
else { //apply policy file
doc =
IxbActionsHelper.writeActionAndParametersToFileXML(doc,xslPolicyFile);
}
//set elem ready for import
importer.doImport(doc);
}

//perform actual import


importer.finalizeImport();
}

Import Export Framework 2179


}

2180 Customization Guide


Product Design eXchange (PDX) Support
for Export
Product Design eXchange (PDX) is a file format used for sharing of product
design data between business partners. This allows you to share information about
Documents, Parts, Product Structure and Bill of Materials (BOM).
You can export data from Windchill to PDX format including Agile. You can
customize to export of BOM data to PDX format.
The OOTB PDX export allows you to export:
• Documents
• Parts
• EPM Documents

Sample product structure in Windchill system

Corresponding PDX output as seen in PDXplorer

Import Export Framework 2181


Customization Points
Required Artifacts
• Class files: wt.ixb.pdx.*
• XSL path used for transformation: <Windchill>\codebase\
registry\ixb\pdx
• DTD path: <Windchill>\codebase\registry\ixb\pdx\dtds

Default Behavior
• By default it would be Agile compatible.
• By default:
○ “Agile_07.dtd” and “wcxml12pdx_agile.xsl” would be
respective dtd and xsl corresponding to Agile format.
○ “IPC_2571.dtd” and “wcxml2pdx.xsl” would be respective dtd
and xsl corresponding to PDX format.

Overridable Properties for wt.properties


• pdx.export.dtdFilePath=
$(wt.home)$(dir.sep)codebase$(dir.sep)registry$(dir.
sep )ixb$(dir.sep)pdx$(dir.sep)dtds$(dir.sep) Agile_
07.dtd
• pdx.export.xslFilePath=
$(wt.home)$(dir.sep)codebase$(dir.sep)registry$(dir.
sep) ixb$(dir.sep)pdx$(dir.sep) wcsml2pdx_agile.xsl
• pdx.AgileCompatible=true
• pdx.debug.enable=false
The xsl may also be modified as per requirement or to support PDX export of
other exportable Windchill objects.

2182 Customization Guide


Supported APIs
• ExportPackage exportPackage=
ExportPackageForPDX.createExportPackageForPDX(...)
• PDXExportHelper.doExportToPDX(...)

createExportPackageForPDX
There are four static public APIs (createExportPackageForPDX) in
ExportPackageForPDX to support this functionality.

public static wt.ixb.objectset.ExportPackage


createExportPackageForPDX
public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

java.lang.String name, java.lang.String description,


java.lang.String exporter, java.langString[] generIds,
java.lang.String[] generParams, java.lang.String[] filterIds,
java.lang.String[] filterParams) throws wt.util.WTException

• Purpose: Create ExportPackage holding all information necessary for


export in PDX format. The objects are collected using standard ixb collection
mechanism (generators and filters).
• Parameters:
○ name — Name of the export package
○ description — Description of the export package
○ exporter — Name of the user who makes export
○ generIds — Array of Sting id for object set generator types, e.g.
{”singleDocument”,”productStructureNavigatorWi
thEPM”}
○ generParams — Array of local id for the corresponding seed objects
○ filterIds — Array of String id for object set filters
○ filterParams — Array of Strings representing parameters for filtering
• Throws: wt.util.WTException

public static wt.ixb.objectset.ExportPackage


createExportPackageForPDX
public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

wt.inf.container.WTContainerRef container,java.lang.String name,


java.lang.String description,java.lang.String exporter,
java.lang.String[] generIds,java.lang.String[] generParams,
java.lang.String[] filterIds,java.lang.String[] filterParams)
throws wt.util.WTException

Import Export Framework 2183


• Purpose: Creates ExportPackage holding all information necessary for
export in PDX format. The objects are collected within a container using
standard ixb collection mechanism (generators and filters).
• Parameters:
○ container — Object reference of container holding objects to export
○ name — Name of the export package
○ description — Description of the export package
○ exporter — Name of the user who make export
○ generIds — Array or String id for object set generator types, e.g.
{”singleDocument”,”productStructureNavigatorWi
thEPM”}
○ generParams — Array of local id for the corresponding seed objects
○ filterIds — Array of String id for object set filters
○ filterParams — Array of String representing parameters for filtering
• Throws: wt.util.WTException

public static wt.ixb.objectset.ExportPackage


createExportPackageForPDX
public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

java.lang.String name,java.lang.String description,


java.lang.String exporter,java.lang.String[] generIds,
java.lang.String[] generParams)throws wt.util.WTException

• Purpose: Convenience method for the common case when objects are
collected without filtering
• Parameters:
○ name — Name of the export package
○ description — Description of the export package
○ exporter — Name of the user who makes export
○ generIds — Array of String id for object set generatory types, e.g.
{”singleDocument”,”productStructureNavigatorWi
thEPM”}
○ generParams — Array of local id for the corresponding seed objects
• Throws: wt.util.WTException

public static wt.ixb.objectset.ExportPackage


createExportPackageForPDX
public static wt.ixb.objectset.ExportPackage createExportPackageForPDX(

2184 Customization Guide


wt.inf.container.WTContainerRef container,
java.lang.String name,
java.lang.String description,
java.lang.String exporter,
java.lang.String[] generIds,
java.lang.String[] generParams)
throws wt.util.WTException

• Purpose: Convenience method for the common case when objects are
collected within a container without filtering
• Parameters:
○ container — Object reference of container
○ name — Name of the export package
○ description — Description of the export package
○ exporter — Name of the user who makes export
○ generIds — Array of String id for object set generatory types, e.g.
{”singleDocument”,”productStructureNavigatorWi
thEPM”}
○ generParams — Array of local id for the corresponding seed objects
• Throws: wt.util.WTException

doExportToPDX

public static void doExportToPDX


public static void doExportToPDX(

ExportPackageForPDX expPackage, String attachmentOption,


File dirToSave, String zipName)
throws wt.util.WTException

• Purpose: Creates pdx file on server.


• Parameters:
○ container — Source container
○ expPackage — Export package
○ attachmentOption — Attachments option. Possible values are:
◆ PDXExportHandler.XML_VALUE_ATTACHMENTS — content files
are included into pdx package (default option)
◆ PDXExportHandler.XML_VALUE_NO_ATTACHMENTS — content
files are ignored (not mentioned in pdx.xml)

Import Export Framework 2185


◆ PDXExportHandler.XML_VALUE_ATTACHMENTS_AS_FILE_
NAMES — contend files are mentioned in pdx.xml but are not
included into zip
○ dirToSave — directory on server where the resulting pdx file will be stored
○ zipName — name for the resulting pdx file (pass name without extension
since extension '.pdx' is added)
• Throws: wt.util.WTException

public static void doExportToPDX


public static void doExportToPDX(

ExportPackageForPDX expPackage, java.lang.String


java.io.File dirToSave, attachmentOption,
throws wt.util.WTException java.lang.String zipName)

• Purpose: Creates pdx file on server.


• Parameters:
○ expPackage — Export package
○ attachmentOption — Attachments option. Possible values are:
◆ PDXExportHandler.XML_VALUE_ATTACHMENTS — content files
are included into pdx package (default option)
◆ PDXExportHandler.XML_VALUE_NO_ATTACHMENTS — content
files are ignored (not mentioned in pdx.xml)
◆ PDXExportHandler.XML_VALUE_ATTACHMENTS_AS_FILE_
NAMES — content files are mentioned in pdx.xml but are not
included into zip
○ dirToSave — directory on server where the resulting pdx file will be stored
○ zipName — name for the resulting pdx file (pass without extension since
extension '.pdx' is added)
• Throws: wt.util.WTException

2186 Customization Guide


Sample Code

Preparing Data to Export


File dir = new File(dirToSave);
WTCollection seedParts = // Get List of Parts as seed
if(!seedParts.isEmpty()) {
String [] genIds = new String[seedParts.sixe()];
String [] genParams = new String[seedParts.size()];
Iterator<WTReference> it = seedParts.referenceIterator();
int i = 0;
while(it.hasNext()) {
genIds[i] = "productStructureNavigator";
genParams[i] = it.next().toString();
i++;
}
WTContainerRef sourceContainer = WTContainerRef.newWTContainerRef(container)

Export to PDX Format


ExportPackage exportPackage =
ExportPackageForPDX.createExportPackageForPDX("name_of_exp_package", "description"
"author", genIds, genParams);

PDXExportHelper.doExportToPDX(sourceContainer,(ExportPackageForPDX)exportPackage,
PDXExportHandler.XML_ATTR_ATTACHMENTS_OPTION, dir, "zipName");

Import Export Framework 2187


Adding Export Functionality in the Project
Plan Table
You can add Export List to XLSX and Export List to PDF actions to action models
for these actions to be available on the Plan table in Windchill ProjectLink.
1. Make a backup copy of the ProjectManagement-actionmodels.xml
file from <Windchill>\codebase\config\actions
2. Open the ProjectManagement-actionmodels.xml file from
<Windchill>\codebase\config\actions
3. Add the actions to the end of the plan view toolbar actions section:
<model name="plan view toolbar actions">
<action name="list_cut" type="plan" shortcut="true" />
<action name="ppPaste" type="plan" shortcut="true" />
<action name="pplist_delete" type="plan" />
<action name="edit_multi_assignments" type="resourceAssignment"
/>
<action name="edit_multiple_activities" type="planActivity" />
<action name="outdent" type="plan" shortcut="true" />
<action name="indent" type="plan" shortcut="true" />
<action name="add_to_timeline" type="plan" />
<action name="create_activity" type="planActivity" shortcut=
"true" />
<action name="explode" type="folder" />
<action name="implode" type="folder" />
<action name="import_msp_plan" type="plan" />
<action name="edit_plan_in_msp" type="plan" />
<action name="export_plan" type="plan" />
<action name="view_gantt_Explorer" type="plan" />
<action name="create_multiple_activities" type="plan" />
<action name="start_plan" type="plan" />
<action name="suspend_plan" type="plan" />
<action name="resume_plan" type="plan" />
<action name="complete_plan" type="plan" />
<action name="exportTablePDF" type="object" />
<action name="exportTableXLS" type="object" />
</model>
4. Save the file.
5. Restart the Method Server.

2188 Customization Guide


Note
You can also add these additional actions:
• Export List to Text
• Export List to CSV
• Export List to XLSX
• Export List to XML

Import Export Framework 2189


2191
60
Evolvable Classes
Background Information......................................................................................... 2193
General Externalization Guidelines ......................................................................... 2193
Hand-coded Externalization Guidelines................................................................... 2195
Migration Guidelines for Classes with Hand-coded Externalization ............................ 2196
Examples of Generated Externalization Code for Evolvable Classes ......................... 2197

This chapter describes evolvable classes.


Externalizable classes that implement the Evolvable interface are the Windchill
classes that can be serialized into BLOB columns in the database. As the
persistent structure of these classes changes, action may be required to maintain
compatibility with previous versions that have been serialized into the database.
Any modeled class that is intended to support being serialized into a BLOB
database column must implement the Evolvable interface. Once Evolvable is
implemented, the owner of the class must manage its compatibility from version
to version.
The Persistent Data Service (PDS) will report any classes being serialized into the
database that implement the NetFactor interface and not the Evolvable interface.
This allows third party classes, such as Vectors, Hashtables, and so on, to be
serialized into the database. This also allows modeled classes that do not
implement NetFactor to be serialized into the database; however, we do not
recommend this practice because it leaves the class exposed to serious data
migration problems.
The best way to specify that a modeled class will implement the Evolvable
interface is to set the Serializable property for the class to Evolvable.

2192 Customization Guide


Background Information
The generated externalization code reads and writes a data stream according to the
following order, with field values for each class ordered alphabetically:
1. BottomClass.ID
2. MiddleClass.ID
3. TopClass.ID
4. TopClass field value1
5. TopClass field value2
6. TopClass field value...N
7. MiddleClass field value1
8. MiddleClass field value2
9. MiddleClass field value...N
10. BottomClass field value1
11. BottomClass field value2
12. BottomClass field value...N
To maintain externalization compatibility of a class from version to version, it is
most important to understand the resulting stream layout for each version of a
class. When the persistent signature of a class is being changed significantly, it
may be helpful to map out the stream format for each version, in order to
understand clearly what is necessary to read a previous version of the stream.
Beyond the fundamental understanding of the stream format, points in the
following sections provide guidance concerning when and what kind of manual
intervention is necessary to maintain compatibility.

General Externalization Guidelines


The following are general externalization guidelines:
• Inserting a parent into the hierarchy is handled automatically.
• Removing a parent from the hierarchy requires implementation of
readOldVersion for pre-Release 9.0 versions.
○ The old ID and fields must be read (removed) from the stream.
• Changing the persistent signature of a class requires implementation of
readOldVersion pre-Release 9.0 versions.
○ Adding or removing fields.
○ Changing the name or type of a field.

Evolvable Classes 2193


For Windchill Release 9.0 and beyond, the virtually all changes are
handled automatically. See explanations in examples sections below for
details on how the automated readVersion<EXTERNALIZATION_
VERSION_UID> methods are generated.

2194 Customization Guide


Hand-coded Externalization Guidelines
The following are guidelines for hand-coded externalization:
• Use the version ID that is generated as the EXTERNALIZATION_VERSION_
UID constant. This allows subclasses to use it for their own comparisons.
• If you want to control the EXTERNALIZATION_VERSION_UID, you must
model it and specify its initial value in the model. A modeled attribute
supersedes the one provided by the code generator.
○ To calculate this version UID, the code generator uses the name of the
parent class, and the names and types of all the non-transient, persistent
fields.
○ It is prudent to manually control this value if the hand-coded
externalization is not related to the signature, or footprint, of the non-
transient, persistent fields of the class. (This occurrence should be rare.)
• Do not model a serialVersionUIDattribute with a value other than 1 as
this disallows the ability to read old versions of the class.

Evolvable Classes 2195


Migration Guidelines for Classes with
Hand-coded Externalization
The following are guidelines for the migration of classes with hand-coded
externalization:
• First, check whether the code generated into the readVersion method
looks the same as the code that is preserved in readExternal. If so, you
should turn off preservation and just let it all be generated.
• If the class had modeled a serialVersionUID attribute, remove it from
the model.
• Set the Serializable property to Evolvable.
• If the class already implemented readOldVersion, multiple old versions
will now need to be supported.
• If the class is not final, the following guidelines apply:
○ If the class was using something other than the generated version ID
number, you must change the read/write to use the EXTERNALIZATION_
VERSION_UID constant.
In addition, OLD_FORMAT_VERSION_UID should be ignored because it
is incorrect for your class. To read in instances externalized in the old
format, reference the version UID that was actually used.
You must also add support for the old ID to readOldVersion().
○ You must move code from readExternal() to readVersion(),
and set preserve=no for readExternal().

2196 Customization Guide


Examples of Generated Externalization
Code for Evolvable Classes
This section contains examples of generated externalization code for evolvable
classes.

Example of Version/UID Mapping Table


The generator manages the release specific externalization by storing a table that
maps each release to its externalization uid. This is stored in a comment block
following the imports section of each source file. In the following example, the
version column is the internal id for the release and the uid column is the
externalization uid for the release version. As the UID changes, the table will be
updated. A line will be added for each release version with its unique id.
//##begin version.uid preserve=yes

/* version uid

X-10 = 6676079877272797361L

*/

//##end version.uid

Example of Generated Constants


static final long serialVersionUID = 1;
public static final long EXTERNALIZATION_VERSION_UID = 6676079877272797361L;
protected static final long OLD_FORMAT_VERSION_UID = -6779867937001963664L;
// OLD_FORMAT_VERSION_UID is only valid for R4 instances of the class

Example of a writeExternal Method


public void writeExternal( ObjectOutput output )
throws IOException {

//##begin writeExternal%writeExternal.body preserve=no


output.writeLong( EXTERNALIZATION_VERSION_UID );
super.writeExternal( output );
output.writeObject( a1 );
output.writeObject( a2 );
output.writeObject( a3 );
output.writeObject( list );
output.writeObject( (size == null ? null :
size.getStringValue()) );
output.writeObject( theOneMoreReference );
output.writeObject( timeline );
output.writeObject( work );

Evolvable Classes 2197


//##end writeExternal%writeExternal.body
}

Example of a readVersion Method


The generator generates a readVersion method that include a conditional block for
each version/uid line in the mapping table, unless a developer has taken over
maintenance of the method by setting preserve=yes. The final "else" block
calls the old readOldVersion() method, to support externalization code that
might already have been implemented in this method. For negative uids, the minus
sign is converted to an underscore in the method name, since a dash is not a valid
character in Java method names.
protected boolean readVersion( MyItem thisObject, ObjectInput input,

long readSerialVersionUID, boolean passThrough, boolean superDone


)
throws IOException, ClassNotFoundException {

throws IOException, ClassNotFoundException {

//##begin readVersion%readVersion.body preserve=no

boolean success = true;

if ( readSerialVersionUID == 6676079877272797361L )

return readVersion6676079877272797361L( input,


readSerialVersionUID,
superDone );

else

success = readOldVersion( input, readSerialVersionUID,


passThrough,
superDone );

if (input instanceof wt.pds.PDSObjectInput)

wt.fc.EvolvableHelper.requestRewriteOfEvolvedBlobbedObject();

return success;

//##end readVersion%readVersion.body

2198 Customization Guide


Example of a readVersion<EXTERNALIZATION_
VERSION_UID> Method
A method is generated for each line in the version/uid mapping table, but the body
is only generated for the uid that matches the current release version. In this
example, the current release version is Windchill R9.0, so its method body will be
generated. The current release version is stored in release.properties, which is
stored in SystemGeneration.jar. The property cannot be overridden by
configuring it in user.properties.
The preserve=maybe tag has been introduced with this automated evolvability
generation to support the generator making the decision regarding whether to
preserve the method body. As with other methods, a particular method can be
permanently taken over by the developer by changing it to preserve=yes.
With these externalization methods generated to be release specific, support for
class evolution is automated but there are still issues that developers will need to
manage. The first is when an attribute (field) is removed from a release. This case
is easy, since the old externalization methods will no longer compile, since they
reference non-existent fields. The developer will need to modify the code to not
set field, but the old field must still be read off the stream, or it will throw a
runtime exception. For example, if the title field is removed from the class, the
previous readVersion<EXTERNALIZATION_VERSION_UID> methods
will need to change the line that reads the title, as follows.
/*title = (String)*/input.readObject(); // field to assign no longer exists
The second scenario is when attributes (fields) are added. In this case, there will
be no compile error and the code will deserialize without problem, but the object
could possibly be left in an invalid state. The developer should be aware of this
possibility and ensure that the object will be initialized to a valid state.
private boolean readVersion6676079877272797361L( ObjectInput input, long
readSerialVersionUID, boolean superDone )

throws IOException, ClassNotFoundException {

//##begin readVersion6676079877272797361L%
readVersion6676079877272797361L.body
preserve=maybe

if ( !superDone ) // if not doing backward


compatibility

super.readExternal( input ); // handle super class

a1 = (String)input.readObject();

a2 = (Date)input.readObject();

a3 = (Xyz)input.readObject();

Evolvable Classes 2199


list = (Vector)input.readObject();

String size_string_value = (String)input.readObject();

try { size = (MySize)wt.fc.EnumeratedTypeUtil.toEnumeratedType


( size_string_value
); }

catch( wt.util.WTInvalidParameterException e ) { // old format

size = MySize.toMySize( size_string_value );

theOneMoreReference = (ObjectReference)input.readObject();

timeline = (Timeline)input.readObject();

work = (MyAddress)input.readObject();

return true;

//##end readVersion6676079877272797361L%readVersion6676079877272797361L.body

Example of a readOldVersion Method


This method is generated virtually the same as readVersion
<EXTERBALIZATION_VERSION_UID> to support backward compatibility. To
support backward compatibility for multiple releases, the method should include a
conditional block for each old version that is being supported. Each condition
should check for the version UID that was used in that version of the class, and
the block that reads the fields should be the same set of read calls that the were
used for that version. The generated OLD_FORMAT_VERSION_UID constant is
only valid for R4 instances of the class. Fields that no longer exist can be read and
discarded (not assigned). Fields that didn't exist for the version can be initialized
in the manner necessary to put the object into a valid state.
private boolean readOldVersion( ObjectInput input,
long readSerialVersionUID, boolean passThrough, boolean superDone
)
throws IOException, ClassNotFoundException {

//##begin readOldVersion%readOldVersion.body preserve=no

boolean success = true;

// handle previous version


if ( readSerialVersionUID == OLD_FORMAT_VERSION_UID ) {

2200 Customization Guide


a1 = (String)input.readObject();
a2 = (Date)input.readObject();
a3 = (Xyz)input.readObject();
list = (Vector)input.readObject();
String size_string_value = (String)input.readObject();

try { size = (MySize)wt.fc.EnumeratedType.toEnumeratedType(


size_string_value ); }

// in case it was old format


catch( wt.util.WTInvalidParameterException e ) {
size = MySize.toMySize( size_string_value );
}

theOneMoreReference = (ObjectReference)input.readObject();
timeline = (Timeline)input.readObject();
work = (MyAddress)input.readObject();
}

else if ( !superDone ) {
success = super.readVersion( this, input,
readSerialVersionUID, false, false ); // reformatted stream-

if ( success &amp;&amp; !passThrough &amp;&amp; // forced pass


through to
skip me
// I have been inserted into hierarchy
readSerialVersionUID != super.EXTERNALIZATION_VERSION_UID )
// try mine again
readVersion( this, input, input.readLong(), false, true );
}
else
throw new java.io.InvalidClassException( CLASSNAME,
"Local class not compatible:"
+ " stream classdesc externalizationVersionUID=
" + readSerialVersionUID
+ " local class externalizationVersionUID=
" + EXTERNALIZATION_VERSION_UID );

return success;

//##end readOldVersion%readOldVersion.body

Evolvable Classes 2201


61
Creating Large Objects (LOBs)
Modeling Large Objects ......................................................................................... 2204

This chapter describes how to create large objects (LOBs).

2203
Modeling Large Objects
You can model an attribute to be a binary large object (BLOB) in one of the
following four ways:
• By default when the attribute type is a class that does not map to any of the
other java.sql.Types.
• Explicitly set the attribute’s class to LobLocator. Use this technique for large
objects that you access infrequently.
• Model the attribute to map to a SMALLBLOB by changing the ColumnType
property under the Windchill tab of the attribute specification. Use this
technique for objects that can expand and contract, but are never more than a
certain size.
• Model the attribute to map to an INLINEBLOB by changing the ColumnType
property under the Windchill tab of the attribute specification. Use this
technique for objects that can expand and contract, and are typically small in
size, but occasionally require large storage size (such as, adhoc ACLs).

DDL Generation
The DDL generated by Windchill defines the BLOB columns to be stored in their
own tablespace. This can be controlled for each attribute by changing the
tablespace property under the Windchill tab while modeling. The tablespace must
be defined before the DDL is executed. The name of the default tablespace to
contain BLOBs can be modified using a property in the user.properties file. See
the properties.html file for details on the specific property.

Note
Both Oracle and SQLServer support this tablespace feature. SQLServer
terminolgy refers to this concept as FileGroups.

Reading and Writing LOBs


BLOBs are either read or written as byte arrays or as Serialized objects each time
the object containing the BLOB is read, created, or updated. If the BLOB is
modeled using LobLocator, then only the LOB locator is retrieved with each read/
write and a second step is required to retrieve or store the LOB. The
StandardPersistenceManager provides getLob() and updateLob() to perform these
operations.

2204 Customization Guide


Be careful about the types of objects that you serialize into the database. Using
default Java serialization is especially prone to breaking if the Java class files are
recompiled with possible changes, or sometimes just with different compilers.
Programming to allow upward compatibility of serialized representations is
difficult. One technique is as follows:
1. Make the class Externalizable, which aids performance as well.
2. Specify a fixed serialVersionUID value.
3. Put an internal version number on the object stream and handle version
changes in code.
See the code-generated Externalizable business classes for an example of this
technique. The disadvantage is that all subclasses are now Externalizable and
require readExternal and writeExternal methods. You can use the same type of
technique with Serializable (fix serialVersionUID and implement read/
writeObject) if independence from the class hierarchy is important.

Small BLOBs
SMALLBLOBs are encoded into Strings before being stored and are mapped to
VARCHAR2(4000) rather than BLOB. Because of the size limitation of 4,000
characters, this option is inflexible and should be used with caution. Your code
should be prepared to handle the possible exception that is thrown if the size of
the attribute grows beyond what can be encoded into 4,000 characters.

Inline BLOBs
INLINEBLOBs combine the features of SMALLBLOB and BLOB to provide
better performance when data is small, but still allow for large data storage
capability. An attribute that is stored as an INLINEBLOB uses two columns:
• A VARCHAR2(4000) column
• A BLOB column
Each object is examined at runtime and, when the data is small enough, it is stored
in the VARCHAR(4000) column; otherwise, it is stored in the BLOB column.
When the data is stored in the VARCHAR(4000) column, no additional datastore
calls are required to read the BLOB data.
Using an INLINEBLOB introduces a fixed cost in terms of storage (two columns
are used instead of one) and additional processing at runtime. However, when the
majority of data is stored “inline” with the table, this cost is negligible in
comparison to the performance benefits. If most of the data exceeds the 4000-byte
limit, BLOB storage is probably more appropriate. However, if it is known that all
data will never exceed the 4000-byte limit, SMALLBLOB should be used.

Creating Large Objects (LOBs) 2205


Example
An example follows, which uses the classes shown in the following figure.

/*
*
* Lobber is an example of storing BLOBs. BlobClass has three BLOBs:
* imablob which is LobLocator, and imasmallblob, and
imanothersmallblob
*
* which are
*
*/

public class Lobber {

private static final int size = 1000;


private static BlobClass atr = null;
private static Enumeration lob_files;

public static void goLobs( String lob_dir ) {

try {

// create a BlobClass object

lob_files = getLobFiles( lob_dir );

// loop thru the files in this directory


if ( lob_files != null ) {
if ( lob_files.hasMoreElements() ) {
try {
String lobIt = (String)lob_files.nextElement();

2206 Customization Guide


File lobFile = new File(lobIt);

long len = lobFile.length();


System.out.println( "file length "+len );
InputStream aIs = new FileInputStream(lobFile);
System.out.println( "bytes available on this
InputStream "+aIs.available());

atr = createBlobClassRec(lobIt);

Transaction trx = new Transaction();


trx.start();
// save the class containing the LOB
atr = (BlobClass)
PersistenceHelper.manager.save(atr);

// Save a LOB of unknown length. Note that


// PersistenceServerHelper is used
// rather than PersistenceHelper. This
// is server side only code.

long theLength =
(long)PersistenceServerHelper.manager.updateLob(
(Persistable)atr,
atr.getImablob(),
aIs,
false );
len = lobFile.length();
// save a LOB of known length
System.out.println( "file length "+len );
aIs = new FileInputStream(lobFile);
System.out.println( "bytes available on
this InputStream "+aIs.available());

PersistenceServerHelper.manager.updateLob(
(Persistable)atr,
atr.getImablob(),
aIs,
len,
false );
trx.commit();
trx = null;
aIs.close();

}
catch ( FileNotFoundException fnf )
{ fnf.printStackTrace();}
catch ( IOException ioe )
{ioe.printStackTrace();}
finally {
if ( trx != null ) {

Creating Large Objects (LOBs) 2207


trx.rollback();
throw new RuntimeException("Error
processing lobs");
}
}
}
}

}
catch (WTException WTe) {
WTe.printStackTrace();
}
}

private static Enumeration getLobFiles( String ldir ) {

String[] s_files = null;


Vector aVec = new Vector();
File lob_dir = new File( ldir );

if ( !lob_dir.isDirectory() )
return null;

s_files = lob_dir.list();
for ( int i=0; i
for ( int i=0; i

2208 Customization Guide


62
Customizing Data Formats
Adding and Updating Data Formats for Content Holders........................................... 2210

This chapter explains how to customize data formats.

2209
Adding and Updating Data Formats for
Content Holders
When content files are added to a content holder object, the format of the file
(based on the file name extension) is set automatically upon upload. The available
formats are stored as DataFormat objects in the system.
In some cases, you may need to augment or change the existing data formats to
accommodate additional MIME types associated with your enterprise data.

Note
Any changes made to existing data formats should be treated as
customizations to your code. Be sure to follow the coding practices introduced
in Managing Customizations on page 100

A data format:
• Sets the MIME type when a file is downloaded.
• Supplies the icon that will represent the object in browser displays.
• Informs the user of the file format.
You can use a command-line utility, provided by Windchill, to maintain data
format objects.

Adding Data Formats


Use the following command to add a data format to the system:
java wt.content.DataFormatUtil -add
You are then prompted to provide values for the following attributes:
Attribute Description
Format name (required) Displays this name (for example,
Microsoft Word) in the client to
identify the file format. The value
specified must be unique.
MIME type (required) The MIME type (for example,
application/msword) to be used
in downloading a file of this type. You
must specify a space-separated list of
valid extensions for the MIME type (for
example, .txt, .text, or .t). This is the
way in which the format of these

2210 Customization Guide


Attribute Description
objects will be set when a file is
uploaded.
Description (optional) Describes this data format object.
Indexable (required) Indicates whether or not this data
format type can be indexed by
RetrievalWare. Most MIME types
supported by RetrievalWare are defined
in the system when it is installed.
However, any simple text format is
indexable.
For a complete list of supported file
type, see RetrievalWare documentation.
Icon (required) Defines the path to a subdirectory of
the codebase that contains the icon for
this format type. When you add a data
format type, you have the option to
reference an icon other than one of
those found in the Windchill codebase.
However, you must ensure that the
pixel size for your icon is 16 x 16 to
avoid an error when viewing icons.
Extensions (required) Defines the extensions that are
associated with this particular mime
type (for example, .doc or .rtf for
Microsoft Word).

After adding a new format for a MIME type using DataFormatUtil, you must
add a new line for that format to the wt\content\FormatNameRB.java file
and then run the ResourceBuild utility to generate resource classes from
FormatNameRB.java file. Enter the new line using the following format:
@RBEntry("Display_value")
public static final String unique_number = "MIME type name";
For example, if the MIME type name is Java Archive and display value
desired is Java Archive File, then new entry is as follows:
@RBEntry("Java Archive File ")
public static final String PRIVATE_CONSTANT_58 = Java Archive";
For details on using the ResourceBuild utility, see the System Generation on
page 1943.

Customizing Data Formats 2211


Updating Data Formats
Enter the following command to update an existing data format:
java wt.content.DataFormatUtil -update
The tool prompts you for the format name of an existing data format object. After
you have identified the data format, you can update its attributes.
If you make a change to the MIME type name or display value, you must also
update the corresponding line in the wt\content\FormatNameRB.java
file.

Note
If you change the MIME type of a data format object, you must stop and
restart the method server to implement the change.

Listing Available Data Formats


Enter the following command to display a list of existing data format objects and
their attributes:
java wt.content.DataFormatUtil -list

Renaming a Data Format


Enter the following command to rename a data format:
java wt.content.DataFormatUtil -rename
The tool prompts for the format name of an existing data format object. After the
data format is identified, the tool will prompt for a new name for the data format.

Deleting a Data Format


Enter the following command to delete a data format:
java wt.content.DataFormatUtil -delete
The tool prompts for the format name of an existing data format object. After the
data format is identified, it gets deleted. If any object currently refers to this data
format, than that object’s data format is changed to UNKNOWN.

2212 Customization Guide

You might also like