You are on page 1of 1432

Windchill Customizers Guide

Windchill 9.1 Pro/INTRALINK 9.1 Arbortext Content Manager Windchill PDMLink Windchill ProjectLink May 2009

Copyright 2008 Parametric Technology Corporation. All Rights Reserved. User and training guides and related documentation from Parametric Technology Corporation 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. For Important Copyright, Trademark, Patent, Licensing and Data Collection Information: For Windchill products, select About Windchill at the bottom of the product page. For InterComm products, on the Help main page, click the link for Copyright 20xx. For other products, click Help > About on the main menu of the product. UNITED STATES GOVERNMENT RESTRICTED RIGHTS LEGEND This document and the software described herein are Commercial Computer Documentation and Software, pursuant to FAR 12.212(a)-(b) (OCT95) or DFARS 227.7202-1(a) and 227.7202-3(a) (JUN95), and are provided to the US Government under a limited commercial license only. For procurements predating the above clauses, use, duplication, or disclosure by the Government is subject to the restrictions set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software Clause at DFARS 252.227 7013 (OCT88) or Commercial Computer Software-Restricted Rights at FAR 52.227 19(c)(1)-(2) (JUN87), as applicable. 10012008 Parametric Technology Corporation, 140 Kendrick Street, Needham, MA 02494 USA

Contents

Change Record ................................................................................................ xxvii About This Guide.............................................................................................. xxxi


Related Documentation .............................................................................................................xxxi Technical Support.....................................................................................................................xxxii Documentation for PTC Products.............................................................................................xxxii Comments ............................................................................................................................... xxxiii

I. Customization Overview Section


Customization Overview.................................................................................... 1-1
Configuration Options.................................................................................................................1-2 Properties and Preferences ................................................................................................. 1-2 Object Initialization Rules .................................................................................................... 1-3 Soft Typing........................................................................................................................... 1-4 Organization and Container Templates ............................................................................... 1-4 Customizations ...........................................................................................................................1-5 Data Model Customizations ................................................................................................. 1-5 Service Customizations ....................................................................................................... 1-5 User Interface Customizations............................................................................................. 1-6 Info*Engine .......................................................................................................................... 1-6 Custom Reports ................................................................................................................... 1-6 Windchill Customization Points ..................................................................................................1-8 Windchill Supported API ...................................................................................................... 1-8

The Windchill Development Environment........................................................ 2-1


Directory Structure......................................................................................................................2-2 The codebase Directory....................................................................................................... 2-5 The src Directory ................................................................................................................. 2-7 Artifact Management ..................................................................................................................2-8 Environment Variables ...............................................................................................................2-9 Class path............................................................................................................................ 2-9 Path ..................................................................................................................................... 2-9 SQL path.............................................................................................................................. 2-9 Rational Rose virtual path map............................................................................................ 2-9

iii

Property Files........................................................................................................................... 2-10 wt.properties file ................................................................................................................ 2-11 service.properties file ........................................................................................................ 2-12 tools.properties file ............................................................................................................ 2-13 user.properties file............................................................................................................. 2-13 db.properties file................................................................................................................ 2-14 Properties and Property Files .................................................................................................. 2-15 Application Context Service/Resource Properties............................................................. 2-15

Getting Started With Windchill Customization ................................................ 3-1


An Overview of the Windchill Development Process ................................................................. 3-2 Verify The Development Environment................................................................................. 3-2 Model the Object in Rose .................................................................................................... 3-3 Generate Java Classes From Rose .................................................................................... 3-5 Create Database Tables ..................................................................................................... 3-6 Initialize the Object .............................................................................................................. 3-6 Design the GUI Layout ........................................................................................................ 3-6 Code the GUI ...................................................................................................................... 3-7 Run the Applet in Mozilla or Internet Explorer..................................................................... 3-8

Modeling Business Objects ............................................................................... 4-1


Rational Rose and Windchill ...................................................................................................... 4-2 Windchill Modeling Heuristics .................................................................................................... 4-4 Windchill Foundation Abstractions............................................................................................. 4-8 Windchill Foundation Interfaces .......................................................................................... 4-8 Windchill Foundation Classes ........................................................................................... 4-10

Managing Customizations ................................................................................. 5-1


Setting Up a Directory Structure for Managing Customized Files and Text Tailoring ................ 5-2 Directory Structure Diagram for Customized Files and Text Tailoring ................................ 5-2 PTC Script for Working with Customized Files.................................................................... 5-5 Using the Safe Area Directory Structure When Customizing Files ..................................... 5-7 Using the Safe Area Directory Structure When Installing the Windchill Service Pack ........ 5-8 Best Practices for Customizing Files Supplied by PTC ............................................................. 5-9 Changing Displayed Text Found in RBINFO Files .............................................................. 5-9 Managing codebase Property Files................................................................................... 5-11 Managing HTML Templates in the <Windchill>/codebase/templates/ Directory ............... 5-12 Managing the LogicalAttributes.xml File............................................................................ 5-12 Managing codebase/{wtcore,netmarkets,pdmlink} Files ................................................... 5-13 Managing Windchill Info*Engine Tasks ............................................................................. 5-13 INI Files for Workgroup Managers .................................................................................... 5-13

iv

Windchill Customizers Guide

Managing Client JAR Files ................................................................................................ 5-14 Best Practices for Adding New Packages and Files.................................................................5-26 Modeling Recommendations ............................................................................................. 5-27 Adding a Custom Service Provider Property File .............................................................. 5-27

Windchill Utilities................................................................................................ 6-1


About the xconfmanager Utility...................................................................................................6-2 Formatting Property Value Guidelines ................................................................................. 6-4 About the windchill Command ....................................................................................................6-6 About the windchill shell .............................................................................................................6-8

Customization Tutorial....................................................................................... 7-1


Tutorial Overview........................................................................................................................7-2 Goals ................................................................................................................................... 7-2 Assumptions ........................................................................................................................ 7-2 Outline ................................................................................................................................. 7-2 Create Administrator and User ...................................................................................................7-4 Create a Library and Document ...............................................................................................7-12 Create a New Attribute Definition and Add it to the Document Type........................................7-17 As the End User, Create a Document with the new Attribute...................................................7-22 Create a Document Soft Type ..................................................................................................7-25 Create an Instance of the New Document Soft Type ...............................................................7-27 Model a New Document Subclass............................................................................................7-28 Create an Instance of the New Document Subclass ................................................................7-38 Verify the Customizations.........................................................................................................7-39 Summary ..................................................................................................................................7-41

II. User Interface Customization Section


User Interface Technology Overview ............................................................... 8-1
Windchill Client Architecture Overview.......................................................................................8-2 Basic Elements of a JSP page ............................................................................................ 8-2 Java Beans .......................................................................................................................... 8-3 Custom Tags and TagLibs................................................................................................... 8-3 Java Services ...................................................................................................................... 8-3 Reusable Components ........................................................................................................ 8-4 Adding Custom Code to all Windchill Client Architecture Pages................................................8-8 Javascript and CSS files ...................................................................................................... 8-8 Maintenance Messaging ...................................................................................................... 8-8 Customization Points ........................................................................................................... 8-8 Javascript Functions Overview...................................................................................................8-9

Contents

TableUtils package........................................................................................................... 8-9 TreeHandler ...................................................................................................................... 8-10 asyncResponseHandler .................................................................................................... 8-11 rowHandler ........................................................................................................................ 8-11 requestHandler.................................................................................................................. 8-12 Other functions in main.js.................................................................................................. 8-12 Wizard.js functions ............................................................................................................ 8-13

Generic UI Customizations ................................................................................ 9-1


Handling Icons for Business Objects ......................................................................................... 9-2 Modeled Business Objects.................................................................................................. 9-2 Defining Localizable Text for the UI ........................................................................................... 9-3 The rbInfo File Format......................................................................................................... 9-3 Customizing Localizable Display Names for Modeled Elements ........................................ 9-3 Customizing the Handling of Soft Attributes .............................................................................. 9-6 Format of AllClients.xml ...................................................................................................... 9-6 Example .............................................................................................................................. 9-7 Customizing Role-Based UI Functions - Attribute Visibility........................................................ 9-8 Objective ............................................................................................................................. 9-8 Solution ............................................................................................................................. 9-10 Customization Points......................................................................................................... 9-13 Sample Code..................................................................................................................... 9-16 Additional Resources ........................................................................................................ 9-16 Customizing Role-Based UI Functions - Action Visibility ......................................................... 9-17 Preferences.............................................................................................................................. 9-18 Preference Macros ............................................................................................................ 9-18 Setting the Hierarchy......................................................................................................... 9-18 Getting Preferences .......................................................................................................... 9-19 Clearing a Preference ....................................................................................................... 9-19 Preference Registry........................................................................................................... 9-20 Creating a Preference ....................................................................................................... 9-20 Deleting a Preference........................................................................................................ 9-23 Constructing URLs................................................................................................................... 9-24 The URLFactory ................................................................................................................ 9-24 Using the URLFactory with JSP ........................................................................................ 9-24 Utilizing Windchill Gateways and Servlets with the URLFactory....................................... 9-24 Utilizing relative links in the URLFactory ........................................................................... 9-24 Setting the URLFactory to Output Fully Qualified HREFs................................................. 9-25 Writing a Mapping File....................................................................................................... 9-25 Capturing Errors From the URLFactory ............................................................................ 9-26

vi

Windchill Customizers Guide

Character Encoding in the URLFactory ............................................................................. 9-26 Offline Package Customization ................................................................................................9-27 Objective ............................................................................................................................ 9-27 Solution .............................................................................................................................. 9-27 Customization Points ......................................................................................................... 9-29 Limitations.......................................................................................................................... 9-29 Offline Package View Supported Icons ............................................................................. 9-29 Sample Code ..................................................................................................................... 9-31 System Banner Alert Message .................................................................................................9-32 Turning on the alert banner feature ................................................................................... 9-32 Displaying the alert message on the top of Windchill UI pages ......................................... 9-32

Customizing HTML Clients Using the Windchill JSP Framework................ 10-1


Customizing Generic Aspects of JSP Pages............................................................................10-2 Customizing UI Branding..........................................................................................................10-2 Customizing the UI with Ajax....................................................................................................10-4 Objective ............................................................................................................................ 10-4 Solution .............................................................................................................................. 10-4 Sample Code ..................................................................................................................... 10-6 Checkin/Checkout ....................................................................................................................10-8 Objective ............................................................................................................................ 10-8 Solution .............................................................................................................................. 10-9 Sample Code ................................................................................................................... 10-10 Component Access Control....................................................................................................10-11 Objective .......................................................................................................................... 10-11 Solution ............................................................................................................................ 10-12 Customization Points ....................................................................................................... 10-13 Sample Code ................................................................................................................... 10-14 Attachments............................................................................................................................10-16 Objective .......................................................................................................................... 10-16 Customization Points ....................................................................................................... 10-22 Limitations........................................................................................................................ 10-23 Sample Code ................................................................................................................... 10-24 Property Panel........................................................................................................................10-26 Objective .......................................................................................................................... 10-26 Solution ............................................................................................................................ 10-26 Customization Points ....................................................................................................... 10-28 Sample Code ................................................................................................................... 10-30 Customizing Access Control For Packages ...........................................................................10-33 Objective .......................................................................................................................... 10-33

Contents

vii

Solution ........................................................................................................................... 10-33 Limitations ....................................................................................................................... 10-34 Sample Code................................................................................................................... 10-35 Additional Resources ...................................................................................................... 10-36 Generating HTML Tags for ProductView Visualization Within a JSP Page ........................... 10-37 Tools Overview ...................................................................................................................... 10-40 Available Attributes Report.............................................................................................. 10-40 Debugging ....................................................................................................................... 10-41 Taglib documentation ...................................................................................................... 10-42 Action Report................................................................................................................... 10-43 Action Model Report........................................................................................................ 10-47 Adding Validation Logic for Actions and Properties ............................................................... 10-51 Objective ......................................................................................................................... 10-51 Applicability ..................................................................................................................... 10-51 Structure.......................................................................................................................... 10-51 Participants...................................................................................................................... 10-51 Collaborations ................................................................................................................. 10-52 Consequences ................................................................................................................ 10-53 Implementation................................................................................................................ 10-53 Sample Code................................................................................................................... 10-60

Adding Actions and Hooking Them Up in the UI ........................................... 11-1


Windchill Client Architecture Action Framework Overview ...................................................... 11-2 Objective ........................................................................................................................... 11-2 Solutions............................................................................................................................ 11-2 Customization Points....................................................................................................... 11-14 Sample Code................................................................................................................... 11-15 Tab Models ............................................................................................................................ 11-16 Objective ......................................................................................................................... 11-16 Action Visibility ....................................................................................................................... 11-27 Objective ......................................................................................................................... 11-27 Solution ........................................................................................................................... 11-29 Customization Points....................................................................................................... 11-32 Sample Code................................................................................................................... 11-35 Additional Resources ...................................................................................................... 11-35 Navigation Stickiness............................................................................................................. 11-36 Objective ......................................................................................................................... 11-36 Solution ........................................................................................................................... 11-36 Prerequisite knowledge ................................................................................................... 11-36 Additional Resources: ..................................................................................................... 11-38

viii

Windchill Customizers Guide

Gathering the Data for the UI........................................................................... 12-1


Data Acquisition Configuration Properties................................................................................12-2 Objective ............................................................................................................................ 12-2 Solution .............................................................................................................................. 12-2 Customization Points ......................................................................................................... 12-8 Sample Code ..................................................................................................................... 12-8 Acquiring Data via Info*Engine.................................................................................................12-9 Objective ............................................................................................................................ 12-9 Solution .............................................................................................................................. 12-9 Customization Points ....................................................................................................... 12-11 Limitations........................................................................................................................ 12-12 Sample Code ................................................................................................................... 12-13 Additional Resources ....................................................................................................... 12-14 NmObject Utilities ...................................................................................................................12-15 Objective .......................................................................................................................... 12-15 Solution ............................................................................................................................ 12-15 NmCommandBean .......................................................................................................... 12-17 NmAction ......................................................................................................................... 12-18 NmOid.............................................................................................................................. 12-18 NmSimpleOid................................................................................................................... 12-18 NmContext ....................................................................................................................... 12-18

Presenting Information in the UI ..................................................................... 13-1


Attribute Handling .....................................................................................................................13-2 Objective ............................................................................................................................ 13-2 Solution .............................................................................................................................. 13-4 Customization Points ....................................................................................................... 13-12 Additional Resources ....................................................................................................... 13-20 Soft Attributes and SCAs........................................................................................................13-21 Constructing and Rendering a Table Using the JSP Framework ...........................................13-23 Objective .......................................................................................................................... 13-23 Solution ............................................................................................................................ 13-25 Customization Points ....................................................................................................... 13-28 Limitations........................................................................................................................ 13-61 Sample Code ................................................................................................................... 13-62 Other Resources.............................................................................................................. 13-63 Windchill Client Architecture Tree ..........................................................................................13-64 Objective .......................................................................................................................... 13-64 Solution ............................................................................................................................ 13-66 Customization Points ....................................................................................................... 13-72

Contents

ix

Sample Code................................................................................................................... 13-90 Adding Custom Modeled Attributes to all Table Views .......................................................... 13-91 Attribute Tables...................................................................................................................... 13-92 Objective ......................................................................................................................... 13-92 Solution ........................................................................................................................... 13-92 Sample Code................................................................................................................... 13-95 Generating the Name Attribute Server................................................................................... 13-97 Objective ......................................................................................................................... 13-97 Solution ........................................................................................................................... 13-97 Customization Points..................................................................................................... 13-100 Limitations ..................................................................................................................... 13-100 Sample Code................................................................................................................. 13-101 Additional Resources .................................................................................................... 13-101 Partial Activation of JSCA .................................................................................................... 13-102 Icon Delegates ..................................................................................................................... 13-103 Objective ....................................................................................................................... 13-103 Solution ......................................................................................................................... 13-103 UI Validation......................................................................................................................... 13-109 Objective ....................................................................................................................... 13-109 Solutions........................................................................................................................ 13-110 Customizing the Find Number Field..................................................................................... 13-152

Constructing Wizards....................................................................................... 14-1


Windchill Client Architecture Wizard ........................................................................................ 14-2 Objective ........................................................................................................................... 14-2 Solution ............................................................................................................................. 14-4 Customization Points......................................................................................................... 14-7 Limitations ....................................................................................................................... 14-15 Sample Code................................................................................................................... 14-18 Wizard Processing ................................................................................................................. 14-19 Objective ......................................................................................................................... 14-19 Solution ........................................................................................................................... 14-20 Limitations ....................................................................................................................... 14-37 Additional Resouces........................................................................................................ 14-37 Building Wizards to Create a Single Object ........................................................................... 14-38 Objective ......................................................................................................................... 14-38 Solution ........................................................................................................................... 14-41 Customization Points....................................................................................................... 14-82 Sample Code................................................................................................................... 14-84 Additional Resources ...................................................................................................... 14-89

Windchill Customizers Guide

Building Wizards to Edit a Single Object ................................................................................14-90 Objective .......................................................................................................................... 14-90 Solution ............................................................................................................................ 14-92 Sample Code ................................................................................................................. 14-107 Additional Resources ..................................................................................................... 14-113

Information Pages ............................................................................................ 15-1


Information Pages ....................................................................................................................15-2 Objective ............................................................................................................................ 15-2 Solution .............................................................................................................................. 15-2 Structure ............................................................................................................................ 15-3 Design Elements................................................................................................................ 15-3 Collaborations.................................................................................................................... 15-4 Consequences................................................................................................................... 15-4 Implementation .................................................................................................................. 15-4 Create a jsp for your object type ........................................................................................ 15-6 Setup ............................................................................................................................... 15-12 Sample Code ................................................................................................................... 15-12 Known Uses..................................................................................................................... 15-14

Incorporating Pickers in JSP Clients.............................................................. 16-1


Picker Interaction......................................................................................................................16-2 Objective ............................................................................................................................ 16-2 Solution .............................................................................................................................. 16-3 Customization Points ......................................................................................................... 16-9 Sample Code ................................................................................................................... 16-10 Common Picker Configuration Options ..................................................................................16-14 Objective .......................................................................................................................... 16-14 Solution ............................................................................................................................ 16-14 Sample Code ................................................................................................................... 16-16 Configuring a Context Picker..................................................................................................16-18 Objective .......................................................................................................................... 16-18 Solution ............................................................................................................................ 16-19 Customization Points ....................................................................................................... 16-21 Configuring an Item Picker .....................................................................................................16-24 Objective .......................................................................................................................... 16-24 Solution ............................................................................................................................ 16-25 Customization Points ....................................................................................................... 16-27 Configuring an Organization Picker........................................................................................16-31 Objective .......................................................................................................................... 16-31 Solution ............................................................................................................................ 16-32

Contents

xi

Customization Points....................................................................................................... 16-34 Configuring a Type Picker...................................................................................................... 16-37 How to Use Type Picker.................................................................................................. 16-37 Overview ......................................................................................................................... 16-41 Customization Points....................................................................................................... 16-43 Attributes and Parameters supported by Type Picker..................................................... 16-44 Source code location....................................................................................................... 16-47 Configuring a User Picker ...................................................................................................... 16-50 Objective ......................................................................................................................... 16-50 Solution ........................................................................................................................... 16-51 Customization Points....................................................................................................... 16-53 Configuring a Participant Picker............................................................................................. 16-57 Objective ......................................................................................................................... 16-57 Solution ........................................................................................................................... 16-57 Customization Points....................................................................................................... 16-61 Sample Code................................................................................................................... 16-63

JSP Customization Scenarios ......................................................................... 17-1


Configuring a Picker to Offer Only Specific Soft Types Based on User-specified Criteria including Restricted Life Cycle States..................................................................................................... 17-2 Building a Picker that Enables Users to Select Projects from an External Project DB ............ 17-8 Pickers from table toolbar ...................................................................................................... 17-13 Objective ......................................................................................................................... 17-13 Solution ........................................................................................................................... 17-13 Customization Points....................................................................................................... 17-14 Generating HTML Tags for ProductView Visualization Within a JSP Page ........................... 17-16

Customizing the Product Structure Explorer (PSE) ...................................... 18-1


Customizing PSE Menus, Toolbars and Popup Menus ........................................................... 18-2 Objective ........................................................................................................................... 18-2 Solution ............................................................................................................................. 18-3 Customization Points......................................................................................................... 18-6 Limitations ......................................................................................................................... 18-6 Other Resources ............................................................................................................... 18-7 Customizing PSE Table Display .............................................................................................. 18-8 Objective ........................................................................................................................... 18-8 Solution ............................................................................................................................. 18-9 Other Resources ............................................................................................................. 18-12 Customizing PSE for Soft Types............................................................................................ 18-13 Objective ......................................................................................................................... 18-13 Solution ........................................................................................................................... 18-16

xii

Windchill Customizers Guide

Customization Points ....................................................................................................... 18-22 Other Resources.............................................................................................................. 18-23 Customizing PSE to Handle Modeled Subclasses .................................................................18-24 Objective .......................................................................................................................... 18-24 Solution ............................................................................................................................ 18-24 Customization Points ....................................................................................................... 18-29 Other Resources.............................................................................................................. 18-30 Customizing PSE Structure Queries ......................................................................................18-31 Objective .......................................................................................................................... 18-31 Solution ............................................................................................................................ 18-32 Other Resources.............................................................................................................. 18-34 Customizing Attribute Displays within Section Headings .......................................................18-35 Customizing the Display of Attributes in Groups ............................................................. 18-35 Expanding/Collapsing the Display Groupings.................................................................. 18-40 Customizing the Number of Columns to Display ............................................................. 18-41 Customizing Tabs - Configure Existing Tabs with Subtabs....................................................18-43 Allow Additional Steps During New Object Creation ..............................................................18-45 Type Picker Display Customization ........................................................................................18-47 Disabling Actions by Object Type...........................................................................................18-49 Validator isValidTypeValidator ......................................................................................... 18-50 Creating a Requirements Tab ................................................................................................18-51 Updating the <TabSet> element to include the Requirements tab .................................. 18-51 Define a <Tab> element for the Requirements tab.......................................................... 18-52 Define the <AssociationTable> element for the Requirements tab ................................. 18-53 Define the <StructureAuthorDefinition> element for the association table ...................... 18-53 Define the <StructureDefinitionSimple> element for the part to requirement association 18-54 Define the <Table> element for the Requirement type .................................................... 18-54 Define the menus for the Requirements tab .................................................................... 18-56 Define the labels, tool tips and mnemonics for the Requirements tab............................. 18-59 Define <ActionDefinition> elements referred to in the <MenuItem> elements ................ 18-60 Implement an 'enabled decider' class to control when the tab is enabled ....................... 18-62 Configurable Link Tables........................................................................................................18-67 Configurable Links Example ............................................................................................ 18-67 Installing the Configurable Links Example ....................................................................... 18-67 Uninstalling the Configurable Links Example .................................................................. 18-68 Customizing Configurable Link Tables ............................................................................ 18-69 Defining Access Control Policy Rules for Configurable Links.......................................... 18-73

Customizing Windchill MPMLink .................................................................... 19-1


Customizing Windchill MPMLink Overview ..............................................................................19-2

Contents

xiii

XML Configuration Files .................................................................................................... 19-3 General Windchill MPMLink Customizations ........................................................................... 19-5 Changing the Availability of Windchill MPMLink Explorers ............................................... 19-5 Changing Default Units of Measure .................................................................................. 19-5 Customizing the Process Plan Explorer................................................................................... 19-7 Changing Units of Measure for Cumulated Time and Cost............................................... 19-7 Customizing Work Instructions.......................................................................................... 19-7 Customizing a Windchill MPMLink Explorer.................................................................... 19-16 Changing Operation Numbering...................................................................................... 19-18 Customizing the Manufacturing Product Structure Explorer .................................................. 19-19 Customizing the Transforming of an eBOM into an mBOM ............................................ 19-19

Customizing Search Functionality .................................................................. 20-1


Adding a Search Component................................................................................................... 20-2 Introduction........................................................................................................................ 20-2 Defining a Search Component .......................................................................................... 20-2 Using a Component........................................................................................................... 20-4 Searching for Soft Types and Attributes .................................................................................. 20-6 Soft Types in Searches ..................................................................................................... 20-6 Soft Attributes in Searches................................................................................................ 20-6 Adding Attributes to the Search Pages .................................................................................... 20-7 Adding Attributes to Advanced Search Page .................................................................... 20-7 The SearchableAttributes.properties File................................................................................. 20-8 Adding Actions to the Search Results Table............................................................................ 20-9 Adding Table Actions ........................................................................................................ 20-9 Row Level Actions............................................................................................................. 20-9 Changing the Layout of the Search Page .............................................................................. 20-10 Adding a New Type to the Search User Interface.................................................................. 20-11 Customizing the Layout of the Search Results Page............................................................. 20-12 Adding Different Formats for Exporting Search Results ........................................................ 20-14 Update DCA Configurations ............................................................................................ 20-14 Create New Style Sheet .................................................................................................. 20-14 Customizing Index Search Capabilities ................................................................................. 20-15 Input Parameters to the Index-Search Webject .............................................................. 20-15 Sorting IndexSearch Search Results .............................................................................. 20-17 Customizing Indexing Behavior ............................................................................................. 20-19 IndexSearch Fields.......................................................................................................... 20-19 Creating a Custom InstreamIndexDelegate .................................................................... 20-20 Windchill Client Architecture Search Customization .............................................................. 20-24 Search customization Scenarios ..................................................................................... 20-24

xiv

Windchill Customizers Guide

Objective .......................................................................................................................... 20-24 Solution ............................................................................................................................ 20-26 Sample Code ................................................................................................................... 20-28 Loading an OOTB Saved Query.............................................................................................20-30 Example: SavedQuery.xml .............................................................................................. 20-30 Sample Code: Handler written for the tag SavedQueries ................................................ 20-39 Search Elements and Associated JSPs .................................................................................20-42 Search element and their associated JSP for Simple Search Page ................................ 20-42 Search element and their associated JSP for Advanced Search Page ........................... 20-43

III. Business Logic Customization Section


Customizing Business Logic .......................................................................... 21-1
Identified Business Classes......................................................................................................21-2 Identity Attributes ............................................................................................................... 21-2 How Identity Is Assigned and Managed ............................................................................ 21-2 When to Use the IdentityService ....................................................................................... 21-5 How to Use the IdentityService.......................................................................................... 21-6 How to Implement System-Managed Identity .................................................................. 21-15 Customizing Iteration and Version Identifiers .........................................................................21-17 Customizing a Bill of Materials ...............................................................................................21-19 Overview .......................................................................................................................... 21-19 Customization .................................................................................................................. 21-19 Current Implementation of Visitors .................................................................................. 21-22 Customizing User Preferences...............................................................................................21-24 Preference Definition ....................................................................................................... 21-24 Visibility ............................................................................................................................ 21-24 Value Handler (type) ........................................................................................................ 21-25 Preference Instance......................................................................................................... 21-25 Preference Category........................................................................................................ 21-25 Preference Client ............................................................................................................. 21-25 The Preference Hierarchy................................................................................................ 21-25 Calling preference values ................................................................................................ 21-27 Adding Preferences ......................................................................................................... 21-27 Writing a Servlet Helper to Use URLFactory Functionality.....................................................21-30 Example URLFactory Usage/Instantiation ....................................................................... 21-31 Updating a Master Through an Iteration.................................................................................21-32 Introduction ...................................................................................................................... 21-32 Read-only and Queryable Master Attributes on the Iteration........................................... 21-33 Updating Master Attributes via the Iteration..................................................................... 21-33

Contents

xv

Updating the Master and Iteration Separately................................................................. 21-34

Customizing Change Management ................................................................. 22-1


Change Management Delegates ............................................................................................. 22-2 ChooseLifeCycleDelegate................................................................................................. 22-2 ChooseFolderDelegate ..................................................................................................... 22-2 ConcreteAssociationDelegate ........................................................................................... 22-3 DisplayIdentificationDelegate ............................................................................................ 22-4

Customizing Life Cycle Administration .......................................................... 23-1


Customizing the Display of Life Cycle Information................................................................... 23-2 Defining Customized Life Cycle Transitions ............................................................................ 23-3 Setting Up a Customized State-Based Versioning Scheme .................................................... 23-3 Adding The Series To StateBasedVersioning.xml And Loading The File ......................... 23-4 Making The Newly Added Version Schemes Available In The Lifecycle Administrator .... 23-5 Creating A Lifecycle Template Which Uses The New Version Series.............................. 23-6 Setting Up The Object Initialisation Rules ......................................................................... 23-7 How The Revision Scheme Can Be Used......................................................................... 23-9

Customizing Workflow Administration........................................................... 24-1


Customizing Workflow HTML Templates ................................................................................. 24-2 Customizing Change Management Workflow Process Templates .......................................... 24-6 Sync on Change Request Submit ..................................................................................... 24-8 Sync on Multiple Object State Change............................................................................ 24-10 Installation and Upgrade ................................................................................................. 24-11 Code Impacted ................................................................................................................ 24-12 Customizing Promotion Request Workflow Processes .......................................................... 24-13 Promotion Request Approval Process ............................................................................ 24-13 Promotion Request Review Process............................................................................... 24-14 Key Customization Points ............................................................................................... 24-14 Customizing Workflow Events on an Object .......................................................................... 24-17 Creating a customized event on an object ...................................................................... 24-17 Emitting a customized event ........................................................................................... 24-18 Customizing Workflow Task Pages ....................................................................................... 24-19 Rendering custom workflow activity variables................................................................. 24-19 Rendering PBO UI Components ..................................................................................... 24-20 Auto Create Change Notice customization ..................................................................... 24-24 Implementing customized Task Page JSP...................................................................... 24-25 Use of Customized Tag Library and/or 3rd Party Tag Library......................................... 24-25

Customizing Workgroup Managers ................................................................ 25-1


Customizing and Administering Pro/ENGINEER Wildfire ........................................................ 25-2

xvi

Windchill Customizers Guide

Customizing Windchill Visualization Services .............................................. 26-1


Custom Publishing....................................................................................................................26-2 Objective ............................................................................................................................ 26-2 Solution .............................................................................................................................. 26-2 Limitations........................................................................................................................ 26-17 Additional Resources ....................................................................................................... 26-17

Report Generation ............................................................................................ 27-1


Overview...................................................................................................................................27-2 Basic Report Example ..............................................................................................................27-2 Query ................................................................................................................................. 27-2 Report Parameters ............................................................................................................ 27-7 Import and Export of Report Templates .................................................................................27-11 Customization Details.............................................................................................................27-15 Customizing the Query .................................................................................................... 27-15 Customizing the Report Format ....................................................................................... 27-16 Customizing the Report Generation Client ...................................................................... 27-30 Customizing the Report Generation URL ........................................................................ 27-33 Customizing Macros ........................................................................................................ 27-35 Customizing Query Builder Types ................................................................................... 27-37 Cognos Presentation Customization ......................................................................................27-38 Objective .......................................................................................................................... 27-38 Solution ............................................................................................................................ 27-39 Limitations........................................................................................................................ 27-42 Sample Code ................................................................................................................... 27-43 Reporting Info*Engine Task Data Source Customization.......................................................27-44 Intended Outcome ........................................................................................................... 27-44 Report Loading .......................................................................................................................27-50 ReportTemplate Data Source Customization .........................................................................27-59 Reporting Input Page Customization......................................................................................27-63 Objective .......................................................................................................................... 27-63 Solution ............................................................................................................................ 27-63 Customization Points ....................................................................................................... 27-65 Limitations........................................................................................................................ 27-66 Sample Code ................................................................................................................... 27-67 Report Localization Customization .........................................................................................27-68 Objective .......................................................................................................................... 27-68 Solution ............................................................................................................................ 27-69 Customization Points ....................................................................................................... 27-71 Limitations........................................................................................................................ 27-72

Contents

xvii

Sample Code................................................................................................................... 27-72 Report Selection List Customization ...................................................................................... 27-74 Solution ........................................................................................................................... 27-74

Customizing Event Audits ............................................................................... 28-1


Introduction .............................................................................................................................. 28-2 Overview of the Audit Event Framework.................................................................................. 28-3 ProjectAuditEvent Class.................................................................................................... 28-4 Audit Recorders................................................................................................................. 28-7 Windchill Auditing Framework Configuration..................................................................... 28-7 Capturing New Events ........................................................................................................... 28-10 Capturing default information about a new event............................................................ 28-10 Capturing new event-specific auditing information.......................................................... 28-11

Customizing Communication Tools................................................................ 29-1


Customizing Meetings.............................................................................................................. 29-2 Sample code for WebexUserInfoDelegate ........................................................................ 29-2 Customizing Action Items (Windchill ProjectLink Only) ........................................................... 29-3 Exposing or Hiding Customizable Attributes ..................................................................... 29-4 Reordering Customizable Attributes.................................................................................. 29-5 Designating Customizable Attributes as Required ............................................................ 29-5 Changing the Display Names of Customizable Attributes................................................. 29-5

IV. Services and Infrastructure Section


Windchill Services ............................................................................................ 30-1
Windchill Packages.................................................................................................................. 30-2 Engineering Factor Services.................................................................................................... 30-5 Handling CAD Models ....................................................................................................... 30-5 Handling Family Instances ................................................................................................ 30-7 Handling Model Structure.................................................................................................. 30-9 The Relationship Between CAD Models and WTParts ................................................... 30-11

System Generation ........................................................................................... 31-1


Overview of System Generation ............................................................................................. 31-2 How Rose UML Maps to Java Classes................................................................................... 31-3 Mapping Modeled Classes to Java ................................................................................... 31-4 Mapping Operations to Java ........................................................................................... 31-10 Mapping Attributes to Java.............................................................................................. 31-12 Mapping Associations to Java......................................................................................... 31-17 Implicit Persistable Associations Stored with Foreign ID References.................................... 31-21 Implementing Interfaces .................................................................................................. 31-28

xviii

Windchill Customizers Guide

Implementing the NetFactor Interface ............................................................................. 31-29 Implementing the ObjectMappable interface ................................................................... 31-31 Implementing the Persistable interface............................................................................ 31-33 Implementing the Externalizable interface ....................................................................... 31-33 Extending the EnumeratedType class....................................................................................31-36 Stereotyping an interface as remote ................................................................................ 31-37 How Rose UML Maps to Info Objects ....................................................................................31-39 How Rose UML Maps to Database Schema ..........................................................................31-41 How Rose UML Maps to Localizable Resource Info Files......................................................31-47 Metadata Resource Info Header...................................................................................... 31-47 Resource Entry Format.................................................................................................... 31-48 Metadata Resource Entry Examples ............................................................................... 31-48 Building Runtime Resources ........................................................................................... 31-48 Using the Windchill System Generation Tool .........................................................................31-50 Registry Files ................................................................................................................... 31-50 Generating mData Files ................................................................................................... 31-51 Generating Java Code ..................................................................................................... 31-51 Generating Info Files ....................................................................................................... 31-52 Generating SQL Files ...................................................................................................... 31-52 Using Windchill System Generation in a Build Environment ..................................................31-54 Management of the mData File ....................................................................................... 31-54 Build Sequence................................................................................................................ 31-55 Command Line Utilities .................................................................................................... 31-55 Deploying Modeled Customizations .......................................................................................31-60 Objective .......................................................................................................................... 31-60 Solution ............................................................................................................................ 31-60

Customizing Modeled Elements ..................................................................... 32-1


Customizing Column Lengths...................................................................................................32-2

Enumerated Types ........................................................................................... 33-1


The EnumeratedType Class.....................................................................................................33-2 Creating an EnumeratedType Subclass...................................................................................33-3 Editing the Resource Info for an Enumerated Type .................................................................33-7 Enumerated Type Resource Info Header .......................................................................... 33-7 Resource Entry Format...................................................................................................... 33-7 Resource Entry Contents................................................................................................... 33-7 Building Runtime Resources ............................................................................................. 33-8 Localizing an Enumerated Type ...............................................................................................33-9 Extending an Enumerated Type .............................................................................................33-10 The Enumerated Type Customization Utility ..........................................................................33-11

Contents

xix

Starting the Utility ............................................................................................................ 33-12 GUI Usage of an Enumerated Type....................................................................................... 33-12

Windchill Design Patterns................................................................................ 34-1


The Object Reference Design Pattern ..................................................................................... 34-2 The Business Service Design Pattern ..................................................................................... 34-3 The Master-iteration Design Pattern ........................................................................................ 34-7

Developing Server Logic.................................................................................. 35-1


Overview .................................................................................................................................. 35-2 Service Management ............................................................................................................... 35-2 Automatic Service Startup................................................................................................. 35-2 Service Startup and Shutdown.......................................................................................... 35-3 Service Management ........................................................................................................ 35-4 Service Event Management..................................................................................................... 35-4 Service Event Registration ................................................................................................ 35-4 Service Event Subscription ............................................................................................... 35-5 Service Event Notification ................................................................................................. 35-6 Service Event Exception Handling .................................................................................... 35-7 Service Event Conventions ............................................................................................... 35-7 Implementing Business Data Types ........................................................................................ 35-8 Initializing Business Attributes........................................................................................... 35-8 Business Attribute Accessors............................................................................................ 35-8 Overriding Accessor Methods ........................................................................................... 35-9 Validating Business Attributes......................................................................................... 35-10 Implementing the checkAttribute Method ........................................................................ 35-12 Business Attribute Aggregation ....................................................................................... 35-12 Business Attribute Persistence........................................................................................ 35-13 Business Attribute Derivation .......................................................................................... 35-13 Implementing Business Services .................................................................................... 35-14 Initializing Business Services .......................................................................................... 35-14 Business Service Operations .......................................................................................... 35-15 Vetoing Business Service Events.................................................................................... 35-16 Business Service Rules................................................................................................... 35-16 Business Service Communication................................................................................... 35-17 Lightweight Services .............................................................................................................. 35-18 The Modeling Implementation ......................................................................................... 35-18 The Inner Class Implementation ..................................................................................... 35-19 Customizing service.properties.............................................................................................. 35-24 Windchill Multi-object Operations........................................................................................... 35-26

xx

Windchill Customizers Guide

The Enterprise Layer........................................................................................ 36-1


Enterprise Abstractions ............................................................................................................36-2 Simple Business Class ...................................................................................................... 36-2 Folder Resident Business Class ........................................................................................ 36-4 Managed Business Class .................................................................................................. 36-5 Revision Controlled Business Class .................................................................................. 36-6 Iterated Folder Resident Business Class........................................................................... 36-8 Cabinet Managed Business Cclass ................................................................................... 36-9 Document Abstractions ..........................................................................................................36-10 Attributes Specific to Windchill Foundation & PDM ......................................................... 36-12 Part Abstractions ....................................................................................................................36-13 Design Overview.............................................................................................................. 36-13 Change Abstractions ..............................................................................................................36-21 Change Item Classes ...................................................................................................... 36-23 Associations with Product Information ............................................................................. 36-26 Change Item Modeling Approach .................................................................................... 36-29 Change Items Classes..................................................................................................... 36-30

Persistence Management ................................................................................ 37-1


Overview...................................................................................................................................37-2 Persistence Manager................................................................................................................37-2 Query........................................................................................................................................37-4 QuerySpec......................................................................................................................... 37-4 SearchCondition ................................................................................................................ 37-5 QueryResult....................................................................................................................... 37-5 Multiple Class Queries ....................................................................................................... 37-6 Transaction...............................................................................................................................37-8 Paging ......................................................................................................................................37-9 Referential Integrity ................................................................................................................37-12 Multi-object CRUD Persistence Manager APIs ......................................................................37-12 Batch (update where/delete from) Statement Capabilities .....................................................37-13 When to use..................................................................................................................... 37-13 Transaction Context and Listeners.........................................................................................37-14 Referential Integrity Association Validation During Object Delete..........................................37-15 Persistence Datastore Sequence Customization ...................................................................37-16 Objective .......................................................................................................................... 37-16 Solution ............................................................................................................................ 37-16 Customization Points ....................................................................................................... 37-18 Limitations........................................................................................................................ 37-18 Sample Code ................................................................................................................... 37-18

Contents

xxi

Advanced Query Capabilities .......................................................................... 38-1


QuerySpec ............................................................................................................................... 38-2 Descendant Query Attribute .............................................................................................. 38-2 Single Column Expression in SELECT Clause ................................................................. 38-2 Table Expression in FROM Clause ................................................................................... 38-4 Expression in WHERE Clause .......................................................................................... 38-4 Bind Parameters................................................................................................................ 38-8 Query Limit ........................................................................................................................ 38-8 SearchCondition ...................................................................................................................... 38-9 Compound Query ............................................................................................................ 38-10 Access Control Consideration ......................................................................................... 38-12 Sorting ............................................................................................................................. 38-13 Join Support .................................................................................................................... 38-14

Internationalization and Localization.............................................................. 39-1


Background.............................................................................................................................. 39-2 The Windchill Approach ........................................................................................................... 39-3 Localizing Text Visible to the User........................................................................................... 39-5 Resource Info (.rbInfo) Files .................................................................................................... 39-8 wt.L10N.complete.............................................................................................................. 39-8 Resource Info Categories.................................................................................................. 39-8 General Resource Info File Usage Rules.......................................................................... 39-9 Resource Info File Descriptions by Category .................................................................. 39-10 Building Runtime Resource Bundles for Resource Info Files.......................................... 39-11

Customizing Archive, Purge, and Restore ..................................................... 40-1


Archiving Related Classes ....................................................................................................... 40-2 Enabling Archive/Purge/Restore for Custom Classes ............................................................. 40-4 Introduction........................................................................................................................ 40-4 Writing Handlers................................................................................................................ 40-4 Make entries in coreobjects.dtd , coreX05.xml.................................................................. 40-5 Make entries in RelationshipMap.xml................................................................................ 40-6 Limitations ......................................................................................................................... 40-7 Customizing Archive Upgrade ................................................................................................. 40-8 How customized archive upgrade works?......................................................................... 40-8 Writing upgrades ............................................................................................................... 40-9

Import Export Framework ................................................................................ 41-1


Overview .................................................................................................................................. 41-2 How to Write an IX Application ................................................................................................ 41-3 Exporter Class................................................................................................................... 41-4

xxii

Windchill Customizers Guide

Using the Exporter to Export Objects ................................................................................ 41-8 How Import Works ............................................................................................................. 41-9 Importer class .................................................................................................................. 41-12 Use Importer to import object from XML files .................................................................. 41-14 How to Write Exp/Imp Handlers .............................................................................................41-17 Writing Export Handlers for the Export Process .............................................................. 41-17 How to Write Handlers for the Import Process ................................................................ 41-20 Navigating Through an Objects Structure with ObjectSet Application...................................41-26 Object Collection.............................................................................................................. 41-26 Navigating Rules.............................................................................................................. 41-26 List of Existing Generators and Filters ............................................................................. 41-31 Examples ......................................................................................................................... 41-32 Simple Export Handler Code: .......................................................................................... 41-38 Simple Import Handler Code: .......................................................................................... 41-43 Product Design eXchange (PDX) Support for Export.............................................................41-46 Customization Points ....................................................................................................... 41-47 Supported APIs................................................................................................................ 41-47 Sample Program .............................................................................................................. 41-51

Evolvable Classes ............................................................................................ 42-1


Background Information ...........................................................................................................42-3 General Externalization Guidelines ..........................................................................................42-4 Hand-coded Externalization Guidelines ...................................................................................42-4 Migration Guidelines for Classes with Hand-coded Externalization .........................................42-5 Examples of Generated Externalization Code for Evolvable Classes ......................................42-6 Example of Version/UID Mapping Table............................................................................ 42-6 Example of Generated Constants...................................................................................... 42-6 Example of a writeExternal Method ................................................................................... 42-6 Example of a readVersion Method .................................................................................... 42-7 Example of a readVersion<EXTERNALIZATION_VERSION_UID> Method..................... 42-7 Example of a readOldVersion Method ............................................................................... 42-9

Creating Large Objects (LOBs) ....................................................................... 43-1


Creating Large Objects (LOBs) ................................................................................................43-2 Modeling Large Objects..................................................................................................... 43-2 DDL Generation ................................................................................................................. 43-2 Reading and Writing LOBs ................................................................................................ 43-2 Small BLOBs ..................................................................................................................... 43-3 Inline BLOBs...................................................................................................................... 43-3 Example............................................................................................................................. 43-4

Contents

xxiii

Customizing Data Formats .............................................................................. 44-1


Adding and Updating Data Formats for Content Holders ........................................................ 44-2 Adding Data Formats ........................................................................................................ 44-2 Updating Data Formats ..................................................................................................... 44-3 Listing Available Data Formats.......................................................................................... 44-3 Renaming a Data Format .................................................................................................. 44-3 Deleting a Data Format ..................................................................................................... 44-4

V. Customization Appendices Section


Extendable Classes in the Windchill Supported API...................................... A-1
PDM Business Information Classes...........................................................................................A-2 Enterprise Business Information Classes ..................................................................................A-2 Windchill Services......................................................................................................................A-2 Foundation Classes ...................................................................................................................A-3 PDM Auxiliary Business Information Classes ............................................................................A-3 Business Logic Classes .............................................................................................................A-3 Server Development Classes ....................................................................................................A-4 Client Development Classes......................................................................................................A-5

Multi-Object Conversion Guidelines ................................................................ B-1


Conversion Overview.................................................................................................................B-2 Objectives............................................................................................................................ B-2 Considerations .................................................................................................................... B-2 API Guidelines ...........................................................................................................................B-3 Multi-Object vs. Multi-Multi-Object APIs .............................................................................. B-3 Converting Boolean Operations .......................................................................................... B-4 Retaining Single-Object Operations .................................................................................... B-4 WTCollection vs. WTSet/WTList and WTHashSet/WTArrayList ......................................... B-4 Empty collections ................................................................................................................ B-5 Memory considerations ....................................................................................................... B-6 Collections Guidelines ...............................................................................................................B-7 Inflating................................................................................................................................ B-7 Using connect() ................................................................................................................... B-7 WTKeyedMap vs.WTValuedMap ........................................................................................ B-7 OBJECT_IDENTIFIER vs.VERSION_FOREIGN_KEY collections ..................................... B-7 Modifying collections ........................................................................................................... B-8 Event Dispatch Guidelines.........................................................................................................B-9 Cleanup ............................................................................................................................... B-9 Use of collections ................................................................................................................ B-9

xxiv

Windchill Customizers Guide

Single-and multi-object listeners? ....................................................................................... B-9 KeyedEvent's getEventTarget()API .................................................................................. B-10 Multi-Object Delegation Guidelines ......................................................................................... B-10 Converting to wt.services.ac.DefaultServices................................................................... B-10 Multi-Object Exceptions Guidelines......................................................................................... B-11 Basic expectations............................................................................................................ B-11 Pre-flight checks ............................................................................................................... B-11 Multi-object Exceptions and Single-Object APIs............................................................... B-12 Multi-Object CRUD API Guidelines ......................................................................................... B-13 Internal Dependency Issues ............................................................................................. B-13 Batch Update/Delete Guidelines ............................................................................................. B-13 When to Use? ................................................................................................................... B-13 Transaction Context/Listener Guidelines................................................................................. B-14 Transaction Context vs.Method Context........................................................................... B-14 Single-object contexts....................................................................................................... B-14 Deferred validation/work with transaction listeners........................................................... B-14 Neat Tips and Tricks................................................................................................................ B-15 Inflating references ........................................................................................................... B-15 Persisting interdependent data ......................................................................................... B-15

Creating Non-Modeled Services for Listening.................................................C-1


Overview.................................................................................................................................... C-2 Create a Service Interface......................................................................................................... C-2 Create a Standard Service Class .............................................................................................. C-3 Compile ..................................................................................................................................... C-5 Register the New Service .......................................................................................................... C-6 Restart the Method Server ........................................................................................................ C-6

Windchill Profiler ................................................................................................D-1


Overview.................................................................................................................................... D-2 Profiler Features ........................................................................................................................ D-2 Profiler Operation ...................................................................................................................... D-2

Additional Topics - Client Customization ........................................................ E-1


Launching a DCA Wizard From a JSP Page............................................................................. E-2 Embedding a DCA Page in a JSP to Use as a Main Page........................................................ E-3 Defining Non-JSP Actions to be Executed From a JSP Page................................................... E-3 Default Assignment of URL ................................................................................................ E-4 Assignment of URL When renderType="GENERAL" or "GENERAL_WITH_CONTEXT" .. E-5 Assignment of URL When renderType="PDM" .................................................................. E-5 actions.xml Elements .......................................................................................................... E-6

Contents

xxv

URLFactory in the JSP Environment .........................................................................................E-7 Creating an URLFactory...................................................................................................... E-7 Setting the JSP Reference Point......................................................................................... E-8 Generating Links on the Page............................................................................................. E-9 Internationalizing JSP Pages in Windchill ......................................................................... E-11 Using File-Handling Applets in Non-JSP Clients .....................................................................E-15 The Three Applets............................................................................................................. E-15 Advantages and Disadvantages........................................................................................ E-15 The File Selection Applet .................................................................................................. E-16 The Upload Applet............................................................................................................. E-23 The Download Applet ........................................................................................................ E-42

Index

xxvi

Windchill Customizers Guide

Change Record

This section details the major changes in this guide. Table 1 Changes for 9.1
Chapter Description

Chapter 8, User Interface Technology Overview Chapter 9, Generic UI Customizations

Added the Adding Custom Code to all Windchill Client Architecture Pages section to this chapter Added the Offline Package Customization section to this chapter Added the System Banner Alert Message section to this chapter Removed the "Customizing Online Help" section from this chapter.

xxvii

Chapter

Description

Chapter 10, Customizing HTML Clients Using the Windchill JSP Framework

Updated the Action Report section. Removed the "Customizing Online Help for a JSP Component" section. Added the Component Access Control section to this chapter. Added the Customizing Access Control For Packages section to this chapter. Updated the Action Report section. Updated the Action Model Report section. Added the Debugging section to this chapter. (MR010) Updated the Windchill Client Architecture Action Framework Overview section. Added the Navigation Stickiness section to this chapter.

Chapter 11, Adding Actions and Hooking Them Up in the UI

xxviii

Windchill Customizers Guide

Chapter

Description

Chapter 13, Presenting Information in the UI

Updated the Constructing and Rendering a Table Using the JSP Framework section Updated the Windchill Client Architecture Tree section Added the Adding Custom Modeled Attributes to all Table Views section Added the Generating the Name Attribute Server section Added the Partial Activation of JSCA section Added the Icon Delegates section Added the UI Validation section Added the Customizing the Find Number Field section Updated the Windchill Client Architecture Wizard section with information on clerks Updated the Windchill Client Architecture Wizard section to remove the Adding the Help Icon section Updated the Wizard Processing section Updated the Building Wizards to Create a Single Object section

Chapter 14, Constructing Wizards

Change Record

xxix

Chapter

Description

Chapter 18, Customizing the Product Structure Explorer (PSE)

Added Customizing Attribute Displays within Section Headings to this chapter Added Customizing Tabs Configure Existing Tabs with Subtabs to this chapter Added Allow Additional Steps During New Object Creation to this chapter Added Type Picker Display Customization to this chapter Added Disabling Actions by Object Type to this chapter Added Creating a Requirements Tab to this chapter Added Configurable Link Tables to this chapter

Chapter 19, Customizing Windchill MPMLink Chapter 21, Customizing Business Logic Chapter 26, Customizing Windchill Visualization Services Chapter 27, Report Generation

New chapter. Updated for MR020. Updated the Customizing a Bill of Materials section New chapter. Added Report Selection List Customization to this chapter.

xxx

Windchill Customizers Guide

About This Guide

The Windchill Customizer's 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 provides customization information for the following Windchill solutions: Windchill PDM Link Windchill ProjectLink Pro/INTRALINK 9.1 Arbortext Content Manager

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. Some code examples in this guide have been reformatted for presentation purposes and, therefore, may contain 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
The following documentation may be helpful: What's New for Windchill Release 9.1 Windchill Installation and Configuration Guide Windchill Upgrade Guide Windchill Data Loading Reference and Best Practices Guide Windchill System Administrator's Guide Windchill Business Administrators Guide Windchill Performance Tuning Guide

xxxi

Windchill User's Guide Workgroup Manager Customization Guide

If books are not installed on your system, see your system administrator.

Technical Support
Contact PTC Technical Support via the PTC Web site, phone, fax, or e-mail if you encounter problems using <product name> or the product documentation. For complete details, refer to Contacting Technical Support in the PTC Customer Service Guide. This guide can be found under the Self Help section of the PTC Web site at: http://www.ptc.com/support/support.htm The PTC Web site also provides a search facility for technical documentation of particular interest. To access this page, use the following URL: http://www.ptc.com/support/support.htm You must have a Service Contract Number (SCN) before you can receive technical support. If you do not have an SCN, contact PTC Maintenance Department using the instructions found in your PTC Customer Service Guide under Contacting Your Maintenance Support Representative.

Documentation for PTC Products


You can access PTC documentation using the following resources: Windchill Help Page--The Windchill Help Center is an online knowledgebase that includes a universal index of all Windchill documentation; you can access it by clicking a help icon or the Help link in any Windchill page header. You can browse the entire Windchill documentation set, or use the advanced search capability to customize your keyword search. Reference Documents Web Site--All books are available from the Reference Documents link of the PTC Web site at the following URL: http://www.ptc.com/appserver/cs/doc/refdoc.jsp A Service Contract Number (SCN) is required to access the PTC documentation from the Reference Documents Web site. For more information on SCNs, see Technical Support: http://www.ptc.com/support/support.htm

xxxii

Windchill Customizers Guide

Comments
PTC welcomes your suggestions and comments on its documentation. Send comments to the following address: documentation@ptc.com Please include the name of the application and its release number with your comments. For online books, provide the book title.

About This Guide

xxxiii

xxxiv

Windchill Customizers Guide

I
Customization Overview Section

Chapter

Page

Customization Overview........................................................................ 1-1 The Windchill Development Environment ............................................ 2-1 Getting Started With Windchill Customization ..................................... 3-1 Modeling Business Objects.................................................................... 4-1 Managing Customizations...................................................................... 5-1 Windchill Utilities.................................................................................. 6-1 Customization Tutorial .......................................................................... 7-1

1
Customization Overview
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. Topic Page

Configuration Options.........................................................................................1-2 Customizations ....................................................................................................1-5 Windchill Customization Points..........................................................................1-8

1-1

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 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 the Property Files section of the The Windchill Development Environment chapter on page 2-10 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 Windchill Administrators Guide and the properties.html file in the codebase directory.

Preferences
Preferences are set through the Windchill user interface and do not require a server restart. They control application behavior1. 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 organizations or an application containers (e.g. Product, Library), or a specific users setup. See the Preferences section of the Generic UI Customizations chapter on page 9-18 for some additional information on preferences. The table below provides just a few of the available preferences:
Preference Description

Change Notice without Change Request Enable Structure Propagation

Allows creating a change notice without a change request. Enables propagation of effectivity statements down a product structure.

1.

For legacy reasons, some Properties also control application behavior.

1-2

Windchill Customizers 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. Controls whether the thumbnail action available in tables.

Display Thumbnails

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 companys 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 customers environment and business process needs. For additional information, see the Object Initialization Rules chapter in the Windchill Business Administrators Guide.

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 Customizing Workflow Administration chapter on page 24-1.

Customization Overview

1-3

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-thebox 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.

1-4

Windchill Customizers 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 in conjunction with Rational Rose to customize your Windchill environment. Information Modeler contains the Windchill modeling files and source code that you will use to develop your customizations. Rational Rose is a design and analysis tool to model business objects. Rational Rose allows you to create a graphical representation of an application, its components, their interfaces, and their relationships. 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 then using soft types. For example, soft types 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 soft types can only be created as super types of existing modeled classes with additional attributes. For more information on Rational Rose see Rational Rose and Windchill on page 4-2.

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 parts details, get the cost of the part from the ERP system and display it in the same UI)

Customization Overview

1-5

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 9-1.

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 basic Info*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 how Info*Engine either displays or retrieves information. Webjects are the means by which Info*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 more information on Info*Engine see Managing Windchill Info*Engine Tasks on page 5-13.

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 Windchillintegrated 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 8 Business Intelligence (BI) within Windchill 9.1 to provide out-of-thebox integration between Windchill and Cognos 8 BI. It also includes pre-built reports on change management, project items status, and parts/products. 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

1-6

Windchill Customizers Guide

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 27-1.

Customization Overview

1-7

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/doc/pds_calendar.pdf 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. 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

1-8

Windchill Customizers Guide

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

1-9

1-10

Windchill Customizers Guide

2
The Windchill Development Environment

This chapter describes the Windchill development environment. Topic Page

Directory Structure ..............................................................................................2-2 Artifact Management...........................................................................................2-8 Environment Variables........................................................................................2-9 Property Files ....................................................................................................2-10 Properties and Property Files ............................................................................2-15

2-1

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 for Apache Tomcat and Windchill


bin

Contains various batch scripts, such as ToolsSetup.bat.


cgi-bin

Contains the Windchill common gateway interface wrappers.

2-2

Windchill Customizers Guide

codebase

Contains the runtime environment files.


conf

Configuration files for Apache, DCA, InfoEngine 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 clients.
installer

Contains files used by, or created by, the installation process, including installation logs.
installlib

Library of code used by Windchill installers and related utilities.


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 programming examples.


src

Contains files for modeling customizations, and rbInfo files for text
srclib

Contains module jar files.


step

Contains STEP application related files.


taskeditor

Contains the I*E task editor startup scripts, help files reside and is the runtime directory for the task editor.

The Windchill Development Environment

2-3

tasks

Contains Info*Engine tasks.


temp

Temporary files used by Windchill.


Upgrade

Contains files to facilitate the upgrade process.


vaults

Default file vault location.


WHC

Contains the Windchill Help Center which consists of the online help and the pdf manuals.
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.

2-4

Windchill Customizers 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.1

The codebase Directory

Most of these directories contain third party product class files. The html directory contains templates that are used to generate HTML dynamically.

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

The Windchill Development Environment

2-5

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 created by the Windchill code generation tool for every business object modeled in Rose. Files in the form <object> .ClassInfo.ser are also code-generated and contain metadata needed by the runtime environment. They are all described in more detail in the System Generation chapter on page 31-1. 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 The wtx directory contains EPM-related files and directories.

2-6

Windchill Customizers Guide

The src Directory


In general, the src directory contains the source files needed for application development. It holds the files necessary to create new models in Rose and generate code. The src directory can be expanded to show the following directories.

The src Directory

The customization directory contains programming examples of customizations, which are described in more detail in either this guide or the readme file that is in the 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: Rose model components: model files with the suffix .mdl and package files with the suffix .cat. (The .cat file is described later in this chapter.) Code generation files: files with the suffix mData, which are intermediate files created by the code generation tool and used to create Java classes, Info classes, and SQL files (for more information, see the System Generation chapter on page 31-1). Localizable ResourceInfo (.rbInfo) files, which contain customizable display text for EnumeratedTypes and modeled elements.

The Windchill Development Environment

2-7

Artifact Management
In Rational Rose, you can optionally separate a model into controlled units as a way of sharing code. Controlled units are source files with a .cat extension that can be checked in and out of your source code control system. Control units are created at the package level. In Rational Rose, right-click on a package in the Browser window, select Units, select Control...; <package>, select the filename for the controlled unit. The menu item is only selectable for packages that are not controlled. This action produces a file with the extension .cat. You can then check in and check out these .cat files to whatever source code management system you use. The directory structure used in the source code management system must match the package structure used in Rose. You can change a control unit that is read-only to write by selecting the WriteEnable<package> item. This is useful if you want to manipulate the model in some way (for example, temporarily changing its appearance before printing it). Be aware that this action does write enable the file at the file system level, so if you dont want it left writable, select the Write Protect <package> item. These are menu items are both available from the same Units menu item mentioned above.

2-8

Windchill Customizers Guide

Environment Variables
When you install the Windchill Information Modeler, the settings required for business modeling and code generation are set automatically. You should have to do nothing more. But, if you have problems, the following sections give information about required settings.

Class path
We recommend that you not make any modifications to your CLASSPATH after installation. In particular, do not add the codebase directory. Doing so can cause Netscape Navigator to incorrectly assume a security violation. (See the Windchill Installation Guide for further information.)

Path
Your PATH variable should contain <Windchill> \bin and JDK\bin. <Windchill> contains batch scripts, such as ToolsSetup.bat, required to use the Information Modeler. (See the Windchill Installation and Configuration Guide for further information.)

SQL path
You must create (or add to) your SQLPATH variable and set it to the location where the SQL scripts that create the necessary tables will be written. When you are in a SQL*Plus session, SQL*Plus searches these directories for SQL scripts. By default, this value is c:\ptc\windchill\db\sql.

Rational Rose virtual path map


Rose provides a virtual path map mechanism to support parallel development by teams. The virtual path map enables Rose to create model files whose embedded path names are relative to a user-defined symbol. Thus, Rose can work with models moved or copied among workspaces and archives by redefining the actual directory associated with the user-defined symbol. The virtual path map contains a list of entries, each of which represents a mapping between a virtual path symbol and an actual path name. To use this capability with Windchill, include the following virtual path map entries: WT_EXTENSIONS, which specifies the directory that contains the Windchill extensions to Rational Rose. WT_STD_PACKAGES, which specifies the directory where the packages for Java reside. WT_WORK, which specifies the top level directory where .mData files and .cat files are located. Every wt package modeled in Rose has a corresponding .cat file in the c:\ptc\windchill\src\wt directory.

The Windchill Development Environment

2-9

Module specific path maps will also be created automatically, based on information stored in moduleRegistry.properties and moduleDir.properties. For example, wnc/CommonCore is the path map for the CommonCore module of the wnc assembly.

Note: See the Windchill Installation and Configuration Guide for further information.

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. debug.properties Contains properties used by Windchill code to control debug info capturing. (See the wt.util package entry in your installed Windchill Javadoc for more information) user.properties Contains user overrides used by Rational Rose and the Windchill code 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 Windchills database connection layer to access the database. The System Generation jars (SystemGeneration.jar, WindchillUtil.jar & CommonCore.jar) contain: tools.properties

2-10

Windchill Customizers Guide

Contains properties used by Rational Rose and the Windchill code 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 soft type. wt.properties 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 Windchill Administrators Guide and the properties.html file in the codebase directory. To change properties, you can edit the file directly or use the System Configurator GUI from the Windchill application home page. The System Configurator allows you to modify property files; start, stop, and restart the server manager and all method servers; and launch other Windchill applications.

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

The Windchill Development Environment

2-11

browser. It is used to build URLs for static resources such as images or HTML files that reside under the servers 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 fullyqualified 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 fullyqualified 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 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

2-12

Windchill Customizers Guide

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
The tools.properties file contains properties that are used by the System Generation tools. The following properties within tools.properties are of interest: wt.generation.bin.dir, which specifies where .ClassInfo.ser files (serialized info objects) will be generated, following the package structure. wt.generation.source.dir, which specifies where .mData files are expected to be found and where .java files will be generated, following the package structure.

Note: Because the source.dir entry informs the code generator of the location of mData files and, in Rose, the WT_WORK variable informs the model information export tools of the location of mData files, they must point to the same location. wt.generation.sql.dir, which specifies where SQL scripts will be generated. wt.generation.sql.xxxTablesSize, which sets default sizes for tables. wt.classRegistry.search.path, which specifies the path to search for files representing classes to be registered. wt.classRegistry.search.pattern, which specifies the file pattern to consider as representing classes to be registered.

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. See the Windchill System Administrators Guide for information on the xconfmanager utility.

The Windchill Development Environment

2-13

db.properties file
The db.properties file contains properties that are used by Windchills 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.

2-14

Windchill Customizers Guide

Properties and Property Files


As you have read in the previous sections, template processing relies heavily on the use of properties contained in properties files to locate the template, processor and other resources for an HTML client. In general, properties for Windchill Foundation PDM 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 either the system configurator client in your Windchill product or the xconfmanager command live utility. These are respectively described in the Administering Runtime Services section of the Windchill System Administrators Guide and in the About the xconfmanager Utility section of the Windchill Utilities chapter on page 6-2. See the section Properties and Property Files on page 2-15 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 Windchill Development Environment

2-15

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
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 of 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, FormTaskDelegate, NavBarActionDelegate, and NavBarURLActionDelegate. 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. To be loaded correctly at runtime, files containing application context service properties must be listed for one of the following properties in wt.properties:

2-16

Windchill Customizers Guide

wt.services.applicationcontext.WTServiceProviderFromProperties. defaultPropertyFiles

wt.services.applicationcontext.WTServiceProviderFromPrope rties.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 the Managing Customizations chapter on page 5-1 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 the Managing Customizations chapter on page 5-1.

Application Context Service Properties for Soft Types


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 soft types. Properties for client features that allow you to specify different services or resources for different soft types must be put in a property file listed for one of the following properties in <Windchill>/codebase/wt.properties: wt.services.applicationcontext.TypeBasedServiceProviderFromProperties.defaul tPropertyFiles wt.services.applicationtext.TypeBasedServiceProviderFromProperties.CustomPr opertyFiles.

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

The Windchill Development Environment

2-17

TypeBasedServiceProviderFromProperties.CustomPropertyFiles using the xconfmanager utility. This procedure is described in the Managing Customizations chapter on page 5-1.

2-18

Windchill Customizers Guide

3
Getting Started With Windchill Customization

The remainder of this manual describes how to create applications using the Windchill product and how to customize existing Windchill applications. You are assumed to be familiar with the third party components used with Windchill: Java, Rational Rose, Oracle, and the IDE (integrated development environment) of your choice. Examples or screen shots use Visual Cafe as an example of a supported IDE, but Windchill supports any Java IDE customers choose to use. This manual does not address how to use these products in general, but how to use them as they relate to Windchill. This chapter gives you a brief overview of the Windchill development process and shows how to create a simple application using Windchill. By following this example, you will perform the major steps in developing an application and verify that the development environment (as described in the The Windchill Development Environment chapter on page 2-1) is set up correctly.

Topic

Page

An Overview of the Windchill Development Process ........................................3-2

3-1

An Overview of the Windchill Development Process


The process of developing Windchill applications is iterative and model-driven. You start with Rational Rose, an object-oriented analysis and design tool. Rose gives you the capability to create a graphic representation that is, a model of an application, its components, their interfaces, and their relationships. Windchill provides foundation classes that can be loaded into Rose so you can include in the applications any of the functionality already developed (for example, version control and the ability to lock objects). In Rose, you can create your own classes and extend those provided by Windchill. When you finish the initial modeling phase, you use the Windchill code generation tool to create Java code from the Rose model. This generated code is already optimized to take advantage of Windchills architecture. You can then implement in this code the server business logic and the client task logic. A Java IDE, such as Jbuilder, NetBeans, Eclipse or Visual Cafe, is useful for building the client-side presentation portions of applications that include HTML and Java applets. Examples or screen shots use Visual Cafe as an example of a supported IDE, but Windchill supports any Java IDE customers chooses to use. Following testing, you can return to the model, make modifications, and repeat the process without losing work you have already done. This iterative, modeldriven process allows you to create or customize an application, get portions of it running as quickly as possible, and continually improve it.

Verify The Development Environment


This section identifies the environment you need to run this example. It discusses only a subset of the information in the The Windchill Development Environment chapter on page 2-1. See that chapter for more detailed information on setting up the development environment. We assume that Windchill and all required third party products are installed. If you did not install Windchill yourself, you will need to know where it is installed. These steps assume installation in the c:\ptc\windchill directory. You will also need to know your Oracle user name, password, and host name. 1. Verify the following environment variables: PATH Ensure that the PATH variable includes the Oracle path. An example follows:
% [ ]SystemRoot% [ ]\system32;% [ ]SystemRoot% [ ]; C:\ORANT\BIN;c:\jdk1.1.6\bin

SQLPATH The SQLPATH specifies the directory in which sql scripts are generated. It must match the value specified in the tools properties1 file entry named

3-2

Windchill Customizers Guide

wt.generation.sql.dir. By default, this value is (wt.home)\db\sql. For example,


c:\ptc\windchill\db\sql

2. Verify the contents of the following property files: wt.properties Set the following entry in the windchill\codebase\wt\wt.properties file: java.rmi.server.hostname =<hostname > For example,
java.rmi.server.hostname=Smith.windchill.com

db.properties In the windchill\db\db.properties file, ensure your Oracle user name, password, and service name are entered in this file. wt.pom.dbUser =<username > wt.pom.dbPassword =<password >

3. Start the Windchill servers. Open a new console window. Start the server manager and a method server by entering the following command:
java wt.manager.ServerLauncher

A window will be started for each but they will be minimized. Initialize the administrator tables by entering the following command in a console window:
java wt.load.Demo

This command loads the database with administrative information. Respond "yes" to all prompts. When prompted for a user name/password, enter the same user name and password you use to access your computer. 4. Establish your Rose model directory. In the c:\ptc\windchill\src directory, create the subdirectory helloWorld. This directory will contain files for the helloWorld package.

Model the Object in Rose


1. Start Rational Rose and check the virtual path map. From the File menu, select Edit Path Map and ensure the following values are set:

1.

See the tools.properties file and user.properties file descriptions in the The Windchill Development Environment chapter.

Getting Started With Windchill Customization

3-3

WT_WORK = c:\ptc\windchill\src WT_EXTENSIONS = c:\ptc\windchill\RoseAddIn WT_STD_PACKAGES = $WT_EXTENSIONS\Standard Packages 2. Establish the initial Rose model by performing the following steps: a. From the File menu, select Open, browse to c:\ptc\windchill\src\wt, and load the model WTDesigner.mdl. b. When asked whether to load subunits, press the Yes button. c. Save the model as c:\ptc\windchill\src\helloWorld\HelloWorld.mdl. d. When asked whether to save subunits, press the No button. 3. Model the person class by performing the following steps: a. In the Logical View/Main class diagram, drop in a Package icon and label it helloWorld. b. Use the dependency tool to draw dependencies from helloWorld to the wt and java packages. c. Go to the Main diagram of the helloWorld package. d. Drop on a class icon and give the class the name Item (the parent for Person). Attributes and operations for Item automatically appear. Change the diagram to suppress attributes and operations of Item. Ensure that the Show Visibility option is on for Item (so you can see in the diagram that it comes from the fc package). e. Drop on another class icon and give it the name Person. f. Make Person a subclass of Item. (Use the generalization icon/tool to draw a line from Person to Item.)

g. Insert the attributes name, age, title, and id. Name, title, and id should be strings (String) and age should be an integer (int). Use lowercase or a mix of upper- and lowercase letters for these attributes; do not use all uppercase letters.2 Right click to start the specification dialog. Make all the attributes public and change the Windchill property of each to constrain=false. Click the Apply button for each change and, when you are done, click the OK button.

2. For every attribute modeled, a corresponding constant is generated using all uppercase letters. For example, if you model an attribute of employeeName, a constant of EMPLOYEE_NAME is generated. Modeling an attribute of EMPLOYEE_NAME would cause the generated constant to conflict with the attribute name. Therefore, unless the attribute being modeled is itself a constant, do not name modeled attributes using all uppercase letters.

3-4

Windchill Customizers Guide

h. Select the menu option Browse > Units. Select the HelloWorld package and press the Control button. Save the unit to c:\ptc\windchill\src\ helloWorld\helloWorld.cat. With the helloWorld package selected, press the Save button. i. Save the Rose model file. When asked whether to save subunits, click the No button.

Tip: From this point on, saving the model is a two-step process: 1. Select the menu option Browse > Units to initiate the Units dialog. In the Units dialog box, select the package you defined earlier and select Save. When asked whether to save subunits, click the Yes button. Close the Units dialog box. 2. Select the menu option File > Save. When asked whether to save subunits, click the No button.

Generate Java Classes From Rose


1. Go to the parent package of the Person class (by selecting the Logical View/Main diagram from the class browser, then selecting the helloWorld package). 2. From the Tools menu, select Windchill > System Generation. 3. From the popup window, select Java Source Code, WT Introspector Support, and Database Support, then click the OK button. The code generator creates several files: An mData file (helloWorld.mData) and a Java file (Person.java), which are put in the directory c:\ptc\windchill\src\helloWorld that you created earlier in this example. (The generated mData file and java file go to the named package in the source directory based on the value specified in the tools properties entry named wt.generation.source.dir which, in this case, is c:\ptc\windchill\src.) A ClassInfo file (Person.ClassInfo.ser), which is put in the directory c:\ ptc\windchill\codebase\helloWorld (this directory is created by the code generator). (The location of this file is based on the value specified in the wt.generation.bin.dir entry which, in this case, is c:\ptc\windchill\ codebase.) SQL scripts that create the tables which store the Person class, and a directory named helloWorld in c:\ptc\windchill\db\sql which contains all the scripts.

You can verify this step by finding these files in the directories.

Getting Started With Windchill Customization

3-5

Create Database Tables


In Oracle SQL*Plus, create the tables by running the following command:
@helloWorld\make_helloWorld

This script creates a Person table and a PersonPk package. You may see a message the first time you run this script because the Person table does not yet exist; you can ignore this message. Note: Establish the project using the IDE of your choice.

Initialize the Object


This step overrides a default initialize() method in order to set the persons id attribute. 1. Edit the Person.java file to add the following code for the initialize() method at the end of the file in the user.operations block:
protected void initialize() throws WTException { Date today = new Date(); super.initialize(); System.out.println("Person - initialize executing!"); String s = String.valueOf(today.toLocaleString()); setId(s); }

2. Add the following import statement in the user imports block:


import java.util.Date;

3. From the File menu, select Save All and, from the Project menu, select Rebuild All.

Design the GUI Layout


1. From the Project menu, select the Object tab and double click on CreatePerson class. 2. Using the FormDesigner, add labels for Name:, Title:, Age:, and Id:. Use the Text property of the Label to set the label value. 3. Add TextFields for the three fields you just added, plus a TextField for the message area. The TextFields for Id and MessageArea should be set to enabled=false and edittable=false. Name the fields nameField, titleField, ageField, idField, and messageField. messageField should span the width of the applet. 4. Add a button between the idField and the messageField. The button name should be saveButton, and its label text should be Save. 5. Save all your work.

3-6

Windchill Customizers Guide

Code the GUI


To make the applet function, you must associate an action event with the saveButton. The method that executes will construct a new Person object, set its values based on the input fields, and invoke the PersistenceHelper to save it in the database. After the object is saved, the method will update the id field on the GUI and put a status message in the messageField. 1. Edit the source of CreatePerson.java. 2. From the form designer, click the right mouse button on the Save button and select Bind Event. Select the actionPerformed event and press the Edit button. 3. Change the contents of the method to the following:
void saveButton_ActionPerformed(java.awt.event.ActionEvent event) { Person p; int age; try { age = Integer.parseInt(ageField.getText()); } catch (NumberFormatException nfe) { messageField.setText("Must supply number for age"); return; } try { p = Person.newPerson(); p.setName(nameField.getText()); p.setTitle(titleField.getText()); p.setAge(age); p = (Person) PersistenceHelper.manager.save(p); } catch (Exception wte) { wte.printStackTrace(); messageField.setText("Exception: " + wte.toString() ); return; } idField.setText( p.getId()); messageField.setText("HelloWorld!"); return;

4. Add the following import statements:


import import import import import wt.util.WTException; wt.util.WTContext; wt.fc.PersistenceHelper; java.lang.Integer; java.lang.NumberFormatException;

5. Insert the following statement as the first line of the init() method in the CreatePerson.java file:

Getting Started With Windchill Customization

3-7

WTContext.init(this);

Also delete the automatically generated line:


symantec.itools.lang.Context.setApplet(this);

6. Compile the whole applet by selecting Execute from the Project menu. You can now execute the project in Visual Caf using the Applet Viewer or run it outside of Visual Caf in a browser. 7. If you encounter an error that states the CreatePerson.class file cannot be found, close Visual Caf. Copy the contents of c:\ptc\windchill\codebase\ helloWorld to c:\ptc\windchill\src\helloWorld (these are the class files). Start Visual Caf and execute the applet. (Be sure the method server is running.)

Run the Applet in Mozilla or Internet Explorer


1. Create a JSP file with the following content and save it as <Windchill>/codebase/wtcore/jsp/CreatePerson.jsp:
<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/util" prefix="util"%> <jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request"/> <jsp:setProperty name="wtcontext" property="request" value="<%=request%>"/> <util:locale/> <html> <body> <util:plugin code="helloWorld/CreatePerson.class" codebase="../.." archive="wt/security/security.jar" width="590" height="600"> <util:params> <util:param name="cache_option" value="Plugin"/> <util:param name="cache_archive" value="wtApplet.jar"/> <util:param name="wt.context.locale" value="<%=locale%>"/> </util:params> </util:plugin> </body> </html>

Note: wtApplet.jar is used simply to get this example working. For guidelines on managing client JARs, see Managing Client JAR Files in the Getting Started With Windchill Customization chapter on page 5-14. 2. Ensure your web server, servlet engine, and method server are running. Refer to the instructions given earlier in Verify The Development Environment (see page 3-2) if they are not. 3. Open http://<hostname>/<web-app>/wtcore/jsp/CreatePerson.jsp in Mozilla or Internet Explorer.

3-8

Windchill Customizers Guide

4. Enter the name, title, and age (where age must be a number) and press the Save button. 5. The method server should start up automatically, if it is not already started. You should see in the output your message about the Person initialize() method. 6. In your applet, you should see the generated ID (that is, the system time) and the message HelloWorld in the messageField.

Getting Started With Windchill Customization

3-9

3-10

Windchill Customizers Guide

4
Modeling Business Objects
This chapter explains how to model business objects. Topic Page

Rational Rose and Windchill...............................................................................4-2 Windchill Modeling Heuristics ...........................................................................4-4 Windchill Foundation Abstractions.....................................................................4-8

4-1

Rational Rose and Windchill


The Windchill development environment uses the Rational Rose design and analysis tool to model business objects. Rose allows you to create a graphical representation of an application, its components, their interfaces, and their relationships. Windchill then uses this model to generate code that is used in server and client development. You are assumed to be familiar with Rose or learning to use it. This section does not describe how to use Rose, but how Windchill interacts with it. Rose offers several kinds of diagrams (as shown in the following figure) intended to help you analyze your model.

Rose Analysis Diagrams

On the left side are some of the various analysis diagrams available in Rose. From top to bottom, they are: a use case diagram, a sequence diagram, and a state transition diagram. The right side shows two class diagrams. The class diagram is the only type of diagram used by Windchill for code generation. Although we recommend that you use analysis diagrams, that choice is up to you. Windchill requires only the class diagrams plus some system specifications that you set within Rose to generate code.

4-2

Windchill Customizers Guide

The following figure shows a class diagram for sample business information objects (Customer, Product, and IncidentReport) and the relationships between them. The annotation in bold points out UML (Unified Modeling Language) concepts and notation.

Sample Class Diagram

Address is a structured attribute class associated with the Customer class. The composite aggregation notation indicates that Address is considered a part of the Customer class. The Address object depends on the existence of the Customer object. For example, if the Customer class is deleted, the Address class is also deleted. An association class allows you to add attributes, operations, and other features to associations. Because customers register for products, an attributed association is modeled between Customer and Product. IncidentReportCustomer and IncidentReportProduct are also link classes, but they have no attributes. You need not give them a class box. If any of these concepts or notations are unfamiliar, you should learn more about UML and Rose before proceeding. Many of the Windchill concepts are explained using class diagrams.

Modeling Business Objects

4-3

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.

4-4

Windchill Customizers 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. Business managers are intended to implement small portions of functionality. The knower/doer separation approach allows you to choose which business managers, the doers, to implement for your business information, the knowers. Windchill provides you with a number of managers (described in more detail in the Developing Server Logic chapter on page 35-1) from which you can choose as

Modeling Business Objects

4-5

much functionality as you want, or design your own managers to meet your specific business needs. The following is an example of one of the managers Windchill provides, the LockService. (In naming classes, managers are sometimes also called services.)

LockService Example

In this example, the knower is MyItem, which extends Item (a foundation class provided by Windchill). Thus, MyItem inherits all the attributes and behavior of Item. In addition, MyItem implements the Lockable interface. The notation <<Interface>> is a stereotype. It is a cue to the code generator to add an Interface modifier to your generated class. This indicates that you must provide the code for this method in an implementation class. (In Java, an interface is a collection of operations and final fields without implementation methods which form an abstract type. A Java class conforms to an abstract type when it implements an interface. When a Java class implements a Java interface, the class or one of its subclasses must provide an implementation method for each operation in the interface.) 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.) StandardLockService is the actual implementation of the lock service functionality and it implements the LockService remote interface.

4-6

Windchill Customizers Guide

<<RemoteInterface>> is another stereotype. It is a cue to the code generator to create a forwarder class (described in the System Generation chapter on page 31-1). The remote interface must be available on the client. 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. StandardLockService expects a lockable object. It can accept MyItem because MyItem implemented the Lockable interface. Likewise, it 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.

Modeling Business Objects

4-7

Windchill Foundation Abstractions


At an infrastructure layer of Windchills 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

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 modeled constructors are generated as factories (for example, newMyItem), along with supporting initialization methods if none matching the same signature are found in the classes ancestry.

4-8

Windchill Customizers Guide

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 Serializable, which gives an object the ability to use RMI for travel between the client and server. Also, every abstract or concrete descendent must implement the externalizable methods writeExternal and readExternal specified in ObjectMappable. These methods provide custom serialization code to decompose and recompose objects to and from a stream. When ObjectMappable is implemented, the code generator generates a readExternal and a writeExternal method. The writeExternal method takes the attributes of an object and writes them into the database. The readExternal method takes a result set from the database and turns it into attributes in an object. For an attribute to have a column in the database, it must implement ObjectMappable. 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. It can be used as a primary key, secondary key, or a foreign key. The WTReference interface specifies an indirect addressing mechanism in which it persists one key that, when used in a query, results in finding an object. If none or more than one object is found, this results in an exception. The object itself is transient and thus not persisted.

Modeling Business Objects

4-9

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.

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.

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. (We recommend that if you extend Windchillsupplied classes, you use those described in the The Enterprise Layer chapter on page 36-1, 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.

4-10

Windchill Customizers Guide

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.

Modeling Business Objects

4-11

4-12

Windchill Customizers Guide

5
Managing Customizations
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. Topic Page

Setting Up a Directory Structure for Managing Customized Files and Text Tailoring ..............................................................................................................5-2 Best Practices for Customizing Files Supplied by PTC ......................................5-9 Best Practices for Adding New Packages and Files..........................................5-26

5-1

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. The ability to change resource bundles requires that you install the text tailoring option which is selected through the Custom installation type of Windchill Services, Windchill PDMLink, Windchill ProjectLink, or Pro/INTRALINK 9.1.

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 sitemodified (i.e., customized) files and corresponding current versions and original

5-2

Windchill Customizers Guide

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. 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.

Managing Customizations

5-3

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 versions 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 section on page 5-5. As described in the PTC Script for Working with Customized Files section on page 5-5 there 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. 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.

5-4

Windchill Customizers Guide

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 the Using the Safe Area Directory Structure When Installing the Windchill Service Pack section, later in this section (page 5-8).

Text Tailoring Directory Structure


Store your updates to PTC-supplied RBINFO files in the wtCustom directory shown in the Directory Structure Diagram for Customized Files and Text Tailoring section diagram on page 5-2. You can update text in RBINFO files only if you have installed the Text Tailoring option through a custom installation of Windchill Services, Windchill PDMLink, Windchill ProjectLink, or Pro/INTRALINK 9.1. The details on which files can be updated and how to do the updates are in the Changing Displayed Text Found in RBINFO Files section on page 5-9.

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

Managing Customizations

5-5

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. 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

5-6

Windchill Customizers Guide

installSiteChanges. This target option is also run when you run the swmaint.xml script with the listSiteModExclusions target option. make_jar.config_jars -- rebuilds all client JAR files that are based on codebase/*.jar.config files. This covers the workgroup managers and Optegra Gateway products as well as any new *.jar.config JAR files defined by the site. (Client JAR files handled by jarContents and jarManifest specifications are built separately.) See Managing Client JAR Files on page 5-14.

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

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 the Directory Structure Diagram for Customized Files and Text Tailoring section on page 5-2. 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/abcx.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 5-5.

Managing Customizations

5-7

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 either the Changed Files Only or Updates for Site-Modified Files to Safe Area installation types. Using either of these options 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 5-5 may be helpful in completing this step and later steps. 3. Update each file 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.

5-8

Windchill Customizers 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 the Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 5-2 section 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: In order to change displayed text, you must have installed the Displayed Text Tailoring capability. This is a Custom installation type of the Windchill Services, Windchill PDMLink, Windchill ProjectLink, or Pro/INTRALINK 9.1 installers. 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 the Managing Client JAR Files section on page 5-14.

Managing Customizations

5-9

The Windchill Service Pack and temporary patch installers automatically recompile these resources so maintenance updates and your site changes are recombined.

The following sections provide additional details on text tailoring and updating client JAR files. For general information about the enumCustomize tool, see the The Enumerated Type Customization Utility in the Enumerated Types chapter on page 33-11. That chapter, as well as the Internationalization and Localization chapter on page 39-1, includes further discussions about RBINFO files. 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 5-26.

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, labels, and messages (StringResourceInfo) 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. 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.

5-10

Windchill Customizers Guide

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 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 temporary 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 5-14 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 or System Configurator 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 the Managing Client JAR Files section on page 5-14.

Manipulating Property Files


Most property files should be manipulated using the xconfmanager Utility or the System Configurator. 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. Information on these tools can be found in the Windchill System Administrators Guide. 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

Managing Customizations

5-11

without an associated XCONF file, a properties file can still be manipulated with the xconfmanager Utility. The following codebase properties should not be manipulated with the xconfmanager Utility: associationRegistry.properties classRegistry.properties descendentRegistry.properties modelRegistry.properties moduleRegistry.properties moduleDir.properties debug.properties This is because these properties are manipulated by Rose Modeling tools or otherwise 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 5-27.

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 About the xconfmanager Utility in the Windchill Utilities chapter on page 6-2 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 5-2.

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

5-12

Windchill Customizers Guide

configuring certain clients, such as DCA-based 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 5-2.

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 5-2.

Managing Windchill Info*Engine Tasks


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 the Setting Up a Directory Structure for Managing Customized Files and Text Tailoring section on page 5-2. 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 Managers


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. The Workgroup Manager for Pro/ENGINEER 2001 has the following INI files: proefileadaptor.ini newdocument.ini proeworkspaceconfig.ini registryclient.ini The Workgroup Manager for CATIA V4 has the following INI files: catiafileadaptor.ini newcatiadocument.ini catiaworkspaceconfig.ini

Managing Customizations

5-13

registryserver.ini registryclient.ini The Workgroup Manager for CADDS has the following INI files: cadds5workspaceconfig.ini registryclient.ini newdocument.ini

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

5-14

Windchill Customizers Guide

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 5-18 for more information.

Overview of Client JAR Deployment Approach


To effectively manage your client JAR customizations, you need to understand Windchills 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 toplevel 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. Note: The usage of DSU comes from the fact that, pre-R7.0, maintenance releases to Windchill were delivered in Downloadable Software Updates.

Managing Customizations

5-15

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.

5-16

Windchill Customizers Guide

These logical JARs are further described in the following table.


Logical JAR 3rdPartyApplet Description 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. 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. [Note that the intermediate JARs wtPolicy, wtQB, and wtWork also serve to consolidate duplicates between themselves and JARs above them.] 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. The JAR for the Policy Administrator and domain browser/selector applets. The JAR for the QueryBuilder and Report Manager applets. The JAR for the Workflow, Life Cycle, and Team-related Applets (Workflow Administrator, Team Administrator, Lifecycle Administrator, Initiate Process, Process Manager, and Setup Participants). The JAR for the External and Remote File Vault Administrator applets. 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 in release 9.0. wtCal wtESig wtIXB wtSearch The Calendar applet JAR. The electronic signature / identity applet JAR. The JAR to support import / export and bulk-loading applets. 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. The JAR for the Attribute Administrator, Type Manager, CSM, and Re-Use Manager applets. The JAR for the login / reauthentication applet (i.e. that accessed via Login.jsp).

wtApplet

wtBootInst

wtPolicy wtQB wtWork

wtFVault wtExp

wtTypeAdm wtLogin

Managing Customizations

5-17

Logical JAR ptcAnnotator, ptcCore (not shown)

Description The JARs for the Product Structure Explorer (PSE) 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.
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. 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 -DdoDeepBuild=true

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.

5-18

Windchill Customizers Guide

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

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 Apache Web server, 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 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.

Managing Customizations

5-19

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 Apache log file, either by a specific user or all users, for specified file extensions and displays them in sorted order. Note: To use the utility, you must be using the Apache 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 a browser window, access the following page:
<local_host_name>/<Web_app_name>/wtcore/jsp/wt/sysadm/HttpRequestLogUtilStart.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 clients results to view the results from all sessions recorded.

5-20

Windchill Customizers 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:
<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.

Managing Customizations

5-21

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.

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:
Adding New Applets Re-using an Existing Root JAR

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.

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

5-22

Windchill Customizers Guide

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 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 5-20. 5. Update your new JARs contents as described in Using the HTTP Request Log Utility on page 5-20. 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).

Managing Customizations

5-23

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 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

This command executes the following targets:

5-24

Windchill Customizers Guide

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).

Managing Customizations

5-25

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

The types of files that you should store under <Windchill>/src/com/mycompany include new Java source files, property files, HTML templates, RBINFO files, XCONF files, and new files created as a result of modeling with Rational Rose. 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 new template processing class under <Windchill>/src/com/mycompany/part, you could compile it to <Windchill>/codebase/com/mycompany/part. HTML template files must be installed under <Windchill>/codebase/templates at runtime. For example, if you create some new templates in the directory <Windchill>/src/com/mycompany/part/htmltmpl, you could copy them to <Windchill>/codebase/templates/com/mycompany/part at runtime. 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/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

5-26

Windchill Customizers Guide

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 the Rational Rose modeling tool 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/ext 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 The Customizing service.properties section (beginning on page 35-24) describes the use of 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.

Managing Customizations

5-27

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.customPropertyFiles

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.customPropertFiles"/> </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.customPropertyFiles

This property is in the codebase/wt.properties file. Store a copy of new XCONF files in your source directories as described in the Best Practices for Adding New Packages and Files section on page 5-26. 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.

5-28

Windchill Customizers Guide

6
Windchill Utilities
This chapter contains information about the xconfmanager and windchill utilities. Topic Page

About the xconfmanager Utility..........................................................................6-2 About the windchill Command ...........................................................................6-6 About the windchill shell ....................................................................................6-8

6-1

About the xconfmanager Utility


The xconfmanager is a command-line utility that is used to add, remove, and modify the properties in the Windchill property files. You should use the xconfmanager (or the System Configurator) to manipulate properties; you should not manually edit property files. There are property files that should not be modified using the xconfmanager. The following registry files are managed by Windchill Information Modeler and they also should not be edited manually or using the xconfmanager: associationRegistry.properties classRegistry.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 those changes. The site.xconf file contains changes made to Windchill property files, starting with installation and continuing with each use of the xconfmanager utility or the System Configurator. The xconfmanager utility is located in the <Windchill>/bin directory. This chapter describes only the information and instructions necessary to modify specific Windchill properties. A full description of the xconfmanager utility and management of the Windchill property files is documented in the Windchill System Administrators Guide in the Administering Runtime Services chapter. Anyone with write access to the XCONF files and the property files under the Windchill installation directory can successfully run the xconfmanager utility. The xconfmanager is executed from the command line from within a windchill shell. See the About the windchill Command section on page 6-6 for more information about the windchill shell. The syntax of xconfmanager command with only commonly used parameters is as follows:
xconfmanager {-h} {-r <product_root>} {-s <property_pair>} {-t <property_file>} {--add <property_pair>} {--remove <property_pair>} {--reset <property_names>} {--undefine <property_names>} {-d <property_names>} {-p}

For the purposes of modifying Windchill properties, you will primarily use the -s, -t, and -p parameters as follows: Use the -s (--set) parameter to identify the relevant property and specify the new property value. See the Formatting Property Value Guidelines section (below) for information about formatting the <property_pair) value. Use the -t (--targetfile) parameter to specify the directory location of the property file. If the file name or path contains spaces, you must enclose the

6-2

Windchill Customizers Guide

<property_file> value in double quotes (" "). It is recommended to use a fully qualified file name to ensure an accurate reference to the file is made. Use the -p (--propagate) parameter to propagate the changes made to the XCONF files into the property files being modified in order to keep the XCONF and the property files in sync with one another. Use the -h (--help) parameter to view the help for xconfmanager. The help describes all xconfmanager parameters.

Additionally, you can add and remove property values from properties that are declared as a multi-valued properties using the following parameters: Use the --add parameter to add the value specified at the end of the set of ordered values already defined in the property. Use the --remove parameter to remove the value specified from the set of ordered values already defined in the property.

Tip: If you are unsure as to whether 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. Some examples of using the xconfmanager utility are as follows: xconfmanager is run from the windchill shell. To open a windchill shell, execute the following command at a command prompt:
windchill shell

To display xconfmanager help, execute the following command from the windchill shell:
xconfmanager -h

To display the current settings for a property, execute the following command from the windchill shell:
xconfmanager -d <property_names>

<property_names> is a comma-separated list of property names. This means that you can display the current settings for multiple properties by executing one command. To change a property value, execute the following command from the windchill shell:
xconfmanager -s <property_name>=<property_value> -t <property_file> -p

Tip: Use the fully qualified name of the property file to ensure an accurate reference. If you are sure that there is only one property file that is known to xconfmanager containing the property, you can omit the -t parameter. When setting a value for a new property not in a property file, you must include the -t parameter to name the property file to which the property is added.

Windchill Utilities

6-3

To add a new classpath entry to the Windchill 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 will be 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. Tip: The previous example command did not include the target file in the -t parameter since the property is known to be in only wt.properties.

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 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 shells 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 interpret 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

6-4

Windchill Customizers Guide

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.

Windchill Utilities

6-5

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 (optional) -h, --help -v, --[no]verbose Description Displays help and exits. Explains what is being done when a command is executed. Default is noverbose.

6-6

Windchill Customizers Guide

Arguments (optional) -w, --wthome=DIR

Description 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. Java classpath. Default is the wt.java.classpath variable value specified in the $WT_HOME/codebase/wt.properties file. Java command line arguments.

-cp, --classpath=PATH

--javaargs=JAVAARGS

Windchill Utilities

6-7

windchill Actions
Action shell Description Sets up a Windchill environment in a new instance of the currently running shell. Starts the Windchill server. Stops the Windchill server. Retrieves the status of the Windchill server. Displays the Windchill installation version. Displays the properties as seen by Windchill for the 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 with no arguments generates the help report CLASS [CLASS_ARGS] Run a Windchill class with optional class arguments. For example: windchill wt.load.Developer -UAOps

start stop status version properties <resource> [,...][?key[&key2]...]

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.

6-8

Windchill Customizers Guide

7
Customization Tutorial
This tutorial is intended for programmers who are not that familiar with Windchill. Topic Page

Tutorial Overview ...............................................................................................7-2 Create Administrator and User............................................................................7-4 Create a Library and Document ........................................................................7-12 Create a New Attribute Definition and Add it to the Document Type..............7-17 As the End User, Create a Document with the new Attribute...........................7-22 Create a Document Soft Type ...........................................................................7-25 Create an Instance of the New Document Soft Type ........................................7-27 Model a New Document Subclass.....................................................................7-28 Create an Instance of the New Document Subclass ..........................................7-38 Verify the Customizations.................................................................................7-39 Summary ...........................................................................................................7-41

7-1

Tutorial Overview
This tutorial illustrates a minimal configuration to create an environment in which you can create administrative objects (users, 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 UIs adapt to new type and attribute definitions

Assumptions
Windchill PDMLink standalone or Integral Windchill PDMLink and Windchill ProjectLink. 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. 3. As the Organization Administrator create a soft attribute definition and add it to the standard document type. 4. As the end user, create a document instance which will include the new attribute.

7-2

Windchill Customizers Guide

5. As the Organization Administrator create a second soft attribute. Then create document soft type and add the new attribute definition to it. 6. As the end user, create an instance of the new document soft type. 7. Model a new document subclass and deploy it. 8. As the end user, create an instance of the new document subclass. 9. Verify what you have done, by searching for instances of your documents.

Customization Tutorial

7-3

Create Administrator and User


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

2. From the first level navigation tabs, select Site. 3. From the second level navigation tabs, select Utilities. 4. Under Business Administration select Principal Administrator. 5. Select New User.

6. Create an Organization Administrator with the following values: User Name (login ID) Full Name E-mail Address

7-4

Windchill Customizers Guide

Password

Organization

Customization Tutorial

7-5

Click Search to search for the organization. Choose the default Organization created for your system (this was specified when the system was installed).

7. Select the Groups tab. 8. Select the black + icon to add groups to the table. 9. In the Search for Parent Groups dialog select Search (leave the search field blank), and then select the three check boxes for Administrators, Attribute Administrators and Type Administrators, then select OK.

Note: For any other organization you would not need to select Administrators. But because this is the default site organization, the

7-6

Windchill Customizers Guide

organization administrator must also be a site administrator in order to manage types and attributes. 10. Select OK.

11. Select New User.

Customization Tutorial

7-7

12. 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.

7-8

Windchill Customizers Guide

13. Close the principal admin window.

14. Now you must declare the Organization Administrator user as an Organization Administrator. Select the Organization tab from the first level navigation tabs.

15. Select your organization from the Organizations drop down list on the second level navigation. If there is a table of displayed organizations, it may also be there. 16. Select the Administrators tab from second level navigation tabs. 17. Select the Add Users icon.

Customization Tutorial

7-9

18. In the Add Organization Administrators dialog select Find Users, leaving the Search field blank. Select the user you created to be the Organization Administrator, and then select Add >> and OK.

19. With the Organization tab still selected, select the Creators sub tab. In the Current View dropdown select Library Creators.

7-10

Windchill Customizers Guide

20. Select your end user and add them to the Library Creators Group using the Add >> button.

Verify that your end user is now part of the Library Creators group.

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 a Soft Attribute and Soft Type administrator. The End User is also a Library Creator.

Customization Tutorial

7-11

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) by navigating to the Home:Overview page. There you will see the user name displayed.

3. As the End User, create a new Library. Select the Library tab and select the New Library icon.

7-12

Windchill Customizers Guide

4. Create a new library.

5. The complete library details display.

Customization Tutorial

7-13

6. Select the Folders subtab and then the Add a New Document icon.

7. In the Type drop down select Document. Click Next.

7-14

Windchill Customizers Guide

8. Set the document attributes.

9. Select Finish. You will not be setting attachments during this process.

Customization Tutorial

7-15

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.

7-16

Windchill Customizers Guide

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 Manager, select Organization > Utilities > Type and Attribute Manager.

Customization Tutorial

7-17

4. Select Attribute Definition Manager > New Organizer to create a new Attribute Organizer.

5. Specify a name for your new Attribute Organizer, and select OK.

6. Select Save. 7. Select the New Attribute icon.

7-18

Windchill Customizers Guide

8. Specify a new Integer attribute called sizeA.

9. Select OK and your new attribute will be displayed in the attribute hierarchy: 10. Before Saving, change the Display Name of the attribute to Size A. Note that the display name can be localized in resource bundles.

Customization Tutorial

7-19

11. Select the Type Manager tab, and expand the hierarchy under Document to see its subtypes.

12. With Document selected, select the Edit icon. Then select the Template tab. Within the Template tab, select Attribute Root to enable the Add Attributes button.

13. Select Add Attribute and from the dialog find and select the sizeA attribute you created. In the Template tab, select the value cell for sizeA and enter the default value of 1. 14. Select Save and then select the Check In icon.

7-20

Windchill Customizers Guide

15. You have just added the sizeA attribute to the Document type and all of its subtypes.

16. Close the Type and Attribute Manager window.

Customization Tutorial

7-21

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:

7-22

Windchill Customizers Guide

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

Customization Tutorial

7-23

3. Select More Attributes to see the soft attribute and value that you added.

4. 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, it only applies to instances created after the attribute existed on the type.

7-24

Windchill Customizers Guide

Create a Document Soft Type


As the Organization Administrator, you will create a new document soft type. 1. Verify that you are logged in as the Organization Administrator. 2. Select Organizations > Utilities > Type and Attribute Manager. 3. In the Type and Attribute Manager window, select Document and then the New icon. 4. Specify the new document type.

5. Select the Attribute Definition Manager tab, and create another Integer attribute type as a peer to sizeA called sizeB. Save it.

6. Add attribute sizeB to your new document type with default value 2.

Customization Tutorial

7-25

7. Your document type now has two attributes:

8. Select the General tab. With the type checked out, select the edit icon and change the Icon to wtcore/image/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. 9. Save and check in your type.

7-26

Windchill Customizers Guide

Create an Instance of the New Document Soft Type


1. Now, as the End User, create an instance of the new document type called Document 102. 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 X in it).

Customization Tutorial

7-27

Model a New Document Subclass


Now you will start Rational Rose (Information Modeler) and create a document subclass with a new integer attribute. 1. From the Windows Start menu open a Windchill Shell and execute "start rose":

2. Within Rose you will first be presented with a Create New Model dialog. Cancel that dialog for now. 3. Select File > Edit Path Map and verify that the path map values are referencing your Windchill installation. 4. Close the Path Map window. 5. Select File > Open, and navigate to, and open the model file:
\Windchill\src\wt\WTdesigner.mdl

6. When prompted to Load subunits select Yes.

7-28

Windchill Customizers Guide

7. Wait until the load is complete, at which point the screen will update and look something like this:

8. In the browser pane, expand the Logical View. Right click Logical View and select New > Class Diagram. Name the new diagram "com Packages". Double click on the "com Packages" icon to open the empty diagram.

Customization Tutorial

7-29

9. Select the Package icon then click in the diagram pane. Name the new package "com":

10. Right click the "com" package in the browser and select New > Package. Name the new package "acme". 11. Right click the "acme" package in the browser and select New-> Class Diagram. Name the new diagram "Documents". 12. Double click the Documents diagram icon to open the new empty diagram. 13. Select the Class icon and click in the diagram window. Name the new class "WTDocument" (it must be this name, as it refers to an existing Windchill class that you will inherit from). When prompted to "Delete NewClass from the Model?" select "Yes".

7-30

Windchill Customizers Guide

14. Select the Class icon again and click in the diagram window below WTDocument. Name the new class "AcmeModeledDoc". Select the Generalization icon and draw an arrow from "AcmeModeledDoc" to "WTDocument".

15. Double-click "AcmeModeledDoc" in the Class Diagram to open the Specification Dialog. Select the Attributes tab.

Customization Tutorial

7-31

All of the existing attributes are inherited from WTDocument and its parent classes. Right click on the list of attributes and select "Insert". Name the new attribute "sizeC".

16. Double-click on the new attribute to open the Class Attribute Specification window. 17. Set the following values: Type = Integer Initial Value = 3

7-32

Windchill Customizers Guide

Export Control = Public

18. Select OK to close the Class Attribute window. 19. Now open the Windchill tab within the Class Specification window. Change the StandardIcon to "wtcore/images/stop.gif".

Customization Tutorial

7-33

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.

20. Select OK to close the Class Specification window.

21. Now you will generate the Java source file, SQL scripts and other artifacts for your new document class.

7-34

Windchill Customizers Guide

22. Select AcmeModeledDoc in the class diagram. Select Tools > Windchill > System Generation. Accept the default selections, select OK.

23. After a minute or so the generation will be complete. You will find the generated java file here:
..Windchill\src\com\acme\AcmeModeledDoc.java

You will find the generated SQL file (to create the new database table) here:
..Windchill\db\sql\com\acme\create_AcmeModeledDoc_Table.sql

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

24. You can inspect the java and sql files to see what was generated (the ClassInfo.ser file is a binary instance of the ClassInfo java class, so you cannot inspect it directly). 25. Now you will compile the java file. 26. Open a Windchill Shell. CD to the directory (<Windchill>/src/com/acme) of the java source file. 27. Compile the java file.

Customization Tutorial

7-35

javac -d <Windchill>\codebase AcmeModeledDoc.java

You'll find the compiled class file in the same directory as the ClassInfo.ser file. 28. 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

29. From the Windchill Shell, login to sqlplus.


sqlplus <db_user>/<db_user_pw>@<sid>

30. 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

31. 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

You may also want count the number of rows in the table to confirm that it is empty:
select count(*) from AcmeModeledDoc

32. Now restart the method server

7-36

Windchill Customizers Guide

33. As the Organization Administrator, open the Type and Attribute Manager. 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.

Customization Tutorial

7-37

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. 3. Navigate to the More Attributes 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

7-38

Windchill Customizers Guide

Verify the Customizations


To verify what you have done, search for instances of your documents. 1. Now click "Search:" in the top right corner of the browser. 2. The Search Page opens. In the "Name" field enter "Document 1*":

3. Now select "Search" button in the bottom right. Four results will be displayed: the four documents you created.

Customization Tutorial

7-39

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.

7-40

Windchill Customizers Guide

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 soft attributes definitions and soft type 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 Rose Verified what you have done, by searching for instances of your documents.

Customization Tutorial

7-41

7-42

Windchill Customizers Guide

III
User Interface Customization Section

Chapter

Page

User Interface Technology Overview .................................................... 8-1 Generic UI Customizations.................................................................... 9-1 Customizing HTML Clients Using the Windchill JSP Framework..... 10-1 Adding Actions and Hooking Them Up in the UI ............................... 11-1 Gathering the Data for the UI .............................................................. 12-1 Presenting Information in the UI ......................................................... 13-1 Constructing Wizards........................................................................... 14-1 Information Pages ................................................................................ 15-1 Incorporating Pickers in JSP Clients.................................................... 16-1 JSP Customization Scenarios............................................................... 17-1 Customizing the Product Structure Explorer (PSE)............................. 18-1 Customizing Windchill MPMLink ...................................................... 19-1 Customizing Search Functionality ....................................................... 20-1

8
User Interface Technology Overview

This chapter explains and give 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). Topic Page

Windchill Client Architecture Overview ............................................................8-2 Adding Custom Code to all Windchill Client Architecture Pages......................8-8 Javascript Functions Overview ...........................................................................8-9

8-1

Windchill Client Architecture Overview


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 framework is largely a jsp-based system and is composed of these items: JSP Pages/Fragments Java Beans Custom Tags/Taglibs Java Services JavaScript functions and 3rd party javascript libraries Reusable Components

The internal code to the jsp will contain the necessary data to describe and configure the sub-components that are used.

Basic Elements of a JSP page


You will need to be aware of a few important jsp fragment files.

begin.jspf
The first and most important is the begin.jspf. This files exists in codebase/netmarkets/jsp/util/. This file is included in most view jsp pages. The purpose of this jspf is to: Include a tag for rendering the header, and 1st and 2nd level navigation.

Take care of housekeeping like: instantiation of beans (context, clipboard, session) including standard .js and .css files including common HTML pieces like <html><body>etc) creating an HTML form for submitting data (called mainform) providing support for closing pop ups and refreshing the main page

8-2

Windchill Customizers Guide

end.jspf
Another jspf that is included on most pages 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 (for example, switching the 3rd level navigation content without refreshing the page display the footer

catch exceptions and handles them if they occur within the page

beginWizard.jspf
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, however, it will not include the rendering of the header for the 1st and 2nd level navigation.

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 NmObject Utilities in the Gathering the Data for the UI chapter on page 12-15 for more information.

Custom Tags and TagLibs


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. Refer to the taglib javadoc at the following location: http://www.ptc.com/view?im_dbkey=77892

Java Services 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

User Interface Technology Overview

8-3

directly. See the Adding Actions and Hooking Them Up in the UI chapter the page 11-1 for more information.

Validation Service
Validation of actions, properties, and wizard steps 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, properties, or wizard steps should be displayed, disabled, or hidden. The service will invoke the appropriate delegates to gather the requested status for that action, property, or wizard step. As a customization point, you can write a delegate that is mapped to a specific action, property, or wizard step, 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 soft attributes created via the type manager, not modeled attributes. That validation service will actually call the role based service as a first pass of validation. If the action, property, or wizard step is valid for the user based on role, the service will then invoke the appropriate delegate. The Validation Service is also used to validate the data entered by the user in wizards. For more information on the Role Based UI framework see Customizing Role-Based UI Functions - Attribute Visibility on page 9-8. For more information on the Validation Service see Adding Validation Logic for Actions and Properties on page 10-46.

Javascript Functions and 3rd Party Javascript Libraries


Also installed with Windchill are 3rd party javascript libraries including Prototype, script.aculo.us, and Dojo libraries.

Reusable Components
There is a broad set of components that are built using the framework that can be reused in customizing your pages. The basic steps to render many components (table, tree, property panel, etc.) are: Describe the component (describe* tags) Acquire the necessary data (get* tags) Render the component (render* tags)

8-4

Windchill Customizers Guide

The configuration of these phases begins with the tag handler 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"%>

This section will gloss over what the details of most of the columns and properties in the tags mean for now, and focus on the overall flow of the page.

Component Description
This part of the lifecycle is used to define the columns/properties that the component will display. This happens first 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 do display. The core 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>

Variations on the describeTable tag are the describePropertyPanel tag, which presents object attributes in label-value rows, and the describeAttributesTable tag, which also presents attributes in label-value rows but in tabular format.
Structure of the tag

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 arent exposed as attributes of the parent tag itself. This gives the infrastructure and the developer some flexibility about the metadata theyd like to be available down the road, without always requiring a tag library definition (tld) update to do so. describeColumn: 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.

User Interface Technology Overview

8-5

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.

Data Acquisition
The second phase gets the model data based on the description from the first phase. 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. The developer does this with one of client infrastructures get tags. The most typical usage of the tag 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>

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 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 do not 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.

8-6

Windchill Customizers Guide

Server processing: data utilities

The construction of a ComponentModel doesn't happen in the servlet container, but instead in the method server. During the execution of the get tags, the flow of execution leaves the servlet container and jumps over to the method server. On the method server, the client infrastructure runs through several phases to create the ComponentModel. The step of most interest to developers is the invocation of Data Utilities, which are delegates that allow developers to post-process and/or augment the data returned by the low-level data acquisition API.

Rendering
This phase produces HTML and JavaScript based on the model data. Rendering is usually the simplest phase for the developer to set up. The client infrastructure 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}"/>

What is it doing?

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

User Interface Technology Overview

8-7

Adding Custom Code to all Windchill Client Architecture Pages


This section explains how to add custom code to all Windchill Client Architecture pages.

Javascript and CSS files


To add any custom javascript, or css scripts to all the pages, modify the codebase/netmarkets/jsp/util/begin_custom.jspf to add the necessary html to get the js or css files included.

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. The message will appear at the top of the page before the Windchill header is displayed.

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

8-8

Windchill Customizers Guide

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

TableUtils package
Name Purpose

getTableRows (parentNode)

Return array of Nmcontexts for each row in a table given the outer DIV DOM node. Return array of Nmcontexts for each row in a table given a table id Return array of Nmcontexts for each row in a table given the outer DIV DOM node. Given some DOM Element, walk up the DOM tree to figure out which table this is in. Given some DOM Element, walk up the DOM tree to find the table DOM Node. Gets the hidden input field that contains the added rows of a table id. Returns String that can be tokenized. Gets the hidden input field that contains the removed rows of a table id. Returns String that can be tokenized Walk up the Dom tree finding the first <tr> tag Remove a row from a table/tree returns true/false if the dom NODE is a row in the table with the class JCA_tablerow @param node - checkbox dom node

getTableRowsByID (tableID getTreeRows (parentNode)

findTableID (node)

findParentTableNodeId (node)

getAddedRows (tableid)

getRemovedRows (tableid)

getParentTR (node) removeParentRow (oid, node, tableid) isTableCheckBox (node)

User Interface Technology Overview

8-9

Name

Purpose

deSelectOtherTableRows (table id)

Invoked when a checkbox is clicked and it changes the row css so that it appears as highlighted. Get all the form nodes within the given parent node. If parentNode is unspecified, the entire document is searched. Disable all form inputs in the given row Updates row Count in Title bar. turns the outer div node id into a normal table id defined by the jsp tags table__jca.sometable__TABLE -> jca.sometable turns a div table id into the simple table id used as in the jsp tags table__jca.sometable__TABLE -> jca.sometable

getFormNodes (node)

disableRow (tr) updateHeader (tableid) getUnformattedTableId (tableid)

getFormattedTableId (id)

updateFooterCount (tableid, count, changeValue) disableSelectAllChBox enableSelectAllChBox

Updates Count of selected rows in footer. Disables the select all checbox given a table id enables the select all checbox given a table id

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.

8-10

Windchill Customizers Guide

Name

Purpose

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, responseObject)

Parses actions from an asynchronous response. Generic high level method that will delegate to all the types of responses. Gets rid of unwanted text from the response. Substrings out antying not inbetween the html comment. Can execute javascript blocks conditionally. Start/end are the html comment strings to use to find the response in.

stripText (text, divID, skipScriptEval, start, end)

rowHandler
Name Purpose

addRows (oidList, table_id, tableRows, params)

Add rows to a table. oidList is an array of oids to add as rows. 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

User Interface Technology Overview

8-11

Name

Purpose

removeRows ( rows, table_id, visually_remove )

Remove rows from the table, rows is an array of oids.

requestHandler
Name Purpose

handleRequest (table_id, params) doRequest (url, options)

Refreshes a table given the params 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 (className, parentElement , tag name)

Returns all the children of the 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. Refreshes the contents of a div (via Ajax) when an element fires its change event. Similar to Prototypes updater, performs an Ajax call (appears to ignore divID). Modifies the hidden form fields of tables used in wizards when users dynamically add rows to said table. Can cause the row to be added dynamically if the doAjaxUpdate is true. Refreshes the parent window. Family of methods for getting contents of the Clipboard as a comma delimited list.

refreshDivTag(id, name, url)

getElementHtml(params, divID, doAsynch, url) addRows( list, tableId, refresh, doAjaxUpdate, preventDuplicates )

PJLrefreshOpener() and refreshOpenerOnly() getClipboardItems()

8-12

Windchill Customizers Guide

Wizard.js functions
Name Purpose

handleRequest (table_id, params) doRequest (url, options)

Refreshes a table given the params

Make the ajax request for the table. Used by the above method to change the url with the options set. Add request params to the options based on the params list passed in. Adds all this form params to the ajax request including the params passed in. Updates the wizard step indicator images for all steps based on the current state. Updates the embedded help based on the current step. Gets the next step id. Sets the next step in the wizard to be refreshed when displayed. Make the wizard go back one step Make the wizard go to the next step 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.

parseAnonymousParams (startIndex, params, result) getParamString

updateStepImage

updateEmbeddedText getNextStep setNextStepDirty goBack goNext setActiveStep (stepId, wizardAction)

findStepIndex setNextStep setStepDirty setStepClean

Find the index of a step id Override what the next step id is Set a step to need a refresh should it display again Set a step to NOT need a refresh should it display again

User Interface Technology Overview

8-13

Name

Purpose

setStepIncomplete setStepComplete setStepRequired setStepOptional

Set a step to need to be vistited again as it needs more info Set a step to NOT need to be vistited again as it does not needs more info Make a user visit a step before the wizard can be completed Make a user able to complete the wizard WITHOUT visiting the specified step id Remove a step from the list of steps Add a new step to the list of steps based on what has already happened dynamic steps Sets the ok button to be displayed or not based on the current state. Sets the next/back button to be displayed or not based on the current state. Force the finish and apply buttons to be disabled Force the finish and apply buttons to be enabled Gets the current active step id Refreshes the current wizard step Refreshes the speicified wizard step This function takes a url and turns it into an absolute URL. Turns on the progress indicator Turns off the progress indicator Finish the wizard by executing it on the server

removeStep insertStep

resetOkButton resetNextBackButton

disableOkButton enableOkButton getCurrentStep refreshCurrentStep refreshStep getAbsoluteUrl goProgress stopProgress onSubmitMain

8-14

Windchill Customizers Guide

Name

Purpose

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. To do Ajax validation when an action is clicked. The event object. The key to use in validation code

onClickValidation (evt, key)

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

User Interface Technology Overview

8-15

8-16

Windchill Customizers Guide

9
Generic UI Customizations
This chapter describes user interface customizations that are independent of any particular Windchill client technology. Topic Page

Handling Icons for Business Objects ..................................................................9-2 Defining Localizable Text for the UI ..................................................................9-3 Customizing the Handling of Soft Attributes......................................................9-6 Customizing Role-Based UI Functions - Attribute Visibility .............................9-8 Customizing Role-Based UI Functions - Action Visibility...............................9-17 Preferences ........................................................................................................9-18 Constructing URLs............................................................................................9-24 Offline Package Customization.........................................................................9-27 System Banner Alert Message ..........................................................................9-32

9-1

Handling Icons for Business Objects


Modeled Business Objects
The icons for a class are modeled into Rose. For the modeled class, select the WT_UI tab and set the StandardIcon and OpenIcon accordingly.

These paths must be fully qualified from the Windchill codebase. The location for all .gif images at this time is wt/clients/image. The gif image specified must be 16 by 16 pixels. Class inheritance determines what glyphs are overlaid on an object: Subclasses of wt.doc.Document are displayed based on their primary format and will also inherit the overlays of RevisionControlled.

wt.clients.util.IconCache is the class that clients use to access icons. An example of its usage follows:
IconCache icons = new IconCache( someWTContextObj ); Image img = icons.getStandardIcon( someWTObject ); Image img2 = icons.getOpenIcon( someWTObject );

Any subclass of wt.fc.WTObject is accepted as an argument. See this class entry in your installed Windchill Javadoc for more information.

9-2

Windchill Customizers Guide

Defining Localizable Text for the UI


The rbInfo File Format
Resource bundle information (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. For details on how to use rbInfo files, see Resource Info (.rbInfo) Files on page 39-8.

Customizing Localizable Display Names for Modeled Elements


A display name for a modeled element (class, attribute, or association role) can be customized. These display names are obtained through the PropertyDescriptors that are created by the wt.introspection package. The default display names are defined in the delivered ResourceInfo (.rbInfo) files. The default values can be overridden by placing entries in the ResourceInfo customizations file for modeled packages, which exists in a parallel directory structure. This segregates customizations so that they need not be manually reapplied at each release. The entries placed in a ResourceInfos customization file override the entries delivered by the package owner. For more information, see the Managing Customizations chapter on page 5-1. To change the display name for a modeled element, perform the following steps: 1. Determine the entry necessary to accomplish the customization. 2. Add the customization entry to the appropriate ResourceInfo customizations file. 3. Build the runtime resource bundles for the customized package. 4. Verify the customization. 5. Restart the method servers if they were running during the procedure. The following example changes the display names for the wt.part.WTPart class and its locker attribute. The following steps describe how to determine which ResourceInfo customizations files entries will contain the new display names, and how to set the values. The customization will be made in a location parallel with the ResourceInfo files. The default location for these customizations is <Windchill>/wtCustom, as defined by the wt.generation.custom.dir entry in the tools properties. Create this directory if it does not already exist. For more information see the The Windchill Development Environment chapter beginning on page 2-1, especially the tools.properties file (page 2-13) and user.properties file (page 2-13) descriptions. 1. Determine the entries necessary to accomplish the customizations. a. Obtain an info report for the class by executing the following command:

Generic UI Customizations

9-3

infoReport wt.part.WTPart

b. Inspect the current getDisplayName() values for the WTPart class and its locker attribute:
getDisplayName() getDisplayName() : Part : Locked By

c. Inspect the value of the WTIntrospector.DEFINED_AS property of the locker PropertyDescriptor:


getValue( WTIntrospector.DEFINED_AS ) : wt.locks.Lock.locker

d. Based on this information, use the following values:


Model Element Customization File Entry Key

WTPart locker

<Windchill>/wtCustom/wt/ part/partModelRB.rbInfo <Windchill>/wtCustom/wt/ locks/locksModelRB.rbInfo

WTPart.Value Lock.locker.value

2. Add the customization entries to the appropriate ResourceInfo customizations files: a. Add the following entry to <Windchill>/wtCustom/wt/part/partModelRB.rbInfo (create this file if it does not exist):
WTPart.value=Windchill Part

b. Add the following entry to <Windchill>/wtCustom/wt/locks/locksModelRB.rbInfo (create this file if it does not exist):
Lock.locker.value=Lock Held By

3. Build the runtime resource bundles for the customized packages by entering the following commands:
ResourceBuild wt.part.partModelRB ResourceBuild wt.locks.locksModelRB

4. Verify the customizations: a. Obtain an info report for the class and inspect the getDisplayName() values as described in the preceding steps. The values should reflect the customizations. b. If the info report values are unchanged, perform the following steps: i. Verify that the build step actually updated the following serialized resource bundle file:

9-4

Windchill Customizers Guide

<Windchill>/codebase/wt/part/partModelRB.RB.ser

ii. Verify the contents of the updated serialized resource bundle:


java wt.util.resource.ResourceBundleUtil wt.part.partModelRB

To support other locales, make locale-specific copies of the files and add the localized values, as in step 2 above. For further information on localizing resource entries, see the Internationalization and Localization chapter on page 39-1.

Generic UI Customizations

9-5

Customizing the Handling of Soft Attributes


Windchill PDMLink and Windchill ProjectLink provide a means to customize the way soft attributes are displayed and processed in HTML Create and Update clients. By editing a XML file you may do the following: 1. Turn off display of the Use Default button. (This also affects the Product Structure Explorer.) 2. Specify whether a string soft attribute should be displayed as a single-line or multi-line input field. This directive overrides the StringLengthThresholdForMultilineInput preference. The path of the XML file is: WT_HOME/codebase/config/logicrepository/xml/AllClients.xml. The file is described by the following DTDs: <Windchill>/codebase/config/dtd/LogicRepository.dtd <Windchill>/codebase/config/dtd/AllClients.dtd

Format of AllClients.xml
The format of elements in AllClients.xml is as follows:
<LogicRepository> <ElementGroup> <LogicContext dataType="<object type>"/> <ObjectAttributes id="ObjectAttributes"> <AttributeEditField id="IBA|<attribute logical form name>" showDefaultValue="true|false" inputFieldType="singleLine|multiLine"/> ... </ObjectAttributes> </ElementGroup> ... </LogicRepository>

Multiple ElementGroup tags may be included in AllClients.xml. All ElementGroup tags must be placed between the beginning and ending LogicRepository tags in this file. Each ElementGroup tag includes a LogicContext tag and an ObjectAttributes tag. The LogicContext tag indicates the object type of an ElementGroup. The behavior of all the attributes included in the ElementGroup applies to this object type. The dataType attribute of the LogicContext tag may refer to a soft type or a modeled type. To refer to a soft type use the hierarchical path name for the type, with each element separated by a '|' character. For example, to configure attributes for the soft type "com.MyCompany.www.MyPart" that is derived from WTPart you would specify:
<LogicContext dataType="wt.part.WTPart|com.MyCompany.www.MyPart"/>

9-6

Windchill Customizers Guide

To refer to a soft type "com.MyCompany.www.ABCPart" that is derived from "MyPart" you might specify:
<LogicContext dataType="wt.part.WTPart|com.MyCompany.www.MyPart|com.MyCompany.www.ABCPart"/>

An example reference for a custom modeled subclass of WTPart called ext.part.MyModeledPart is:
<LogicContext dataType="ext.part.MyModeledPart"/>

Note: The LogicContext tag, as defined by LogicRepository.dtd, also includes an optional application attribute. The application attribute is not used for elements in AllClients.xml. The ObjectAttributes tag may include multiple AttributeEditField tags. Include an AttributeEditField tag for each attribute you wish to configure. These tags are described in <Windchill>/codebase/config/dtd/AllClients.dtd. In the id attribute of the AttributeEditField element, modeled attributes are identified by the prefix "MBA" and soft attributes by the prefix "IBA". An AttributeEditField tag may include either a showDefaultValue attribute or an inputFieldType attribute or both. The inputFieldType attribute will be ignored if the attribute is not a string. If no AttributeEditField tag is provided for an attribute its presentation is as follows: 1. Use Default Button - Will be presented if the attribute has a default or initial value, is editable, and has not yet been set in the database. 2. Input Field Type - Will be determined according to the value of the StringLengthThresholdForMultilineInput preference.

Example
An example ElementGroup to configure three soft attributes for the modeled base type wt.part.WTPart is as follows:
<ElementGroup> <LogicContext dataType="wt.part.WTPart"/> <ObjectAttributes id="ObjectAttributes"> <AttributeEditField id="IBA|MyBooleanAttribute" showDefaultValue="false" /> <AttributeEditField id="IBA|MyStringAttribute" showDefaultValue="false" inputFieldType="singleLine"/> <AttributeEditField id="IBA|MyStringAttribute2" inputFieldType="multiLine"/> </ObjectAttributes> </ElementGroup>

Generic UI Customizations

9-7

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 dont 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 Administrators 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.

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:

9-8

Windchill Customizers Guide

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

9-9

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

9-10

Windchill Customizers Guide

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 *actionModels.xml Type XML Description 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 <Windchill>/codebase; other *actionmodels.xml files are generally in <Windchill>/codebase/config/actions Files where actions and other UI components are defined. Actions are optionally given a uicomponent value. actions.xml is located in <Windchill>/codebase; other *actions.xml files are generally in <Windchill>/codebase/config/actions. 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/netmarkets/roleAccess/.

*actions.xml

XML

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

Generic UI Customizations

9-11

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. 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/>

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:

9-12

Windchill Customizers Guide

31.value=Create Folders 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/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.

Customization Points uic Element


Each UIC in roleaccessprefs.xml represents a UIComponent or action to be controlled.
Possible Values string

Parameter name

Default Value n/a

Req? Y

Description 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. The position of this UI component in the wizard. UI components with lower numbers are placed before those with higher numbers.

order

n/a

Integer

Generic UI Customizations

9-13

Parameter enabled

Default Value true

Possible Values true | false

Req? N

Description Whether or not this uicomponent will be shown in the wizard and utilized by the system. The default visibility value for All Members. The default visibility value for 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.

defaultAll defaultManager

true true

true | false true | false

N N

defaultGuest

true

true | false

The default visibility value for people in the Guest role. Note: Guests are not technically members of the Project; they are not unioned with the ALL_MEMBERS role.

managerEnabled

true

true | false

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. 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.

guestEnabled

true

true | false

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 profilebased 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.

9-14

Windchill Customizers Guide

<uic name=CUSTOMIZED_TAB order=190 enabled=true defaultAll=true/>

2. Associate the appropriate actions in actions.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 the Procedure Making an Action Available to Visibility Administration section on page 9-12 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.

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

Generic UI Customizations

9-15

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


Windchill Customizers Guide Managing Customizations

Other Related Windchill Documentation


Windchill Business Administrators Guide Role-Based Visibility Administration Windchill Business Administrators Guide Access Control (ad hoc policies)

9-16

Windchill Customizers Guide

Customizing Role-Based UI Functions - Action Visibility


Role-based action visibility in Windchill is implemented only in JSP pages. See the Action Visibility section in the Adding Actions and Hooking Them Up in the UI chapter on page 11-27 for more information.

Generic UI Customizations

9-17

Preferences
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

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

9-18

Windchill Customizers Guide

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 dont 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 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

Generic UI Customizations

9-19

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), /keyname is the name of the key under the node (SortOrder) and % [ ]tag is one of the tags mentioned above (% [ ]DISPLAY_NAME).

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 manger UI and visible at what contexts: SITE, ORGANIZATION, CONTAINER or USER. Preference category: The category the new preference will appear under in the Preference Manager UI. Display name: This is the Name column in the Preference Manager UI string in the form <RBINFO>:< RBINFO key>

9-20

Windchill Customizers Guide

Description: This is the Description column in the Preference Manager UI 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 handler

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 Manager 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/mycompany/MyNewPreference MyNewPreference.description.value=Description of preference /com/mycompany/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">

Generic UI Customizations

9-21

<NmLoader> <csvPreferenceCategory handler="wt.preference.LoadPreference.createPreferenceCategory" > <csvname>CUSTOM_PREFERENCE_CATEGORY</csvname> <csvparentName></csvparentName> <csvdisplayName> com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceC ategory.displayName </csvdisplayName> <csvdescription> com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceC ategory.description </csvdescription> </csvPreferenceCategory> <csvPreferenceDefinition handler="wt.preference.LoadPreference.createPreferenceDefinitio n"> <csvname>/com/mycompany/MyNewPreference</csvname> <csvvisibility>USER</csvvisibility> <csvcategoryName>CUSTOM_PREFERENCE_CATEGORY</csvcategoryName> <csvdisplayName>com.mycompany.pref.mycompanyPreferenceResource: MyNewPreference.displayName</csvdisplayName> <csvdescription>com.mycompany.pref.mycompanyPreferenceResource: MyNewPreference.description</csvdescription> <csvlongDescription>com.mycompany.pref.mycompanyPreferenceResou rce:MyNewPreference.longDescription</csvlongDescription> <csvdefaultValue>Default Value</csvdefaultValue> <csvhandler>com.ptc.windchill.enterprise.preference.handler.Str ingPreferenceValueHandler:4000</csvhandler> </csvPreferenceDefinition> <csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.setClientDefinitionLink"> <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

9-22

Windchill Customizers Guide

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.deletePreferenceDefinitio n"> <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

Generic UI Customizations

9-23

Constructing URLs
The URLFactory
The URLFactory is a utility class provided to generate relative HREFs and support the Windchill Single-Point-Of-Contact (SPOC) environment. The URLFactory has been designed to take in a web-resource at a particular state in the Windchill system (from a certain request, host etc.) and generate an appropriate String HREF or URL object corresponding to that resource. The URLFactory was introduced in Release 6.0 to replace the functionality provided by GatewayURL, as GatewayURL has a number of significant limitations in its implementation. The URLFactory is an instance-based toolkit which may be used in either Java code directly, JSP Pages or HTML templates. For Java code directly, there are two constructors defined as can be seen in the Javadoc. The most commonly utilized one will be:
URLFactory aURLFactory = new URLFactory( );

This will utilize the current servers codebase and properties for HREF construction.

Using the URLFactory with JSP


See URLFactory in the JSP Environment in the Additional Topics - Client Customization appendix on page E-7, for details on how to setup a JSP page to utilize the URLFactory.

Utilizing Windchill Gateways and Servlets with the URLFactory


In order to utilize the gateways and servlets with URLFactory a Helper class needs to be written like the wt.httpgw.GatewayServletHelper class. These helper classes will provide a series of methods to build properly formed links through the gateway or servlet. For example, using the GatewayServletHelper class a call to buildAuthenticatedHREF( ) will return a HREF utilizing the URLFactory with a call similar to the one below (for JSP)
wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF (url_factory,"wt.httpgw.HTTPServer","echo","");

If writing a helper class, the GatewayServletHelper provides a good basis for developing further helper classes. Helper classes should not be extended but implemented on a package or servlet specific level and if possible should be declared final for JIT (just-in-time) compilation and optimization.

Utilizing relative links in the URLFactory


URLFactory is simply a processor for taking a resource from an arbitrary location under the codebase and determining if several techniques such as relative links

9-24

Windchill Customizers Guide

may be utilized for the desired resource. Relative links will automatically be returned if the RequestURI is set, and the desired resource can be resolved into a relative link (for example an external link to another site will always be returned as an external link).

Setting the URLFactory to Output Fully Qualified HREFs


In order to generate fully qualified HREFs, the easiest method is to set the request URI to null. For example,
URLFactory aFactory = new URLFactory( ); aFactory.setRequestURI( null ); String aHREF = aFactory.getHREF("wt/clients/login/login.html");

Would return the HREF:


"http://<hostname>/<web-app>/wt/clients/login/login.html"

Writing a Mapping File


A mapping file is basically a flat-text property file. Empty lines, or lines starting with a # are ignored. The mapping filename for Windchill is urlmap.properties and should be located in the Windchill codebase. The URLFactory is smart enough to find it and utilize it automatically. The mappings should be key/value pairs and following the mapping schemes defined below.

Valid Mapping Schemes


There are many different mapping schemes and formats that may be used. Please see the Javadoc for wt.httpgw.URLFactory mappings. Following are three common mappings that may be used, however altogether there are over twenty such mappings.
# Will map the folder wt/clients to a folder on newhost.com, # in the Windchill6 codebase wt/clients/=http://newhost.com/Windchill6/wt/clients/ # Will map the wt/clients folder to another folder wt/clients/=wt/customization/clients/ # will map the resource index.html to the same protocol on a # new host and codebase wt/clients/index.html= ://newhost.com/Windchill6/wt/clients/index.html

Mapping a Particular File Type

Currently there is no functionality in the mapping scheme to map a particular file type to an alternate location/hostname. In future releases of Windchill this may be addressed if there is a need for this capability.

Generic UI Customizations

9-25

Mapping Components of Core Windchill

For Windchill Development, the mapping scheme should NOT be used to map any components of the core Windchill. This capability has been added to support multiple customer requirements, and should not be utilized as a way to make classes/documents of Windchill re-direct to other classes/documents. The mapping file may be used during development to remap to a new prototype or program, however proper HREFs should be implemented in any relevant files before the program is placed into production. There is a performance decrease using the URLFactory, and it should only be used to support customizations.

Capturing Errors From the URLFactory


Currently the only exceptions thrown by the URLFactory are at URLFactory instantiation. A WTException will be thrown by URLFactory if there is a problem reading the urlmap.properties file at construction.

Character Encoding in the URLFactory


Character encoding in the URLFactory will be handled internally by the URLFactory. All HREFs and URLs will be properly encoded before being returned to the calling program. As well, any passed in parameters are assumed to be in their decoded form and stored in the appropriate HashMap. See the parseFormData or parseQueryString class entry in your installed Windchill Javadoc for more information.

9-26

Windchill Customizers Guide

Offline Package Customization


Objective
You want offline packages exported from Windchill to display your companys 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 companys 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.

Generic UI Customizations

9-27

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 %WT_HOME%\codebase\com\ptc\netmarkets\wp\ ixb directory of your server. Contained within the resources.zip file, this CSS style sheet contains the rules which control the look and feel of the offline view. The HTML file which is loaded at the top of every page. The background image of the header Transparent GIF of the Windchill logo.

wpofflinestyles.css

CSS Style Sheet

head.html header.gif logoWC.gif

HTML File GIF graphics file GIF graphics 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 section on page 9-29. 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.

9-28

Windchill Customizers Guide

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 with Windchill background image (header.gif) and a dark green bottom border. logoWC.gif Height: 55 pixels.

Defines the border, background image and color of the header.

.wncApplLogo .applLogo

Defines logo graphics file. Defines the height of the logo div, normally shown in the upper left corner of the page. Defines the style of links and text normally in the upper right corner of the page. Links can be added to this div.

.pageHeaderActions (CSS rule in wpofflinestyles.css) pageHeaderActions (div in head.html)

White text links.

Delivered empty

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.

Offline Package View Supported Icons


The following icons are supported in the offline view of a package. Only these icons are capable of being represented. If an object of an unsupported type is included in a package, the offline view attempts to determine which icon is closest in the object hierarchy using the external type id string. If none if found, a generic icon is used. WPBaseline WTPart

Generic UI Customizations

9-29

WorkPackage CDRLPackage

Documents WTDocument Plan Agenda Presentation General ReferenceDocument Minutes

CAD Documents EPMDocument DynamicDocument Note Deviation BurstConfiguration CADASSEMBLY

Change Objects WTVariance WTChangeRequest2 WTAnalysisActivity WTChangeInvestigation WTChangeProposal PromotionNotice WTChangeActivity2 WTChangeDirective WTChangeIssue WTChangeOrder2 ChangeAction AuthorizationAgreement

9-30

Windchill Customizers Guide

VariantSpec WTProductInstance2 folderLink

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

9-31

System Banner Alert Message


You can create a sytem 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 Tomcat.

Displaying the alert message on the top of Windchill UI pages


Write the alert message with html format into the following file: windchill_home\ codebase\netmarkets\jsp\util\banner.txt For example:
<style type="text/css"> .bannertable {border: 2; background: #E7E8E0; text-align: center; width: 100%;} .bannerfont {color: #BB0000; font-weight: bold; font-size: 1em;} </style> <TABLE class=bannertable cellpadding=0 cellspacing=5> <TR> <TD> <FONT class=bannerfont> <center> <table border=1> <tr bgcolor=white> <td width=800> <font color=red size=+1> <center> Windchill maintenance alert: Windchill server will be shut down soon for maintenance. </center> </font> </td> </tr> </table> </center> </FONT> </TD> </TR> </TABLE>

Removing the alert message from Windchill UI page


Set windchill_home\codebase\netmarkets\jsp\util\banner.txt as empty file.

9-32

Windchill Customizers Guide

Turning off the alert banner feature


1. Set windchill\codebase\netmarkets\jsp\util\begin_custom.jspf as an empty file 2. Restart Tomcat.

Generic UI Customizations

9-33

9-34

Windchill Customizers Guide

10
Customizing HTML Clients Using the Windchill JSP Framework

This chapter explains and give 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). Topic Page

Customizing Generic Aspects of JSP Pages......................................................10-2 Customizing UI Branding .................................................................................10-2 Customizing the UI with Ajax...........................................................................10-4 Checkin/Checkout .............................................................................................10-8 Component Access Control.............................................................................10-11 Attachments.....................................................................................................10-16 Property Panel .................................................................................................10-26 Customizing Access Control For Packages.....................................................10-33 Generating HTML Tags for ProductView Visualization Within a JSP Page .10-37 Tools Overview ...............................................................................................10-40 Adding Validation Logic for Actions and Properties......................................10-51

10-1

Customizing Generic Aspects of JSP Pages


This section contains the following topics: Customizing UI Branding (page 10-2) Customizing the UI with Ajax (page 10-4)

Customizing UI Branding
This section describes how to make changes to certain generic items that appear on JSP pages such as logos, site-specific information in headers and footers, and generic error messages. Note: In making changes to .rbInfo files and image files, be sure to follow the coding practices introduced in the Resource Info (.rbInfo) Files section in the Internationalization and Localization on page 39-8. Caution: Do not change any <key>.constant entries in the .rbInfo files, change only <key>.value entries. Setup: It is necessary to have an internationalized Java SDK installed so that the classes can be compiled.

1. Modify <Windchill>/src/com/ptc/netmarkets/netmarkets/netmarketsResource.rbInfo (and/or any of the other language versions) in a text editor. Change entry 0 Old
0.value=Welcome to Windchill ProjectLink,

New
0.value=<Your welcome message>

2. Modify <Windchill>/src/com/ptc/netmarkets/util/utilResource.rbInfo (and/or any of the other language versions) in a text editor. Change entries 4,5,14,15. There are a few other candidates in this file if one was to make a total conversion. Old
4.value=Powered by <A HREF=http:// www.ptc.com/products/windchill/index.htm>Windchill</a> <sup>&reg;</sup> 5.value=About Windchill ProjectLink 14.value=Windchill ProjectLink Error 15.value=Windchill ProjectLink Error

New
4.value=<your powered by>

10-2

Windchill Customizers Guide

5.value=<your about label> 14.value=<your generic error text> 15.value=<your generic error text>

3. Compile the changes by executing the following commands in a windchill shell:


ResourceBuild com.ptc.netmarkets.netmarkets.netmarketsResource ResourceBuild com.ptc.netmarkets.util.utilResource

4. Change the icons: Replace <Windchill>/codebase/netmarkets/images/ptclogo.gif with a different image Replace <Windchill>/codebase/netmarkets/images/linklogo.gif with a different image 5. Change the <Windchill>/codebase/presentation.properties Change all of the following to appropriate values. It affects the title on the browser, the cssFiles could be used to plug in more style sheets without replacing the current one:
netmarkets.presentation.website=http\://www.ptc.com netmarkets.presentation.author=PTC netmarkets.presentation.cssFiles=

The colors of JSP clients are derived primarily from the style sheet <Windchill>/codebase/netmarkets/css/nmstyles.css. See the style sheet for more information.

Logos
To override the logo, add a custom css file that overrides the logo styles:
/**** Application Logos for the header area */ .applLogo {background-repeat: no-repeat; height: 55px; background-position:34px;} .wncApplLogo {background-image: url(../../netmarkets/images/logoWC.gif);} .pjlApplLogo {background-image: url(../../netmarkets/images/logoPJL.gif);} .pdmlApplLogo {background-image: url(../../netmarkets/images/logoPDML.gif);} .proIApplLogo {background-image: url(../../netmarkets/images/logoPROI.gif);} .atcmApplLogo {background-image: url(../../netmarkets/images/logoATCM.gif);} /****/

Customizing HTML Clients Using the Windchill JSP Framework

10-3

Customizing the UI with Ajax


Objective
Explain and give examples of how to implement an Ajax UI component. Also gives detailed explanation of Ajax capabilities and overview to the Ajax infrastructure Problem: You would like to make an action to be ajax based to make the action faster and more usable. Problem: You would like a portion of the page to dynamically refresh when some event occurs.

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 update the majority of the page like most of the rows of a table. Ajax actions only update the row of the table, or refresh the whole table, that the action was invoked on. The rest of the page and table are unchanged when the action is complete.

Scope/Applicability/Assumptions
Assume you have an action that updates an object and refreshes the parent page when complete and an action that updates all the rows of a table.

Intended Outcome
The result of applying this pattern is that instead of the page refreshing, the row is updated in-line and highlighted in yellow in the first case, and the second case the table fades out and refreshes itself without refreshing the rest of the tables and navigation on the page.

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

10-4

Windchill Customizers Guide

Solution Elements
Element <your actions>.xml <your>formProcessor.java <your wizard step>.jsp Type XML Java Jsp Description Xml file that contains the action definitions Delegate that performs the db transaction Jsp to partially refresh in a wizard

Refresh a row in a table


In the <your actions>.xml, specify the ajax attribute to have value of row
<action name="<your action>" ajax="row"> <command class="> </action>

In the <your>formProcessor.java file, override the setResultNextAction method to return some dynamic refresh Info:
protected FormResult setResultNextAction(FormResult result, NmCommandBean cb) throws WTException{ DynamicRefreshInfo di = new DynamicRefreshInfo(newOid,oid,NmCommandBean.DYNAMIC_UPD) ; result.addDynamicRefreshInfo(di); result.setNextAction(FormResultAction.REFRESH_OPENER); return result; }

Many examples exist, search actions.xml for ajax=row or the processors for the addDynamicrefreshInfo.

Refresh the whole table


To get the whole table to refresh when the action completes, specify the ajax type to be component.
<action name="<your action>" ajax="component"> <command class="> </action>

Third Level Navigation


To get the whole Third level navigation section to refresh when the action completes, specify the ajax type to be thirdLevelNav.
<action name="<your action>" ajax=" thirdLevelNav"> <command class="> </action>

Refresh a partial page, typically in a wizard step


This can be done with a javascript call to refreshDivTag that will bind an ajax call to the on change event of a field. The jsp needs to have a <div> tag wrapped around it and it should include begin.jspf and end.jspf.

Customizing HTML Clients Using the Windchill JSP Framework

10-5

Finally you should have this javascript block in your JSP that need to be refreshed.
<script type=text/javascript> refreshDivTag ('id of div tag', 'id of object to listen to event on', 'url to the page'); </script>

Example:
refreshDivTag ('sourceContextDropDown', 'myContextPicker', '/netmarkets/jsp/folder/sourceFoldersDropDown.jsp');

Examples: codebase\netmarkets\jsp\folder\sourceFoldersDropDown.jsp

Sample Code
Examples of usage in out-of-the-box code.

Packaged samples

Picture of part 1 of the interaction when a popup action dynamically updates the page. The popup action is completed and calls to refresh the opener window.

10-6

Windchill Customizers Guide

Picture of interaction when a popup action dynamically updates the page when a dynamic popup action completes.

Customizing HTML Clients Using the Windchill JSP Framework

10-7

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

Intended Outcome
By following these procedures you should be able to add or modify the checkin and checkout actions. Checkout action (no wizard involved)

10-8

Windchill Customizers Guide

Checkout status icon after the object is checked out

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 &

Customizing HTML Clients Using the Windchill JSP Framework

10-9

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" <action name="checkout" <action name="checkout_and_download" <action name="undocheckout" <action name="replace_content" <action name=" checkoutAndEdit " YOUR TYPES ACTIONS XML"/> type="wip"/> type="object"/> type="wip"/> type="object"/> type="wip"/> type="YOUR TYPE FROM

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 then 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\DocumentManagementactionmodels.xml) 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)

10-10

Windchill Customizers Guide

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 Manage Security action and also in the Create Document and Create Part wizards. 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. The feature may be used in two ways: The Manage Security action can be added to the objects action model. The Access Control Component can be included as a step in the objects Create wizard.

Intended Outcome
Manage Security Action

When the Manage Security action is included in an objects action model, the action will available in the objects action list. Note: The visibility of the action may be constrained by profiles defined in the Role Based UI. See the Windchill Business Administrators Guide for more details about profile- and role-based visibility administration.

Customizing HTML Clients Using the Windchill JSP Framework

10-11

Create Wizard

When the component is included in an objects Create wizard it appears as an optional Access Control step in the create process. The Set Access Control step should be the highlighted step in the wizard at this point. It is not being correctly rendered in the current build.

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

Procedure - Adding a Manage Security action to an action model


Include the following in the desired action model in your objects 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"/>

10-12

Windchill Customizers Guide

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\ DevModules\Foundation\src\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</csvdi splayName> <csvdescription>com.ptc.core.security.securityResource:READ</csvde scription> <csvlongDescription>com.ptc.core.security.securityResource:READ</c svlongDescription> <csvdefaultValue>UPDATE</csvdefaultValue> <csvhandler>com.ptc.windchill.enterprise.preference.handler.Choice MultiPreferenceValueHandler:readPermission:HIDE,com.ptc.core.secur ity.securityResource,HIDE:VIEW,com.ptc.core.security.securityResou rce,VIEW:UPDATE,com.ptc.core.security.securityResource,UPDATE</csv handler> </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.

Customizing HTML Clients Using the Windchill JSP Framework

10-13

Sample Code Examples of usage in OOTB code


Manage Security Action in document action model

The Manage Security 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"/> <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"%>

10-14

Windchill Customizers Guide

<%@ 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"/> </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\DevModules\Security\src_web\config\actions\Security-actions.xml defines


<action name="setAccessControlWizStep" id="setAccessControlWizStep" preloadWizardPage="false"> <command class="com.ptc.core.security.forms.UpdatePermissionsFormDelegate" method="" windowType="wizard_step"/> </action>

Customizing HTML Clients Using the Windchill JSP Framework

10-15

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.

10-16

Windchill Customizers Guide

Primary content component in a wizard (object must be a FormatContentHolder)

Secondary attachments component in a wizard (object must be a ContentHolder)

Customizing HTML Clients Using the Windchill JSP Framework

10-17

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 table in a details page (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

10-18

Windchill Customizers Guide

Solution Elements
Element Type Description

attachments.tld

Java tag definition

Defines any common component tags you will need to use the attachments common components. Runtime location: codebase\WEB-INF\tlds\ attachments.tld

AttachmentsDown loadAppletServlet. class

Java file

Servlet that redirects download to the appropriate file for the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

AttachmentsValid ationHelper.class

Java file

Supporting methods for validating various attachments related actions. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

AbstractAttachme ntsSubFormProces sor.class

Java file

General form processing delegate that provides shared attachments functionality to the primary and secondary form processors. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

PrimayAttachment SubFormProcessor .class

Java file

Form processing delegate that attaches primary attachments to the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

Customizing HTML Clients Using the Windchill JSP Framework

10-19

Element

Type

Description

SecondaryAttachm entsSubFormProce ssor.class

Java file

Form processing delegate that attaches secondary attachments to the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

AttachmentsDataU tilityHelper.class

Java file

Supporting methods for 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/>

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. 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.

10-20

Windchill Customizers Guide

<%@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" />

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 objects 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 objects attributes.jsp add the following to get the secondary attachments to show up under the more attributes sub nav of the info page.
<jsp:include page="/netmarkets/jsp/attachments/attachments_table.jsp" flush="true"> <jsp:param name="role" value="SECONDARY" /> </jsp:include>

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" <action name="replace_content" type="wip"/> type="wip"/>

Customizing HTML Clients Using the Windchill JSP Framework

10-21

Customization Points <primaryAttachment> tag attributes


Parameter Default Value Possible Values Req? Description

allowFile allowUrl allowExternal

true true true

True/False True/False True/False

no no no

Allows the Local File option to be displayed. Allows the URL Link option to be displayed. Allows the External Storage option to be displayed. Allows existing primary content to be removed. Displays the optional Comments field. Displays the optional Externally Distributable checkbox. Displays the optional file version, tool version and tool name fields. Displays the optional Authored By and Last Authored fields. Renders the file path specified instead of allowing the user to choose the file. If fixedFileUpload param on this tag and the forceApplet param on the fileSelectionAndUploadA pplet tag are both set this can be used to force the specified file to be uploaded and attached to the object.

allowRemoveP rimaryContent showAttachme ntComments showDistributa ble showOptionalF ileAttributes showAuthoring Information fixedFilePath

true false false

True/False True/False True/False

no no no

false

True/False

no

false

True/False

no

null

Valid file path

no

10-22

Windchill Customizers Guide

<fileSelectionAndUploadApplet> tag attributes


Parameter Default Value Possible Values Req? Description

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, jsps, 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 jsps 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.

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.

Customizing HTML Clients Using the Windchill JSP Framework

10-23

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.

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"> ... <jca:wizardStep action="attributes_step" type="attachments" /> ...

10-24

Windchill Customizers Guide

</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

10-25

Property Panel
Objective
You want to display the attributes of some object as label value pairs. You want the colons to align and the HTML to be section 508 compliant.

Scope/Applicability/Assumptions
This document assumes you are familiar with the configuring and acquiring the data for a JCA table.

Solution
Use the property panel component to display label/value pairs (or label/input field pairs) for an object. Examples:

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving HTML, JSP, JavaScript and Custom taglibs. Overview of JCA tags. JCA Table

10-26

Windchill Customizers Guide

Configuring Data Acquisition, Data Utilities and GUI components

Solution Elements
Element <your_page>.jsp <your>service.properties Type jsp properties Description Your JCA Property Panel implementation jsp file. Data utilities and services are defined here. Run time Location: <Windchill>\ codebase components.tld tld Tags can be defined here. Run time Location: <Windchill>\ codebase\WEB-INF\tlds\

Procedure Using the Property Panel Common Component


Using the JCA property panel is similar to using a JCA table, it just has different tags. For the property panel there are describePropertyPanel, describeProperty and renderPropertyPanel tags that are analogous to the describeTable, describeColumn and renderTable tags respectively. This is used in both Create and View. These tags are defined in components.tld, to use them your jsp should include that taglib:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

Describe the property panel

To describe the property panel use the describePropertyPanel and describeProperty tags. For example:
<jca:describePropertyPanel var="<name of the descriptor>"> <jca:describeProperty id="name" /> <jca:describeProperty id="number" /> <jca:describeProperty id="<attribute name | data utility id | logical form>" /> </jca:describePropertyPanel>

The value for <name of the descriptor> can be any name you wish to assign to your panel. The reporting tool that gives details about what properties are available can be accessed here:
http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/property/propertyReport. jsp

Customizing HTML Clients Using the Windchill JSP Framework

10-27

Acquire the Data for the property panel

To acquire data use the either the getModel or getIeModel tag. 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 data. The value for <name of the descriptor> should be that used in your describePropertyPanel tag.
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. To see more code examples of using the renderPropertyPanel tag look at:
<WT_HOME>/codebase/netmarkets/jsp/carambola/propertyPanel/examples .jsp

To see how the above jsp looks on your system go here:


http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/carambola/propertyPanel/ examples.jsp

Customization Points describePropertyPanel tag attributes


describePropertyPanel describes a Property Panel common component that can be plugged in to JCA getModel or getIeModel tags. Its tag class is com.ptc.core.components.tags.components.DescribePropertyPanelTag and the body content is scriptless.
Parameter var Default Value Possible Values Any.String value Req? Yes Description Name of the exported scoped variable for the property panel descriptor. The type of the variable is com.ptc.core.components.descriptor. ComponentDescriptor.

10-28

Windchill Customizers Guide

Parameter scope

Default Value page

Possible Values Can be: 'page', 'request', 'session' or 'application' (case-insensitive)

Req? No

Description The name of the scope to export the var attribute to.

mode

VIEW

String form of com.ptc.core.ui.resou rces.ComponentType enum: VIEW, CREATE, EDIT, SEARCH

No

Sets the ComponentMode that will be used for validation and for data utilities to determine what kind of GUI component to return.

componentT ype

TABLE

String form of com.ptc.core.ui.resou rces.ComponentType enum: TABLE, WIZARD, WIZARD_TABLE, INFO_ATTRIBUTE S_TABLE, SIMPLE, INFO, PICKER, SEARCH

No

Sets the ComponentType that will be used for validation and for data utilities to determine what kind of GUI component to return.

describeProperty tag attributes


The describeProperty tags are nested as children of the describePropertyPanel tag. Its tag class is com.ptc.core.components.tags.components.DescribePropertyTag and the body content is scriptless. Below are some of the attributes that can be set. For more information see the components.tld.
Parameter id Default Value Possible Values name of an attribute, data utility id or logical attribute Req? Yes Description The identifier for this property descriptor. This is used to look up default properties for the column. If the parent table supports configurable views, then this id is used to look up the view configurations. Name of the exported scoped variable for the property panel descriptor.The type of the variable is com.ptc.core.components.descriptor.C omponentDescriptor.

var

Any String value

Yes

Customizing HTML Clients Using the Windchill JSP Framework

10-29

Parameter label

Default Value -

Possible Values Any String value

Req? No

Description A localized display label for this property. If the label isnt specified, then the infrastructure will attempt to look up a label The name of the scope to export the var attribute to.

scope

page

Can be: "page" , "request", "session" or "application" (case-insensitive). String form of com.ptc.core.ui.res ources.Component Mode enum: VIEW, CREATE, EDIT, SEARCH

No

mode

value inherited from describePropert yPanel tag

No

Sets the ComponentMode that will be used for validation and for data utilities to determine what kind of GUI component to return.

renderPropertyPanel tag attributes


The renderPropertyPanel tag renders a JCA Property Panel. Its tag class is com.ptc.core.components.tags.propertyPanel.RenderPropertyPanelTag and the body content is scriptless. Below are some of the attributes that can be set. For more information see the components.tld.
Parameter model Default Value Possible Values Of type com.ptc.core.comp onents.descriptor.C omponentModel Req? Yes Description The model to render. If there are no child tags just the model is rendered. If there are child tags, then the model is just used as the default model for any addProperty tags that don't specify a model.

Sample Code
There are many ways to use the renderPropertyPanel tag and its child tags to display the ComponentModel that is put into page scope by the getModel tag. To see more code examples of using the renderPropertyPanel tag and its child tags look at:
<WT_HOME>/codebase/netmarkets/jsp/carambola/customization/examples /propertyPanel/examples.jsp

You can see the examples on your system here:

10-30

Windchill Customizers Guide

http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/carambola/customization/ examples/propertyPanel/examples.jsp

Examples of Usage in Windchill Code


<WT_HOME>\codebase\netmarkets\jsp\configuration\ createConfiguration_step.jsp

<jca:describePropertyPanel var="attributeDisplayPanelDescriptor" mode="VIEW"> <jca:describeProperty id="number" label="${base_part_number}" /> <jca:describeProperty id="orgid"/> <jca:describeProperty id="version" label="${base_part_version}" /> <jca:describeProperty id="name" label="${base_part_name}" /> </jca:describePropertyPanel> <jca:describePropertyPanel var="attributeInputPanelDescriptor" mode="CREATE" > <jca:describeProperty id="name" inputRequired="true" label="${part_config_name}" /> <jca:describeProperty id="description" label="${part_config_desc}" /> </jca:describePropertyPanel> <wc:batch> <jca:getModel var="attributeDisplayPanel" descriptor="${attributeDisplayPanelDescriptor}" serviceName="wt.fc.StandardPersistenceManager"

Customizing HTML Clients Using the Windchill JSP Framework

10-31

methodName="refresh"> <jca:addServiceArgument value="${commandBean.primaryOid.oid}" type="wt.fc.ObjectIdentifier" /> </jca:getModel> <jca:getModel var="attributeInputPanel" descriptor="${attributeInputPanelDescriptor}" serviceName="com.ptc.core.components.forms.CreateAndEditModelGette r" methodName="getItemAttributes"> <jca:addServiceArgument value="${attributeInputPanelDescriptor}" 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"/> </jca:getModel> </wc:batch> <jca:renderPropertyPanel> <jca:addPropertyPanel model="${attributeDisplayPanel}"/> <jca:addSeparator/> <jca:addPropertyPanel model="${attributeInputPanel}" /> <w:radioButton propertyLabel="${populate}" name="PopulationType" value="<%=PartConfigurationCommand.POPULATION_BASIC%>" label="${basic}" checked="true" required="true" /> <w:radioButton name="PopulationType" value="<%=PartConfigurationCommand.POPULATION_FULL%>" label="${full}"/> </jca:renderPropertyPanel>

10-32

Windchill Customizers Guide

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.

Customizing HTML Clients Using the Windchill JSP Framework

10-33

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 packageTemplate.xml Type XML Description 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: <WT_HOME>/loadXMLFiles/ packageSharedTeamTemplate.xml XML The XML file that 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 isnt extended. Location: <WT_HOME>/loadXMLFiles/

Procedure - Modifying Domain Structure


The packageTemplate.xml file supports customization of the roles, domain structure, and access control policy rules. Modifying these elements is documented in the appendix of the Windchill Business Administrators Guide. To modify the roles, refer to the projectMember element described in Creating Business XML Files 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. 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 file applies to the entire site which means you can not customize it for specific contexts or specific packages.

10-34

Windchill Customizers Guide

If you change the default domain path, you may have to enable packages again. If the domain already exists in a context, you wont be prompted to enable packages again. If the context is using a shared team that isnt extended, the roles from packageSharedTeamTemplate.xml will be used and the roles from packageTemplate.xml will be ignored.

Sample Code Examples of Usage in Windchill Code


Filename: <WT_HOME>/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> <lifecycleState>ALL</lifecycleState> <WTPrincipalReference isInternal="true"> <groupName>PACKAGE MANAGER</groupName> <groupType>ALL</groupType> </WTPrincipalReference> <grantPermissionSet> <AccessPermissionSet> <permissionField name="ALL"/> </AccessPermissionSet> </grantPermissionSet> </AccessControlRule>

Customizing HTML Clients Using the Windchill JSP Framework

10-35

Additional Resources Other Related Windchill Documentation


Access Control Chapter in the Windchill Business Administrators Guide Team Chapter in the Windchill Business Administrators Guide Creating XML Files for Templates and Shared Teams section in the Windchill Business Administrators Guide

10-36

Windchill Customizers Guide

Generating HTML Tags for ProductView Visualization Within a JSP Page


At the Windchill 6.2 release there is no supported API for generating the HTML tags for ProductView visualization within a JSP page. This TAN documents the support now available. To generate HTML code for the ProductView visualization components in a JSP page, use the com.ptc.wvs.common.ui.VisualizationHelper class. See this class entry in your installed Windchill Javadoc for more information.
public static final String THUMBNAILS_PROP_PAGE_PREF_KEY

Constant defining preferences entry for generating thumbnails on the property page
public static final String DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE

Default value for generating thumbnails on the property page


public String getCreateDialogWindow()

Returns the JavaScript to create the Dialog Window function creationDialogWindow. This should be called once per page. This JavaScript function is used by the HREFs created from getDefaultVisualizationData().
public String[] getDefaultVisualizationData(String representableObjectReference, Boolean forListing, Locale locale)

Returns a set of HTML fragments to allow the default representation to be manipulated by a UI.
public int getIndexOfVisLink(String prefKey, String prefDefault)

Returns the index in the data array returned by getDefaultVisualizationData of the URL to use for launching ProductView.
public int clipboardLinkIndex()

Returns the index of the Add to Clipboard link in the data array returned by getDefaultVisualizationData
public int printLinkIndex()

Returns the index of the Print link in the data array returned by getDefaultVisualizationData
public int viewRepsLinkIndex()

Returns the index of the view representations link in the data array returned by getDefaultVisualizationData
public int[] getThumbnailSize()

Returns the user-preferred thumbnail width and height


public boolean isWVSEnabled()

Returns true if WVS is enabled, otherwise it returns false.

Customizing HTML Clients Using the Windchill JSP Framework

10-37

public static VisualizationHelper newVisualizationHelper()

Default factory for the class.


General flow of logic:

The VisualizationHelper can be instantiated via the newVisualizationHelper() factory method. getCreateDialogWindow() is required to generate the Javascript fragment required by the results returned from getDefaultVisualizationData(String, Boolean, Locale). This code must be embedded somewhere in the HTML returned by the JSP page. getDefaultVisualizationData(String, Boolean, Locale) method returns an array of String values. Each value corresponds to a different component within the ProductView Visualization Service. Elements in the array can be accessed directly through the indexes returned by the following methods: getIndexOfVisLink(String, String), clipboardLinkIndex(), printLinkIndex(), viewRepsLinkIndex(). Each String is the base HTML code for the ProductView visualization component and can be embedded into the HTML returned by the JSP page. It may be an '<A HREF .. /A>' code tag or other simple unformated HTML tags. Note: The getDefaultVisualizationData(String, Boolean, Locale) method returns the basic HTML components necessary for accessing the ProductView visualization components. Most likely the results will need to be used within proper HTML tags. The responsibility of designing the user interface and properly using the values returned by these methods belongs to the implementer. Example usage:
// comp.ptc.wvs.common.ui.VisualizationHelper is assumed to be imported. VisualizationHelper visHelper = newVisualizationHelper(); if (visHelper.isWVSEnabled()) //only execute code if WVS is enabled { // Embed the create dialog JavaScript somewhere in returned HTML. // The below is just an example of calling it. Placement within // HTML is the responsibility of the implementer. out.println(visHelper.getCreateDialogWindow());

//ObjectReference object or and locale object is assumed to be obtained prior to the following line String visData[] = visHelper.getDefaultVisualizationData(or.toString(),new Boolean(false), locale); //Obtain array indices for thumbnail, clipboard link, print link, and representations link int thumbnailIndex = visHelper.getIndexOfVisLink( VisualizationHelper.THUMBNAILS_PROP_PAGE_PREF_KEY, VisualizationHelper.DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE); int clipboardIndex = visHelper.clipboardLinkIndex(); int printIndex = visHelper.printLinkIndex(); int repsOrMarkupsIndex = visHelper.viewRepsLinkIndex(); /**

10-38

Windchill Customizers Guide

* Print the various HTML code fragments generated for each component. * Any HTML formatting code must be wrapped around each of the following lines **/ out.println(visData[thumbnailIndex]); out.println(visData[clipboardIndex]); out.println(visData[printIndex]); out.println(visData[repsOrMarkupsIndex]); }

Customizing HTML Clients Using the Windchill JSP Framework

10-39

Tools Overview
This section contains the following information: Available Attributes Report Debugging Taglib documentation Action Report Action Model Report

Available Attributes Report


To find the list of supported attributes for a given object type (eg: wt.part.WTpart), you can use the Available Attributes Report that can be accessed from a running Windchill installation. The report includes information about the attribute such as the id used to reference the attribute in your JSPs and the label used for that attribute in the UI. The data utility mapped to that component is also listed.

http://<machine_name>/<app_name>/netmarkets/jsp/carambola/createta bleview/availableAttributesReport.jsp

10-40

Windchill Customizers Guide

Debugging
There is a debug mode that can be enabled in the UI that can help track down information about a particular action on a page. The jcaDebug tool is a display parameter that can be added to any URL to add debug info to the current page inline with the items in the page. The debug tool can: debug what class is handling data that gets displayed in a table cell shows what kind of component is rendering the cell data shows what class is responsible for hiding/enabling/disabling an action

Enable jcaDebug
To enable the JCA debug feature add the following to the end of any url, that is JCA:
&jcaDebug=true

For example:
<servername>/Windchill/servlet/TypeBasedIncludeServlet?Containe rOid=OR%3Awt.pdmlink.PDMLinkProduct%3A4462&oid=VR%3Awt.part.WTP art%3A5142&u8=1&jcaDebug=true

Action Tool Tips


If you perform a mouse over on an action, the following tooltip displays.

The tool tip displays the following information:


Attribute Description

Display Name Action Name

Displays the name of the action. Displays the action type separated by a period and the action name. The Action Name is also a hyperlink to the action details page. Displays the action model name. The Action Model Name is also a hyperlink to the action model details page.

Action Model Name

Customizing HTML Clients Using the Windchill JSP Framework

10-41

Attribute

Description

Validator Validator Status

Displays the validator. Displays the status of the validator.

Table Cell Tooltips


The Table Cell objects have an icon (red lady bug), that you can mouse over to display the following tooltip.

The tool tip displays the following information


Attribute Description

Data Utility GUI Type Column ID Row Object

Displays the data utility. Displays the GUI type. Displays the ID used to look up the customizable delegates. Displays the object passed into the data utility that the table cell is displaying info about.

Taglib documentation
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. Refer to the taglib javadoc at the following location: http://www.ptc.com/view?im_dbkey=61784

10-42

Windchill Customizers Guide

Action Report
We support modularized actions and actionmodels within the system, so to find what file an action is defined in, there is a reporting tool that can be used. On a running Windchill installation, you can use the Actions report. The Action Report is a search page that returns the details of actions matching the search criteria. 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 (aka Description), action name, object type. The search supports multiple search parameters, regular expressions and caseinsensitive matching.

Location
http://<your machine name>/<appname>netmarkets/jsp/carambola/tools/actionReport/action.jsp

Search Supports
Multiple search parameters Regular expressions Case-insensitive matching

Customizing HTML Clients Using the Windchill JSP Framework

10-43

Action Details Page

If there is no information for the particular action, the line is shown blank.

Search Examples
Description

remove ==> Matches: "remove", "list_delete", "related_delete_described_part", etc.

Action Name
remov.* ==> Matches: "remove", "remove_deliverable", "removeUses", etc. r[a-z]* ==> Matches: "reply", "REVISEITEMS", "reassignLC", etc.

10-44

Windchill Customizers Guide


Hot Keys

.*move ==> Matches: "remove", "CONTAINERMOVE", "WFMOVE", etc. .* ==> Matches: everything

m ==> Matches: "home" .* ==> Matches: "home", "productStructure", "documentStructure", etc.


Action Model File/Action Definition File

only files under \codebase\ search matches files under "\config\actions\" with specifying it Note: Some matches may be deceiving due to include tags in xml files

Known Bugs
Opposite facing slashes in file paths On Details Page Definition file: Z:\\Windchill\codebase\config/actions/RelContextactions.xml In Details Table

In Internet Explorer When pressing the back button from the Details Page, you are given:

Customizing HTML Clients Using the Windchill JSP Framework

10-45

Then, when refreshing this page, you get the alert:

Clicking retry will correctly refresh this page.

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.

10-46

Windchill Customizers Guide

Action Model Report


We support modularized actions and actionmodels within the system, so to find what action models the action is used in, there is a reporting tool that can be used. On a running Windchill installation, you can use the ActionModels report. 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.

Location
The Action Model Report is available at the following location: http://<your machine name>/<appname>/netmarkets/jsp/carambola/tools/actionReport/actionModel.jsp

Search Supports
Multiple search parameters Regular expressions case-insensitive matching

Search Examples
Returns action models depending on search:

(all examples below are the action model names returned)

Customizing HTML Clients Using the Windchill JSP Framework

10-47

Action Model Details Page

If there is no information for the attribute of a particular action model, the line is shown blank.
Action Model


Model File

Default.* ==> Matches: "DefaultWizardButtons", "DefaultWizardButtons", etc. .*actions ==> Matches: "dti actions", "bookmark actions", "workitem actions", etc. [a-z]*s ==> Matches: "ScmiWizardButtons", "relatedItems", "EditWizardButtons", etc. .* ==> Matches: everything

only files under \codebase\ search matches files under "\config\actions\" without having to specify it

10-48

Windchill Customizers Guide

Note: Some matches may be deceiving due to include tags in xml files.

Action Model Details

Description for this Model


This represents the comments for an action model. When a "description" tag is used in an actionmodel xml file, the information in the tag is then saved and displayed.

Order in Table
This shows the order of the actions within an actionmodel xml file.

Known Bugs
In Internet Explorer

When pressing the back button from the Details Page, you are given:

Then, when refreshing this page, you get the alert:

Customizing HTML Clients Using the Windchill JSP Framework

10-49

Clicking retry will correctly refresh this page.


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 what you are looking for.

10-50

Windchill Customizers Guide

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 design pattern outlines the process and best practices for authoring Validator classes.

Applicability
This design pattern 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 design pattern 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. Their source code is located in \ Windchill\src\com\ptc\core\ui\validation. 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. 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.

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.

Customizing HTML Clients Using the Windchill JSP Framework

10-51

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 methods 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 { } }

10-52

Windchill Customizers Guide

Consequences
By using this design pattern 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.

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.

Customizing HTML Clients Using the Windchill JSP Framework

10-53

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 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 design pattern 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.

10-54

Windchill Customizers Guide

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, youll 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() 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 teams 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/<vali daitonKey>/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

Customizing HTML Clients Using the Windchill JSP Framework

10-55

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 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);

10-56

Windchill Customizers 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

10-57

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 theyve 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: 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?

10-58

Windchill Customizers Guide

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(); 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

Customizing HTML Clients Using the Windchill JSP Framework

10-59

(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, its important to note that in practice its 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 prevalidation all the time).

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 import import import java.lang.ClassNotFoundException; java.util.ArrayList; java.util.Iterator; java.util.Locale;

import org.apache.log4j.Logger; import import import import import wt.access.AccessPermission; wt.access.AccessControlHelper; wt.epm.workspaces.EPMWorkspaceHelper; wt.fc.Persistable; wt.fc.ReferenceFactory;

10-60

Windchill Customizers Guide

import import import import import import import import import import import import import import import import import import import

wt.fc.WTReference; wt.fc.collections.WTArrayList; wt.fc.collections.WTCollection; wt.folder.CabinetBased; wt.folder.CabinetMember; wt.folder.Foldered; wt.folder.FolderHelper; wt.inf.container.WTContained; wt.inf.container.WTContainerHelper; wt.log4j.LogR; wt.org.WTUser; wt.sandbox.SandboxHelper; wt.session.SessionHelper; wt.util.WTException; wt.vc.Iterated; wt.vc.VersionControlHelper; wt.vc.wip.Workable; wt.vc.wip.WorkInProgressHelper; wt.vc.wip.WorkInProgressState;

public class DefaultWIPValidator extends DefaultUIComponentValidator { private Logger logger = LogR.getLogger("wt.method.server.httpgw"); private ReferenceFactoryrefFactory = 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 <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

10-61

{ logger.debug("ENTERING DefaultWIPValidator.performLimitedPreValidation"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toString()); UIValidationResultSet resultSet = performWIPValidation(validationKey, validationCriteria, locale, LIMITED); logger.trace("RETURNING " + resultSet.toString()); logger.debug("EXITING DefaultWIPValidator.performLimitedPreValidation"); return resultSet; }

public UIValidationResultSet performFullPreValidation (String validationKey, UIValidationCriteria validationCriteria, Locale locale) 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 validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { logger.debug("ENTERING DefaultWIPValidator.validateSelectedAction"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toString()); UIValidationResult result = null; WTReference wtRef = validationCriteria.getContextObject(); Persistable persistable = wtRef.getObject(); if (!(persistable instanceof Workable)){ return new UIValidationResult(validationKey, wtRef, UIValidationStatus.DENIED, null); } Workable workable = (Workable)persistable; if (validationKey.equalsIgnoreCase("checkin") || validationKey.equalsIgnoreCase("undocheckout")){ result = performCheckinValidation(validationKey, workable, SELECTED, (WTUser)(validationCriteria.getUser().getPrincipal())); } else if (validationKey.equalsIgnoreCase("checkout")){ result = performCheckoutValidation(validationKey, workable, SELECTED);

10-62

Windchill Customizers Guide

} 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.validateSelectedMultiSelectAction"); 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.getTargetObjects()); Iterator workableIter = getWorkableIterator(targetObjects); Workable workable = null; while (workableIter.hasNext()){ workable = (Workable)workableIter.next(); if (validationKey.equalsIgnoreCase("checkin") || validationKey.equalsIgnoreCase("undocheckout")){ resultSet.addResult(performCheckinValidation(validationKey, workable, validationType, (WTUser)(validationCriteria.getUser().getPrincipal()))); } else if (validationKey.equalsIgnoreCase("checkout")){

Customizing HTML Clients Using the Windchill JSP Framework

10-63

resultSet.addResult(performCheckoutValidation(validationKey, workable, validationType)); } } resultSet.appendResults(processNonWorkables(targetObjects, validationKey, validationType)); return resultSet; }

private UIValidationResult performCheckinValidation(String validationKey, Workable workable, String validationType, WTUser user) 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, UIValidationStatus.ENABLED, null); } else{ return new UIValidationResult(validationKey, wtRef, UIValidationStatus.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); } }

10-64

Windchill Customizers Guide

if (WorkInProgressHelper.isCheckedOut(workable, user) || (WorkInProgressHelper.isCheckedOut(workable) && WTContainerHelper.service.isAdministrator(((WTContained)workable).getContainerRefer ence(), 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(WorkInProgressState.CHECKED_OUT_TO_SANDBOX)){ return new UIValidationResult(validationKey, wtRef, UIValidationStatus.DISABLED, null); } else{ return new UIValidationResult(validationKey, wtRef, UIValidationStatus.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; } if (isNewInWorkspace(workable)){ return new UIValidationResult(validationKey, wtRef, badStatus, null); }

Customizing HTML Clients Using the Windchill JSP Framework

10-65

if ((AccessControlHelper.manager.hasAccess(workable, AccessPermission.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, UIValidationStatus.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; } }

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; } }

10-66

Windchill Customizers Guide

} 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; } }

Known Uses
This design pattern should be used by any developer responsible for writing a Validator for an action or UI component.

Customizing HTML Clients Using the Windchill JSP Framework

10-67

10-68

Windchill Customizers Guide

11
Adding Actions and Hooking Them Up in the UI

This chapter describes how to customize actions and add them to the user interface. Topic Page

Windchill Client Architecture Action Framework Overview .......................... 11-2 Tab Models..................................................................................................... 11-16 Action Visibility ............................................................................................. 11-27 Navigation Stickiness ..................................................................................... 11-36

11-1

Windchill Client Architecture Action Framework Overview


Objective
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.

Background
The action framework for the Windchill client architecture supports the ability to configure new actions and action models in the system.

Scope/Applicability/Assumptions
This section describes the action framework for the Windchill Client Architecture. It does not include information on how to control the display of the action.

Intended Outcome
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.

Solutions
Define a new action and add it to an action model. Define a new action model to the system. Remove an action from an action model.

Prerequisite knowledge
XML file structures

Solution Elements

Element

Type

Description

StandardNmActionService (and corresponding helper and forwarder)

.java

The StandardNmActionService manages the actions and actionmodels in the system. Run time Location: <Windchill>\codebase\com\ptc\netmarkets\util\misc

11-2

Windchill Customizers Guide

Element

Type

Description

actions.xml

.xml

Default system xml file for defining actions in the system. Run time Location: <Windchill>\codebase\config\actions

actionmodels.xml

*.xml

Default system xml file for defining action models ins the system. Run time Location: <Windchill>\codebase\config\actions

actions.dtd

.xml

Default system dtd file for defining structure of an actions*.xml Run time Location: <Windchill>\codebase\config\actions

actionmodels.dtd

*.xml

Default system dtd file for defining structure of an actionsmodels*.xml Run time Location: <Windchill>\codebase\config\actions

The action framework provides a way to define actions and action models within the system. A service, called the StandardNmActionService manages the set of actions and action models in the system. Actions and action models are defined via xml files referred to as actions*.xml and actionmodels*.xml. There is one default actions.xml and actionmodels.xml file that is delivered with the system. However, each functional area may also have its own xml file as well which is also managed by the action service. For customization purposes, a customactions.xml and custom-actionmodels.xml is delivered with the product and are found in codebase/config/actions relative to the Windchill installation directory. All other out of the box actions.xml and actionmodels.xml files are also located in <windchill-install-dir>/codebase/config/actions. The default actions.xml and actionmodels.xml files contain commonly used actions, such as copy, cut, and commonly used action models such as wizard buttons. Additional actions*.xml and actionmodels*.xml files contain actions. and action models related to their functional areas. (e.g. ChangeManagement-actions.xml contains actions related to change management, PartManagement-actions.xml contains actions related to part management). In general, as a developer you would not have to directly make calls to the StandardNmActionService. These calls are done via the components that support display of actions and action models, for example tables, trees, information pages.

Adding Actions and Hooking Them Up in the UI

11-3

For details about how to configure the action model to use for a component, see related sections: See the Constructing Wizards chapter beginning on page 14-1 for more detailed information on wizards See the information on tables and trees in the Presenting Information in the UI chapter beginning on page 13-1 See the information in the Information Pages chapter beginning on page 15-1

Procedure 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 the codebase/config/actions/actions.dtd. Here is an example of an action definition for the New Document wizard.
<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>

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.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. We recommend that all your objecttypes have a prefix specific to your company to prevent collisions with object types delivered with the product.
Possible Object Type Attributes

The table below describes the valid parameters for a objecttype. Details about these parameters can also be found in the codebase/config/actions/actions.dtd.
Default Value n/a Possible Values any combination of alpha-numeric characters

Parameter name

Req? Yes

Description The name used to reference this objecttype

11-4

Windchill Customizers Guide

Parameter class resourceBundle

Default Value n/a n/a

Possible Values A valid java class Any valid resource bundle class name

Req? Yes No

Description Object class for the enclosed actions Class name for the default resource bundle to use for the properties of the actions that are to be localized

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 objecttype. The packaging is relative to codebase/netmarkets/jsp. For example, the action name in the xml above, called create, within the objecttype of document has a jsp in codebase/netmarkets/jsp/document called create.jsp. Naming conventions for the name of an action can be any combination of alphanumeric characters. We recommend that all your actions have a prefix specific to your company to prevent collisions with names of actions delivered with the product.
Possible Action Attributes

The table below describes the valid parameters for a action. Details about these parameters can also be found in the codebase/config/actions/actions.dtd.
Possible values all Page Component Row thirdLevelNav popupMenu

Parameter name ajax

Default Value n/a n/a

Req? Yes No

Description This is the name by which the action will be referenced Specifies the scope of the AJAX refresh

ajaxActionClass cad enabledwhensusp ended installType

n/a false false n/a true true WINDCHILL PDM PDM PJL PDM

No No No No

The jsp that is requested via ajax Indicates if this action is only valid within the Wildfire embedded browser Enabled when the project is suspended/cancelled/completed Applicable actions based on the installed components. This is for legacy purposes only.

Adding Actions and Hooking Them Up in the UI

11-5

Parameter multiselect selectRequired

Default Value false false

Possible values false / true false / true

Req? No No

Description Used to indicate that multi-selection of row data can be used for this action. Determines if the UI should allow the action to proceed if nothing has been selected. Results in "Nothing Selected" popup JS function name to invoke on client side validation for a wizard step after the step is completed. JS function name to invoke client side validation for a wizard step when the step is loaded Server validator name to invoke client side validation for a wizard step after it is finished. Server validator name to invoke client side validation for a wizard step when the step is loaded. Overrides the id of the wizard step (default is objecttype.action) Specifies that the wizard step is to be downloaded when the wizard is launched A wizard step to be hidden first, or that an action is rendered as non-clickable Used for an wizard action that represents a step in the wizard. Specifies the wizard step is required. Class name for the resource bundle to use for the properties of the actions that are to be localized

afterJS

n/a

No

beforeJS

n/a

No

afterVK

n/a

No

beforeVK

n/a

No

id preloadWizardPa ge hidden required

objecttype.actio n true false false false / true false / true false / true

No No No No

resourceBundle

No

11-6

Windchill Customizers Guide

Parameter renderType

Default Value

Possible values PDM

Req? No

Description Default: http://<host>/<webapp> General: http://<host>/<webapp><command.meth od> General with context: http://<host>/<webapp><command.meth od>?oid=... PDM: url generated by URLactionDelegate; used for template processing or DCA

uicomponent preloadJS

No No

References entry n roleaccessprefs.xml (uic.name) to specify role-based access. The javascript function executed executed before a wizard step is loaded or displayed. The javascript function is executed after a wizard step is loaded into memory, but before it is displayed to the user.

postloadJS

No

If necessary, place a <command> tag in the body of the <action> tag to define the processing aspects of the action.
<command class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcess or" method="execute" windowType="popup" onClick="validateCreateLocation(event)"/>

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 a Wizard so the windowType is popup. The framework will add javascript that launches this action in a new window. The specified class and method are executed upon submit of the wizard.

Adding Actions and Hooking Them Up in the UI

11-7

Possible Command Attributes Parameter class method url onClick Default Value n/a n/a n/a n/a Possible Values Req? No No No No Description The class to handle post The method in the class to execute and handle post Used to override the generated url Specified an additional onclick function to call. Useful for confirming with the user whether to execute a special action New: like a popup, except includes a browser bar no_content: no window action normal: default, submit the form wizard_step: display the action as a wizard step page: display a new page popup: create a non-modal popup dialog, typically a wizard. Sets come form of data Possible NonSupportedType Attributes Parameter value Default Value n/a Possible Values Any object types. It can be comma separated. Req? Yes Description This action will be disabled for the object type/s mentioned in the "Possible values". Actions will be disabled in Third Level Navigation, Row Level action. No filtering will be done for MenuBar and Table Tool Bar actions.

windowType

page

New no_content normal page popup wizard_step

No

11-8

Windchill Customizers Guide

Possible SupportedType Attributes Parameter value Default Value n/a Possible Values Any object types. It can be comma separated. Req? Yes Description This action will be enabled only for the objecttype/s mentioned in the "Possible values". Actions will be enabled in Third Level Navigation, Row Level action. No filtering will be done for MenuBar and Table Tool Bar actions.

By specifying SupportedTypeAttribute or NonSupportedTypeAttribute, ActionFramework will either enable or disable the Actions depending upon the object types mentioned. This filtering will be applied only for Third Level Navigation and Row Level Actions. Also this will be carried out before calling any other Filtering ( Validation service ) class defined by application developers. In short it is a UniversalFilter. If an action is disabled by this Universal Filter, Custom Validators written will not get executed. If an action is enabled by this Universal Filter, Custom Validators will get invoked. 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 do it as:<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>

Procedure - Localizing an action


To have the localized properties for your action you would use rbinfo files. For more information see the Resource Info (.rbInfo) Files section of the Internationalization and Localization chapter on page 39-8. The format for the entries in the rbinfo files for actions is:

Adding Actions and Hooking Them Up in the UI

11-9

<objecttype name>.<action name>.<purpose>.value=<value>

Element objecttype name action name purpose

Possible Values all all title description tooltip icon morurlinfo hotkey

Description Corresponds to the name of the objecttype specified in the actions.xml file. Corresponds to the name of the action specified in the actions.xml file. title: localizable text for the title bar if the action is for a wizard description: the localizable text for the label of the action tooltip: the localizable text shown on mouse over of the action icon: image file, relative to codebase/netmarkets/images moreurlinfo: parameters used to size the window for this action hotkey: the alphanumeric key to trigger this action.

value

all

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 shown here:

11-10

Windchill Customizers Guide

title shown here:

icon and description shown here:

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 will be used.

Procedure Defining a new action model


Action models are defined in an xml file that follows the structure based on the 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" <action name="list_copy" <action name="fbpaste" <action name="pasteAsCopy" <action name="list_paste_sharing" <action name="list_delete" <action name="CONTAINERMOVE" <action name="PAGERELOADINGMULTICHECKOUT" <action name="WFADDTOWORKSPACE" <action name="separator" <action name="create" <action name="create_share_folder" <action name="create" <action name="create_shared_doc" <action name="createMulti" <action name="createFromTemplateWizard" <action name="createPartWizard" <action name="createMultiPart"

type="object"/> type="object"/> type="object"/> type="saveas"/> type="folder"/> type="object"/> type="pdmObject"/> type="folder"/> type="folder"/> type="separator"/> type="folder"/> type="folder"/> type="document"/> type="document"/> type="document"/> type="document"/> type="part"/> type="part"/>

Adding Actions and Hooking Them Up in the UI

11-11

<action <action <action <action <action <action </model>

name="add_link" name="create" name="create" name="create" name="SBUpdatePrj" name="separator"

type="bookmark"/> type="problemReport"/> type="changeRequest"/> type="changeNotice"/> type="sandbox"/> type="separator"/>

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.WTDocuments.
Possible Model Attributes

Details about these parameters can also be found in the codebase/config/actions/actionsmodels.dtd.


Parameter name menufor Default Value n/a n/a Possible values all Any valid class name. Req? Yes No Description This is the name by which the action model will be referenced Specifies which action should be highlighted by default. This is only applicable if the model is used as a third level nav bar Specifies which action should be highlighted by default. This is only applicable if the model is used as a third level navigation bar.

defaultActionNa me

First action in the model is used by default First action in the model is used by default

Action name for one of the actions in the model. Object type of one of the actions in the model.

defaultActionTy pe resourceBundle

Class name for the resource bundle to use for the properties of the action models that are to be localized

Possible Action Attributes

Details about these parameters can also be found in the codebase/config/actions/actionsmodels.dtd.


Parameter name Default Value n/a Possible values Name of any action defined in an actions.xml file Req? Yes Description This is the name of an action defined in an actions.xml file

11-12

Windchill Customizers Guide

Parameter type

Default Value n/a

Possible values Name of any objectype defined in an actions.xml file

Req? Yes

Description This is the name of an objectype defined in an actions.xml file.

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.
Possible SubModel Attributes

Details about these parameters can also be found in the codebase/config/actions/actionsmodels.dtd.


Parameter name Default Value n/a Possible Values Name of any action model defined in an actionmodels.xml file Req? Yes Description This is the name of an action model defined in an actionmodels.xml file. An example of where an action model with submodels is used is for the File menu on the Folders table.

Procedure Adding validation logic for your action


When creating a new action, there may be logic that you want executed to determine if that action should be enabled, disabled, or hidden in the UI. You can write this logic in a class called a validator. See the section on UI Validation for details about the validation service, writing a validator, and registering the validator for your action. See UI Validation on page 13-109 for more information.

Procedure Localizing an actionmodel


Some action models need display label (e.g. 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, as noted in Procedure Localizing an action on page 11-9.
object.relatedItems.description.value=<U class='mnemonic'>R</U>elated Objects

Adding Actions and Hooking Them Up in the UI

11-13

object.relatedItems.description.comment=Used for the text on the Related Objects third level navigation menu. The <U class=mnemonic> </U> tag should be put around the character that is the access key. object.relatedItems.hotkey.value=r object.relatedItems.hotkey.comment=Mnemonic for the Related Objects third level navigation menu. This should be a character that matches the character surrounded by the <U class=mnemonic> </U> tag in the value line above.

Procedure Reporting tools for actions and actionmodels.

We support 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. On a running Windchill installation, you can use the Actions and ActionModels reports. See the Tools Overview section in the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-40 for information on the Action Report and the Action Models Report.

Customization Points
As mentioned earlier in Solution Elements section on page 11-2, there are two files, custom-actions.xml and custom-actionmodels.xml, that are delivered with the product. If you want to add/modify an action/actionmodel you can put the changes in these files. It is important to note that if you have an <objecttype> element in the customactions.xml file, and that type exists within another actions.xml file, the actions from your file will be added to the full set of actions supported for that type. This custom-actions.xml is read in last of all the actions.xml files, so if action names are duplicated, the one in this file will be used. It is also important to note that if you have a <model> element in the customactionmodels.xml file, and a model by that name already exists, your model will completely wipe out the ones read in before yours. Be very careful in the naming of your models so that you don't wipe out others from files read in before yours unless that is the intent.

11-14

Windchill Customizers Guide

Sample Code Action Model - configurtion for a soft type


This is an example of a action model configuration for a soft type.
<!-- 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>

Where org.default.www.SampleChangeRequest is the Name of the soft type entered in the Type Manager.

Adding Actions and Hooking Them Up in the UI

11-15

Tab Models
Objective
You want to change something in the header section of the page. Examples: Add and remove tabs or sub tabs, Change logo, change other styles.

Background
The tabs and sub tabs rendered in the header area are actions in action lists just like any other actions in the system. The action lists are being displayed by a special tag that knows how to render them as tabs and sub tabs instead of rendering them in any of the other formats found throughout the system. Adding tabs and sub tabs is very much like adding any other action into the system, but there are some additional special consideration. The look and feel of the header and footer areas is controlled by CSS classes in nmstyles.css. A detailed list of the styles used and a description of their purpose is provided in this document in the Procedure - Changing the header or footer look and feel section on page 11-21.
Scope/Applicability/Assumptions

Assume you need to change the look and feel of Windchill to conform to your company's branding. Assume you need to add a new tab or sub tab to the main navigation of the product. Assume you need to remove an existing tab or sub tab from the main navigation of the product.

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, Windchill Client Architecture Action Framework Overview on page 11-2.

The management of RBINFO file customizations. For more information see, Procedure - Localizing an action on page 11-9.

11-16

Windchill Customizers Guide

Solution Elements Element codebase\config\actions\ navigation-actions.xml codebase\config\actions\ nigation-actionModels.xml Type XML Description This file contains the action definitions for the actions that represent the tabs and sub tabs in the Windchill system This file contains the action model definitions used in the navigation. Including the main tab list, the sub tab list, the recent lists, and the header actions lists. Preferences files This file contains the style classes used to create the look and feel of the Windchill header and footer. 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.

XML

codebase\action.properties or an rbinfo file. codebase\netmarkets\css\ nmstyles.css <mytab>/<list>.jsp

rbinfo CSS

JSP

Procedure - Adding a Main Tab


The process of adding a main tab consists of the following steps: Create an action in navigation-actions.xml Add your action to the main navigation action model in navigationactionModels.xml Create an entry in action.properties or an rbinfo file Create a new sub tab model for your tab in navigation-actionModels.xml Create a new stickiness Preference and load it into the Database Add a Sub Tab

Create an action in navigation-actions.xml

Create an action for your new tab in navigation-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>

Adding Actions and Hooking Them Up in the UI

11-17

Add your action to the main navigation action model in navigation-actionModels.xml

To get your main tab to show up you will need to add it to the action model for the main tabs. My new tab is shown in bold below:
<!-- 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"/> </model>

Create an entry in action.properties or an rbinfo file

Create localization strings for your action in action.properties or your own rbInfo file. For more information see, Procedure - Localizing an action on page 11-9.
Create a new sub tab model for your tab in navigation-actionModels.xml

Your new tab will need a sub tab model. In order for the navigation to find the subtab model it must be named after the main tab that it belongs to. For sub tab 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 subtabs to your new action model. You must create at least one sub tab whose name and type match the defaults specified in the action model tag.
Create a new stickiness Preference and load it into the Database

Your preferences should be named <tabName>stickyAction and <tabName>StickyType. So for this example they are mytabStickyAction and mytabStickyType. Here is a complete xml examples for the two preferences for mytab.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader> <csvPreferenceDefinition handler="wt.preference.LoadPreference.createPreferenceDefinition"> <csvname>mytabStickyAction</csvname> <csvvisibility>HIDDEN</csvvisibility> <csvcategoryName>DISPLAY_CATEGORY</csvcategoryName> <csvdisplayName>wt.preference.preferenceResource:UNASSIGNED_WIT

11-18

Windchill Customizers Guide

H_NAME</csvdisplayName> <csvdescription>wt.preference.preferenceResource:UNASSIGNED_WIT H_NAME</csvdescription> <csvlongDescription>wt.preference.preferenceResource:UNASSIGNED _WITH_NAME</csvlongDescription> <csvdefaultValue/> <csvhandler>com.ptc.windchill.enterprise.preference.handler.Str ingPreferenceValueHandler:</csvhandler> </csvPreferenceDefinition> <csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.setClientDefinitionLink"> <csvname>mytabStickyAction</csvname> <csvclientName>WINDCHILL</csvclientName> </csvLinkPreferenceClientDefinition> <csvPreferenceDefinition handler="wt.preference.LoadPreference.createPreferenceDefinition"> <csvname>mytabStickyOid</csvname> <csvvisibility>HIDDEN</csvvisibility> <csvcategoryName>DISPLAY_CATEGORY</csvcategoryName> <csvdisplayName>wt.preference.preferenceResource:UNASSIGNED_WIT H_NAME</csvdisplayName> <csvdescription>wt.preference.preferenceResource:UNASSIGNED_WIT H_NAME</csvdescription> <csvlongDescription>wt.preference.preferenceResource:UNASSIGNED _WITH_NAME</csvlongDescription> <csvdefaultValue/> <csvhandler>com.ptc.windchill.enterprise.preference.handler.Str ingPreferenceValueHandler:</csvhandler> </csvPreferenceDefinition> <csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.setClientDefinitionLink"> <csvname>homeStickyOid</csvname> <csvclientName>WINDCHILL</csvclientName> </csvLinkPreferenceClientDefinition> </NmLoader>

Add a Sub Tab

This step consists of multiple sub steps and can be repeated as many times as needed. The process of adding a main tab consists of the following steps:
Create the JSP

Create the JSP Create an action in navigation-actions.xml Create an entry in action.properties or an rbinfo file Add your action to the action list in navigation-actionModels.xml

In order to ensure that the correct main tab is selected properly, you must create your JSP in a package named after that tab. In our example I will create my list.jsp in the following path: codebase\netmarkets\jsp\mytab\list.jsp

Adding Actions and Hooking Them Up in the UI

11-19

This will ensure that mytab is selected when the user is viewing this JSP. Example JSP content:
<!-- Import the navigationRB file that contains the constant for the page title. --> <%@page import="com.ptc.core.ui.navigationRB" %> <!-- Set a request attribute to tell the navigation infrastructure the title constant --> <!-- OPTIONAL, the default is "Windchill" --> <!-- This must be done before including begin.jspf --> <%request.setAttribute("browserWinTitleConst", navigationRB.WIN_TITLE_WORKSPACE_VIEW); %> <!-- Set a request attribute to tell the navigation infrastructure the help context --> <!-- OPTIONAL, the default is that no help is displayed --> <!-- This must be done before including begin.jspf --> <%request.setAttribute("helpFileSelectorKey", "myTabListHelp"; %> <!-- begin.jspf is required to draw the header --> <%@ include file="/netmarkets/jsp/util/begin.jspf"%> <!-- Your content should occur between begin.jspf and end.jspf --> <H1>Hello World!</H1> <!-- end.jspf is required to draw the footer --> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Create an action in navigation-actions.xml

Create an action for your new sub tab in navigation-actions.xml. You can create any type of action for a sub tab. In this example we will create an action that maps to the JSP created in the previous step.
<objecttype name="mytab" class="com.ptc.myTabClass"> <action name="list" > <command windowType="page"/> </action> </objecttype>

Create an entry in action.properties or an rbinfo file

Create localization strings for your action in action.properties or your own rbInfo file. For more details see Customizing Localizable Labels and Enumerations on page 18-29.
Add your action to the action list in navigation-actionModels.xml

Add an entry to the action model that will add your action to
<model name="mytab navigation" defaultActionType="mytab" defaultActionName="list"> <action name="list" type="mytab"/>

11-20

Windchill Customizers Guide

</model>

Customization Points
Procedure - Changing the application logo Procedure - Changing the header or footer look and feel Procedure - Removing a Main Tab Procedure - Removing a Sub Tab Procedure - Context Bar

Procedure - Changing the application logo

The application logo is controlled by CSS. Depending on what your install set is, a different CSS style is used. The following table lists the CSS style classes that are used and when they are used. When in doubt you can always change all the CSS classes to indicate the logo image you desire.
Style Class Install Set

pjlApplLogo pdmlApplLogo proIApplLogo atcmApplLogo wncApplLogo

Windchill ProjectLink standalone is installed. Windchill PDMLink standalone is installed. ProI is installed. Arbortext Content Manager is installed. Windchill ProjectLink and Windchill PDMLink are installed together.

Procedure - Changing the header or footer look and feel

The look and feel of the header and footer is controlled by CSS style classes defined in nmstyles.css. To change the look of the header update the appropriate style class. Below is a list of all the style classes and a description of what they do. For details on the logo image, please see the previous section Procedure Changing the application logo.
Style Class Description

pageHeader

This style defines the image that displays behind the logo and above the tabs and subtabs.

Adding Actions and Hooking Them Up in the UI

11-21

Style Class

Description

pageHeaderActions

This style controls the look and feel of the actions that are rendered above the tabs in the page header. This style controls the look and feel of the copy page button that is rendered above the tabs in the page header. This style controls the look and feel of the first level tabs. This style controls the look and feel of the second level navigation or sub tabs. This style defines the look and feel of the page footer, including the PTC logo displayed in the footer.

headerBtns

nav1 nav2

footer

Procedure - Removing a Main Tab

To remove a main tab simply remove the action for that tab from the main navigation list in navigation-actionModels.xml.
<!-- 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"/> </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>

11-22

Windchill Customizers Guide

Procedure - Removing a Sub Tab

To remove a sub tab simply remove the action for that sub tab from the sub tab navigation list in navigation-actionModels.xml.
<model name="product navigation"> <action name="list" <action name="separator" <action name="view" <action name="listFiles" <action name="listTeam" <action name="listProduct" <action name="changeMonitor" <action name="view_forum" <action name="MyWorkspace" <action name="listTemplates" <action name="listUtilities" </model> type="product"/> type="separator"/> type="object"/> type="product"/> type="product"/> type="work"/> type="product"/> type="project"/> type="product"/> type="product"/> type="product"/>

After removing the Change Monitor sub tab from the product sub tab list above. The list will look like this:
<model name="product navigation"> <action name="list" <action name="separator" <action name="view" <action name="listFiles" <action name="listTeam" <action name="listProduct" <action name="view_forum" <action name="MyWorkspace" <action name="listTemplates" <action name="listUtilities" </model> type="product"/> type="separator"/> type="object"/> type="product"/> type="product"/> type="work"/> type="project"/> type="product"/> type="product"/> type="product"/>

Procedure - Context Bar

The context bar has the capability to be customized. Three parts exist in the context bar. You have the container type followed by the container name. Then you may have a bread crumb depending on your location. In the example shown below, the bread crumb shows we are in a workspace and gives the name. Depending on your location you may see actions to the left of the container. These three parts of the context bar have the ability to be customized. Extend the ContextBarDelegate or a subclass of ContextBarDelegate Register MyContextBarDelegate

Extend the ContextBarDelegate or a subclass of ContextBarDelegate

The ContextBarDelegate is packaged under com.ptc.windchill.enterprise.navigation.ContextBarDelegate. The first thing you need to do is create a subclass of ContextBarDelegate or extend a subclass like WTLibraryContextBarDelegate. Below is an example. Since we are extending WTLibraryContextBarDelegate we have the choice of using super method instead

Adding Actions and Hooking Them Up in the UI

11-23

of having to override the three main methods. Otherwise, if ContextBarDelegate is extended you will need to implement each of the three abstract methods. Sample Code:
public class MyContextBarDelegate extends WTLibraryContextBarDelegate { @Override protected NmHTMLActionModel getActionModel() throws WTException { //Insert customized code } @Override protected GUIComponentArray getLeftSideComponents() throws WTException { //Insert customized code } @Override protected GUIComponentArray getRightSideComponents() throws WTException { //Insert customized code } }

Description of the three methods getActionModel() - This returns the action model to be shown in the context bar getLeftSideComponents() - In most cases this currently returns the container type, name and the breadcrumb. getRightSideComponents() - Components can be shown on the far right side of the context bar. An example of this is when you are in the Project container you will see a yellow/green/red indicator of the project status.

Register MyContextBarDelegate

As an example you can view the components.service.properties.xconf located under: Windchill\codebase\com\ptc\core\components. Though the properties should be added to a specific customized service.properties.xconf file. In the above example you would write something like the following:
<Service context="default" name="com.ptc.windchill.enterprise.navigation.ContextBarDelegate"> <Option requestor=" wt.inf.library.WTLibrary" serviceClass="com.ptc.windchill.enterprise.org.navigation.MyContex tBar" selector="cbNav" /> </Service>

11-24

Windchill Customizers Guide

Procedure - Display a custom object type's details page under your new tab

This section describes how to make a custom object's details page display on a custom tab. This assumes the custom object has already been created and is called com.mycompany.MyObject and the custom tab has already been added following the instructions above and is called mytab.
Create a custom Navigation Delegate

The tab highlighting has the capability to be customized even further than the examples given already above. Tab highlighting is controlled by classes that extend the interface com.ptc.windchill.enterprise,navigation.NavigationDelegate. In general it is not recommended to implement the interface directly. You should subclass one of the existing out of the box implementations. Many of the NavigationDelegates available out of the box can be found in the com.ptc.windchill.enterprise.navigation package. For this example you will need to create a custom subclass of com.ptc.windchill.enterprise.WTContainedNavigationDelegate. This subclass will be very simple as it only needs to override one method: getSelectedTabFromContextObject()
Package com.mycompany; import wt.util.WTException; import com.ptc.windchill.enterprise.navigation.WTContainedNavigationDeleg ate; public class MyObjectNavigationDelegate extends WTContainedNavigationDelegate { /** * Creates a new instance of MyObjectNavigationDelegate */ public void MyObjectNavigationDelegate () {} /** * All MyObjects are displayed on mytab, so when this class is * invoked, The tab from context object should always be mytab. */ protected final String getSelectedTabFromContextObject() throws WTException { return "mytab"; } }

There are other methods that you may wish to override but getSelectedTabFromContextObject() is the only one required for this use case.
Register MyObjectNavigationDelegate

For some examples you can view the components.service.properties.xconf located under: Windchill\codebase\com\ptc\core\components. Though the properties

Adding Actions and Hooking Them Up in the UI

11-25

should be added to a specific customized service.properties.xconf file or site.xconf. In the above example you would write something like the following:
<Service context="default" name="com.ptc.windchill.en terprise.navigation.NavigationDelegate"> <Option requestor="com.mycompany.MyObject " serviceClass="com.mycompany.MyObjectNavigationDelegate" selector="mainNav" /> </Service>

After registering you will need to run xconfmanager -p from a windchill shell and restart the method server. In some cases it may be necessary to increase the order of the delegate. Essentially this increases the priority of the delegate and bumps it above other delegates. Currently this is done in the out of the box product for the VerstionableChangeItemNavigationDelegate like so:
<Service context="default" name="com.ptc.windchill.enterprise.navigation.NavigationDelegate"> <Option order="1" requestor="wt.change2.VersionableChangeItem" serviceClass="com.ptc.windchill.enterprise.change2.navigatio n.VersionableChangeItemNavigationDelegate" selector="mainNav" /> </Service>

When order is used be sure to use an order higher than the delegate you are trying override.

Limitations
In order to get your tab and sub tab to display and highlight correctly you must follow the following conventions You must place your sub tab JSPs in a directory that exactly matches the name you gave to your main tab in Procedure - Adding a Main Tab on page 11-17. 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 the Create a new sub tab model for your tab in navigationactionModels.xml section on page 11-18. 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".

11-26

Windchill Customizers Guide

Action 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 profileand 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. As a customizer, you have the ability to customize the list of UI components available to administrators. You can:

Adding Actions and Hooking Them Up in the UI

11-27

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:

At the container level, you are managing the equivalent list presented when configuring visibility by roles:

11-28

Windchill Customizers 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

Adding Actions and Hooking Them Up in the UI

11-29

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; other *actions.xml files are generally in <Windchill>/codebase/config/actions. 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. Defines the labels to provide in the Uis for the actions or UI components.Located in <Windchill>/wtCustom/com/ptc/netmarkets/roleAcc ess/.

Roleaccessprefs.xml

XML

RoleAccessResource.rbInfo

RBINFO

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

11-30

Windchill Customizers Guide

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 The uic Element on page 11-32 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

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/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.

Adding Actions and Hooking Them Up in the UI

11-31

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.

Customization Points The uic Element


Each UIC in roleaccessprefs.xml represents a UIComponent or action to be controlled.
Parameter name Default Value n/a Possible values string Req? Y Description 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. The position of this UI component in the wizard. UI components with lower numbers are placed before those with higher numbers. Whether or not this uicomponent will be shown in the wizard and utilized by the system. The default visibility value for All Members. 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 also defaultAll to false, otherwise managers will still have access through the ALL_MEMBERS role. 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.

Order

Non-negative? Integer true | false true | false true | false

Enabled DefaultAll DefaultManag er

true true true

N N N

DefaultGuest

11-32

Windchill Customizers Guide

Parameter ManagerEnabl ed

Default Value true

Possible values true | false

Req? N

Description Whether or not this uicomponent can affect the manager role. Do not change this value in out-ofthe-box UICs. For customized UICs, you may choose your own setting. Whether or not this uicomponent can affect the guest role. Do not change this value in out-of-thebox UICs. For customized UICs, you may choose your own setting. The class on which runMethod exists 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.

GuestEnabled

true

true | false

RunClass runMethod

Java class name Java method name

N N

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 profilebased 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>

Adding Actions and Hooking Them Up in the UI

11-33

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 the Procedure - Making an Action Available to Visibility Administration section on page 11-31 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.

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"

11-34

Windchill Customizers Guide

defaultManager="true" defaultGuest="false" managerEnabled="false" guestEnabled="false" runClass="com.ptc.netmarkets.roleAccess.StandardNmRoleAccessServic e" 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.

Sample Code Examples of Usage in out-of-the-box 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


The Windchill Customizer's Guide - Managing Customizations on page 5-1

Other Related Windchill Documentation


Windchill Business Administrator's Guide - Role-Based Visibility Administration Windchill Business Administrator's Guide - Access Control (ad hoc policies)

Adding Actions and Hooking Them Up in the UI

11-35

Navigation Stickiness
Objective
Your users are not able to access tabs because the stickiness context is wrong. Examples: Clicking on Library tab leads to the Product tab.

Background
Each tab maintains a sticky info in order to take the user back to the same page they were on last time they visited the tab. It is possible for the stickiness info to be corrupted somehow (e.g. Library tab having a sticky context object that is in a Product results in the issue described in the problem statement clicking on the Library tab leads to the Product tab). This issue should not occur during the normal course of navigating the UI, but it is very easy to simulate the issue by manually manipulating the url. One way to force this issue to occur is to visit the details page of an object in a Product and add tab=library as a url parameter. This would cause the object in the Product to be stored as the sticky object for the Library tab. Now clicking on the Library tab will lead to the Product tab.

Solution
Clear the sticky info for the tab with the issue.

Prerequisite knowledge
To see or clear the sticky info for a particular user, you need to be logged in as the user. Note: Depending on which solutions are installed and the users role, you would see a different set of tabs than what is shown in the screen shots.

Procedure Viewing Current Sticky Info


Log in as the user whose sticky info should be cleared. Once youve visited a particular tab, the sticky info will be in the session and you can see it by visiting this url:
http://<machine>/<webApp>/netmarkets/jsp/components/stickiness.jsp

This will lead to a page that looks like this:

11-36

Windchill Customizers Guide

In the above example you can see that the sticky info for the Product tab is a Product oid and the Discussions action (the Discussions sub tab). Also note, you can see there is no sticky info in the current session for the Project tab. This means either you havent visited the project tab in this session, or you have just cleared the sticky info for the project tab. Once youve visited a tab within the session, youd see at least a sticky action. The sticky context oid is optional and some sub tabs dont have one. (e.g. the Products List)

Procedure Clearing the Sticky Info for a Tab


Log in as the user whose sticky info should be cleared. Visit this url:
http://<machine>/<webApp>/netmarkets/jsp/components/stickiness.jsp

For example, if clicking on the Library tab leads to the Product tab, the Library tab sticky info should be cleared. So click on the clear library tab hyperlink. (or click on clear sticky info for all tabs if you dont mind clearing out all the stickiness info for that user) Notice both sticky context oid and sticky action should be blank after youve cleared the sticky info.

Adding Actions and Hooking Them Up in the UI

11-37

Use Search to clear sticky object


Log in as the user whose sticky info should be cleared. Search for an object in the appropriate type of container and go to its details page to replace the corrupt sticky info with new valid sticky info. For example, if clicking on the Library tab leads to the Product tab, search for any object that is in any library. Going to the details page of that object will highlight the Library tab and save new sticky info for the Library tab, thus fixing the issue.

Additional Resources:
Windchill Client Architecture Action Framework Overview on page 11-2

11-38

Windchill Customizers Guide

12
Gathering the Data for the UI
This chapter describes how to gather data to be used in the user interface. Topic Page

Data Acquisition Configuration Properties .............................................. Page 12-2 Acquiring Data via Info*Engine .............................................................. Page 12-9 NmObject Utilities ................................................................................. Page 12-15

12-1

Data Acquisition Configuration Properties


Objective
You want to configure how data is retrieved for a Windchill Client Architecture table, tree or property panel.

Background
This document describes how you can configure Windchill Client Architecture components to retrieve and process data, without writing framework-specific Java code. Windchill Client Architecture allows you to configure a means to get your backing component data, and then a way to configure how this data is postprocessed to extract the properties that will actually be shown in the UI. What this means is that you have a lot of flexibility regarding the kind of data you retrieve, as long as it can be post-processed by the infrastructure.

Scope/Applicability/Assumptions
Specific considerations for each type of Windchill Client Architecture component are covered in their respective sections within the Windchill Customizers Guide.

Intended Outcome
An understanding of what options are available to you to configure data acquisition for a Windchill Client Architecture component.

Solution
Use the getModel, describeColumn and describeProperty tags to configure a data source for your Windchill Client Architecture component.

Prerequisite knowledge
To apply this knowledge you need to have an understanding of the following: JSP expression language (EL) JSP tags Windchill Client Architecture overview

12-2

Windchill Customizers Guide

Solution Elements
Element getModel tag getIeModel tag describeColumn tag describeProperty tag Type JSP tag JSP tag JSP tag JSP tag Description Configures a MethodServer data source Configures an Info*Engine data source Configures a column to display in a table Configures a property to display in a property panel. Supports the same API as describeColumn. A tag attribute that allows you to change the "backing object" A reporting tool to find what existing Windchill Client Architecture extension points are in the system Batches together multiple getModel calls

targetObject attribute Property report

JSP tag attribute Reporting tool

batch tag

JSP tag

Procedure - Deciding between getModel and getIeModel


There are two ways to get data for a Windchill Client Architecture table: Invoke a Java API on the MethodServer using getModel Invoke an Info*Engine task using getIeModel

Your choice will often be dictated by some pre-existing API that you are trying to integrate into the page. If that is not the case, then consider the following. getModel will: Enable coding to Persistable and other plug and play interfaces Facilitate unit testing and more POJO-style development

getIeModel will: Facilitate federation and customization Limit the attributes available to you to whatever is specifically requested, rather than the entire java object. This can either be a good or bad thing, depending on the use case Require the definition of logical attributes to return associations

If you choose to use the getModel tag, then refer to the Constructing and Rendering a Table Using the JSP Framework section on page 13-23 for details on how it is configured.

Gathering the Data for the UI

12-3

If you choose to use the getIeModel tag, then refer to the Acquiring Data via Info*Engine section on page 12-9 for more information.

Procedure - Extracting properties from data elements when using the getModel tag
If you configured your component using the getModel tag, you still need to tell the Windchill Client Architecture framework how to extract each property that will be displayed in the component from the resulting data elements. In many cases Windchill Client Architecture can automatically figure out how to extract these properties: Bean properties: If you are using an API that returns a Java bean, and you intend to display a property in the UI that corresponds to a property of the bean, the infrastructure can handle this automatically. Soft attributes: Windchill Client Architecture knows how to automatically find soft attributes for your business objects, even if the objects you returned do not know about the soft attributes. Existing Windchill Client Architecture extensions: Windchill Client Architecture already has a rich set of logical "properties" which can augment the business object or Info*Engine Element that you return.

Do I need to return Persistables?

Your backing APIs and tasks do not need to return Persistable objects. However, in order for non-Persistable objects to be selectable in the interface some additional configuration and/or extension may be necessary.
Bean properties

Windchill Client Architecture handles Java beans in the same way that the JSP EL does, meaning 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 with a column like the following:
<jca:describeColumn id="foo" .../>

Then the infrastructure will look for a "getFoo" method on each result object that it processes when it executes your getModel API. If the method isn't found, then 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 bean. In fact, anything you can do with the JSP EL can also be accomplished with Windchill Client Architecture. For example, you can use the dot notation to refer to nested properties. In addition, Windchill Client Architecture 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 Windchill Client Architecture uses to process bean properties.

12-4

Windchill Customizers Guide

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")

What about Info*Engine?

The bean-style property access only works for getModel calls. Info*Engine calls that need to retrieve associated properties should instead define logical attributes for those properties.
targetObject

targetObject provides a complementary approach to bean-style notation to access nested properties of objects. It is described in more detail below.
Soft attributes

Windchill Client Architecture can automatically look up the soft attributes for your Typed business objects if you ask it to. If you have a soft attribute on your part named "baz", and have added a column descriptor as follows:
<jca:describeColumn id="baz" .../>

Windchill Client Architecture will fail to find a bean property for "baz" on your business object, but will not just give up. It will next try to see if "baz" could be a soft attribute of the object. There are two ways that Windchill Client Architecture can determine this: If "baz" corresponds to a logical attribute of the object type. If the component id is a soft attribute external form, such as IBA|baz

If Windchill Client Architecture is able to find a soft attribute definition for the object, then it will go and fetch the object's value. Retrieval of soft attributes can be expensive, so if Windchill Client Architecture determines a soft attribute retrieval is in order, it will get the soft attributes for all objects in the data set at once.

Batch soft attributes

The soft typing infrastructure provides some convenience attributes that you can include in table definition to get a collection of related soft attributes. For example, the ALL_SOFT_ATTRIBUTES attribute will, as the name implies, retrieve any soft attribute that is visible on the object. To use this in a table definition, do the following:
<describeColumn id="ALL_SOFT_ATTRIBUTES" .../>

Gathering the Data for the UI

12-5

The out-of-the-box Windchill Client Architecture rendering infrastructure recognizes batch attributes and knows to expand out the resulting attribute set into individual columns per attribute.
Existing Windchill Client Architecture extensions

Beyond simple bean-style property retrieval and soft typing, Windchill Client Architecture also provides extensions that handle the many properties that need additional processing beyond what the core business object model provides. Some of these properties may still correspond to an underlying property of the business object, and some may in fact be doing their own separate data acquisition to add in data that the core business object doesn't know about. Refer to the "Finding existing Windchill Client Architecture extensions" procedure below for more information on discovering what extension points exist in the system.

Procedure - Using the targetObject configuration to change the "backing object" for a component
targetObject allows the developer to manipulate the result set from a backing API call, so that the infrastructure treats a property of each result object as the "row" object rather than the result object itself. For example the following configuration tells the infrastructure to use the "foo" property of the result object as the backing object for the "bar" row:
<jca:describeColumn id="bar" targetObject="foo" .../>

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 configuration calls getFoo().getBar() on the row object returned by your API:
<jca:describeColumn id="foo.bar" .../>

Rule of thumb: Use targetObject with Windchill Client Architecture extension classes

The difference between the foo.bar and targetObject="foo" approaches is that when you configure target object, the infrastructure treats the target object as if it were the object returned by your backing API. When you use the bean-style property configuration, the backing object for the API remains the row object that the Windchill Client Architecture infrastructure interacts with. This difference becomes significant when using Windchill Client Architecture extension classes in particular -- these classes may base functionality on what they think the current row object is, not just on what the specific property is that was requested in the component configuration. For this reason, it is generally a good practice to use the targetObject property when reusing a Windchill Client Architecture extension class (typically a DataUtility implementation).

12-6

Windchill Customizers Guide

This difference is also significant when implementing a selectable component. With targetObject, the selected object will be the nested object, whereas if using bean properties, the selected object will still be the data element returned by the getModel API.
Where can I use targetObject?

You can use target object at both the component level, in which case it applies to all columns or properties, or on specific columns or properties within the component.
What object types can targetObject return?

The targetObject can be any of the following types: Persistable WTReference ObjectIdentifier NmObject NmOid NmSimpleOid

Can targetObject be used with non-Persistables?

You can use target object to point to an object that is not a Persistable by wrapping the object in an NmSimpleOid. Refer to the NmObject Utilities section on page 12-15 for more information.

Procedure - Finding existing Windchill Client Architecture extensions


Windchill Client Architecture extension points are implementations of the DataUtility interface. Windchill is installed with a reporting tool that helps you find out what data utilities are available to you. This tool reports on all the available ids that you can add to your table configurations, as well as what the DataUtility implementation class is for that id. You can then refer to the JavaDoc for that DataUtility in order find out more details on what it does. The reporting tool can be accessed at:
http://<HOSTNAME>/<WEBAPP>/netmarkets/jsp/property/propertyReport. jsp

For information on how to implement your own Windchill Client Architecture extensions, refer to the Data Acquisition Configuration Properties section on page 12-2 for more information.

Gathering the Data for the UI

12-7

Procedure - Batching getModel calls


You can use the batch tag to retrieve multiple models at once. This cuts down on interprocess communication between the servlet container and method server. To use the batch tag you need to include the wc tag library as follows:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/core" prefix="wc"%>

The following shows you could use the batch tag:


<wc:batch> <jca:getModel ..../> <jca:getModel ..../> </wc:batch>

Customization Points
Refer to the Constructing and Rendering a Table Using the JSP Framework section on page 13-23 and the Windchill Client Architecture Tree section on page 13-64 for details on the various tag customization points discussed in this document

Sample Code
Refer to the Constructing and Rendering a Table Using the JSP Framework section on page 13-23 and the Windchill Client Architecture Tree section on page 13-64 for more code samples.

12-8

Windchill Customizers Guide

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
Windchill Client Architecture provides a getIeModel tag that works similarly to the getModel tag, but that retrieves its data from Info*Engine. The tag interacts with other Windchill Client Architecture tags just as getModel does. The difference is that instead of specifying a service method, one specifies an action that maps to an Info*Engine task.

Intended Outcome
A Windchill Client Architecture table that has its data backed by an Info*Engine task

Solution
Use the Windchill Client Architecture getIeModel tag to configure a Windchill Client Architecture table component

Prerequisite knowledge
Readers should be familiar with Info*Engine as well as with the basic Windchill Client Architecture data acquisition concepts.

Solution Elements

Element getIeModel tag ie tag library Param tag

Type JSP tag JSP tag library JSP tag

Description Configures the task to use to get the data The Info*Engine tag library A tag from the ie tag library that supplies parameters to the getIeModel tag

Procedure Implementing the getIeModel tag


The getIeModel tag is used in a JSP page in the same way that the getModel tag is. The only required configuration for the getIeModel tag (beyond descriptor and var) is an action that says what task should be executed to get the model data. For example, the following code snippet demonstrates the use of the dca-Search

Gathering the Data for the UI

12-9

task, where the resulting model is put in the scoped tableModel variable, and the relevant table descriptor is supplied by the tableDescriptor scoped variable:
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}" action="dca-search"/>

getIeModel is implemented by an Info*Engine-based tag handler. This means it works like the tags included in the Info*Engine JSP library, and can interact with them. Since it is an Info*Engine tag, getIeModel uses the page VDB and is embeddable. In addition, you supply parameters to the tag using Info*Engines param tag. To use the param tag, you need to include the Info*Engine tag library in your page, as follows:
<%@ taglib uri="http://www.ptc.com/infoengine/taglib/core" prefix="ie"%>

The param tag is nested in your getIeModel tag declaration as follows:


<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}" action="dca-search"> <ie:param name="GROUP_OUT" data="groupOutName"/> </jca:getIeModel>

Configuring task selection

Internally, the getIeModel tag uses Info*Engines Dispatch-Tasks webject to look up the task implementation for the action task name that is configured in the JSP. getIeModel exposes several parameters which are passed on to Dispatch-Tasks that it uses to choose the right implementation task. Refer to the Dispatch-Tasks documentation in the Info*Engine Users Guide.
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}" action="dca-search"> <!--These parameters are used by Dispatch-Tasks--> <ie:param name="GROUP_IN" data="groupInName"/> <ie:param name="TYPE" data="typeName"/> <ie:param name="CLIMBER" data="climberName"/> </jca:getIeModel>

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 pages URL ends with something like /somePage.jsp?foo=bar, then in your task implementation, @FORM[]foo[] will map to bar. If you want to explicitly configure the form data for your task, then you can do this by creating the form group in your jsp page (using Info*Engines JSP tag library), and then specifying the name of the group as an attribute of the getIeModel tag, as follows:
<jca:getIeModel var="tableModel" descriptor="${tableDescriptor}" form="formGroupName" action="dca-search">

12-10

Windchill Customizers Guide

Using configurable table views

The getIeModel tag fully supports configurable table views. Sort and filter criteria from the current table view are passed along to your task as described in the following section.
Using information supplied to your task by 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 PAGE_OFFSET: The first result row to return from the paging session, if any PAGING_SESSION_ID: The current paging session id, if any

Note: Most of these parameter names can be reconfigured to some other name using ie:params. See the Customization Points section below for details.

Customization Points getIeModel attributes


The following are attributes of the getIeModel tag that can be customized:
Parameter action form Default Value None The current request parameters Possible Values Any valid task name Name of a valid group in the page VDB Req? Yes No Description The name of the task to execute A group that contains form data for the task

Gathering the Data for the UI

12-11

ie:param customization points


The following are all parameters that can be specified using the <ie:param> tag:
Parameter GROUP_OUT GROUP_IN TYPE CLIMBER ATTRIBUTE_P ARAM_NAME SORTBY_PAR AM_NAME SORTED_PAR AM_NAME WHERE_PARA M_NAME TYPE_PARAM _NAME VERSION_PAR AM_NAME ITERATION_P ARAM_NAME ATTRIBUTE_T YPE_CONTEX T_PARAM_NA ME PAGE_LIMIT_ PARAM_NAM E PAGE_OFFSET _PARAM_NA ME Default Value output None None None ATTRIBUTE SORTBY SORTED WHERE TYPE VERSION ITERATION ATTRIBUTE_ TYPE_CONTE XT PAGE_LIMIT Possible Values Any Any Any Any Any Any Any Any Any Any Any Any Req? No No No No No No No No No No No No Description The name of the resulting group The name of the group in to supply to Dispatch-Tasks The name of the type to supply to Dispatch-Tasks The name of the climber to supply to Dispatch-Tasks The name of the attribute to put the requested attribute list in The name of the attribute to put the sort criteria in The name of the attribute to put the sort direction criteria in The name of the attribute to put the filter criteria in The name of the attribute to put the type criteria in The name of the attribute to put the version criterion in The name of the attribute to put the iteration criterion in The name of the attribute to put the attribute type context criterion in

Any

No

The name of the attribute to put the page limit info in The name of the attribute to put the page offset info in

PAGE_OFFSE T

Any

No

Limitations
Currently there is no Info*Engine support for trees.

12-12

Windchill Customizers Guide

Sample Code
The following JSP page demonstrates how a simple search page could be constructed, given a backing task name demo-Search. The page submits back to itself, supplying the TYPE and WHERE parameters to the backing task.
<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <%@ taglib uri=http://www.ptc.com/windchill/taglib/components prefix="jca"%> <%@ taglib uri=http://www.ptc.com/infoengine/taglib/core prefix="ie"%> <h2>Test Search</h2> <table> <tr> <th scope="row" align="right">Type:</th> <td> <input type="text" name="TYPE" value="${param.TYPE}"/> </td> </tr> <tr> <th scope="row" align="right">Additional criteria:</th> <td> <input type="text" name="WHERE" value="${param.WHERE}"/> </td> </tr> <tr> <td colspan="2" align="right"><input type="submit" value="Search"/></td> </tr> </table> <p> <jca:describeTable var="tableDescriptor" id="searchTable" label="Search Results"> <jca:describeColumn id="name"/> <jca:describeColumn id="number"/> <jca:describeColumn id="version"/> </jca:describeTable> <jca:getIeModel var="tableModel" descriptor="${tableDescriptor}" action="demo-Search"/> <jca:renderTable model="${tableModel}"/> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Examples of Usage in Windchill Code


Windchill search uses getIeModel.

Gathering the Data for the UI

12-13

Additional Resources Related Documentation


Windchill Adapter Guide (Info*Engine)

12-14

Windchill Customizers Guide

NmObject Utilities
Objective
You need to give each row in a Windchill Client Architecture table or tree a unique identifier, and a persisted object identifier is either inappropriate or unavailable.

Background
Left to their own devices, Windchill Client Architecture components assume that each row object that they are processing is a Windchill Persistable object. Components use the object identifier from the Persistable as a way to uniquely identify the object for selection and hyperlinks. If you run into a situation where the data returned by your query is not a Persistable object, or the data does not map to a Persistable in an obvious way, then you can implement an NmObjectUtility to provide the infrastructure a way to uniquely identify your objects. targetObject is preferable to NmObjectUtility If the row objects expose an API that returns a supported object type, then you do not need to write an NmObjectUtility. In this case, you can use the targetObject configuration at the table and/or column level to tell the infrastructure what property to use as the backing object for the row. The supported object types along with additional information are documented in the Data Acquisition Configuration Properties section on page 12-2. If it is possible to modify the row objects to expose an API for targetObject, this approach is considered a better practice than writing an NmObjectUtility, as it means you have fewer dependencies on framework-specific code.

Intended Outcome
An implementation of the NmObjectUtility interface

Solution
Implementing an NmObjectUtility

Prerequisite knowledge
You need to have an understanding of the following: Windchill application context (service.properties) Windchill Client Architecture Overview Configuring Data Acquisition NmObjects Overview

Gathering the Data for the UI

12-15

Solution Elements
Element NmObjectUtility DefaultNmObjectUtilit y An xconf file Type Interface Class Configuration file Description The NmObjectUtility interface that you will implement The default implementation of NmObjectUtility that you may extend The file in which you will register your new NmObjectUtility

Procedure Implementing an NmObjectUtility


The NmObjectUtility interface has two methods: getNmObject() and getTargetObject(). Your customization should only deal with the getNmObject() method. The getTargetObject() method is unsupported and you should only provide a no-op implementation of it. The getNmObject() method must create an instance of NmObject. The interesting part of the NmObject is its NmOid. An NmOid points to a persistent object, and its subclass NmSimpleOid points to an unpersisted one.
Constructing an NmObject for a persisted object

To construct an NmObject for a persisted object, you must obtain a Persistable, WTReference, or ObjectIdentifier for that object. Once you have the identifier, you use it to construct an NmOid and subsequently an NmObject.
//Construct an NmObject from a Persistable public NmObject getNmObject(Object datum, ModelContext mc) { //getPersistableFromDatum is your method to find //the Persistable object Persistable p = getPersistableFromDatum(datum); NmOid oid = new NmOid(p); NmObject result = new NmObject(); result.setOid(oid); return result; }

Constructing an NmObject for a non-persisted object

To construct an NmObject for a non-persisted object, you must create a unique String key for the object. Once you have the key, you use it to construct an NmSimpleOid and subsequently an NmObject.
//Construct an NmObject from a Persistable public NmObject getNmObject(Object datum, ModelContext mc) { //getStringKeyFromDatum is your method to find //the unique String key String key = getStringKeyFromDatum (datum); NmSimpleOid oid = new NmSimpleOid(); oid.setInternalName(key); NmObject result = new NmObject();

12-16

Windchill Customizers Guide

result.setOid(oid); return result; }

Registering your NmObjectUtility

Once you have written your NmObjectUtility, you need to let the Windchill Client Architecture infrastructure know about it. To do this, you add an application context mapping for the NmObjectUtility, where the table id that you want the NmObjectUtility to be used for is the application context selector. For example, if the table id is customTable, then the xconf entry would look as follows:
<Service name="com.ptc.core.components.descriptor.NmObjectUtility"> <Option serviceClass="com.myco.MyCoNmObjectUtility" selector="customTable" requestor="java.lang.Object" cardinality="singleton"/> </Service>

After adding the xconf entry, be sure to run the xconfmanager to propagate the change to your installation.

NmCommandBean
Object that 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 will execute actions if they exist on the request but it won't execute actions accidentally if the page is manually refreshed and the form is resubmitted. It essentially carries the request and state information from the Tomcat VM to the Method Server VM. Interesting attributes: Context: the where. compcontext, parentContext, element context, etc are used to determine what page is displayed and where actions are launched. oids : the objects that actions or pages apply to. requestData : all the state info about the page

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 javadoc for more info api usages.

Gathering the Data for the UI

12-17

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.

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. Often it is used 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.

NmContext
NmContext represents a UI address of a page. 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. Note that the $, ^, and !* are reserved separator characters.
"folder$list$OR:wt.projmgmt.admin.Project2:2343$OR:wt.folder.Su bFolder:7195^VR:wt.doc.WTDocument:18913!*

12-18

Windchill Customizers Guide

13
Presenting Information in the UI

This chapter describes how to customize information that is displayed in the user interface. Topic Page

Attribute Handling.............................................................................................13-2 Soft Attributes and SCAs ................................................................................13-21 Constructing and Rendering a Table Using the JSP Framework ....................13-23 Windchill Client Architecture Tree.................................................................13-64 Adding Custom Modeled Attributes to all Table Views.................................13-91 Attribute Tables...............................................................................................13-92 Generating the Name Attribute Server............................................................13-97 Partial Activation of JSCA ............................................................................13-102 Icon Delegates ...............................................................................................13-103 UI Validation.................................................................................................13-109 Customizing the Find Number Field .............................................................13-152

13-1

Attribute Handling
Objective
You want to render a UI component for an attribute of a Windchill object to either capture the users input during Create/Edit or to display the existing value of that attribute.

Background
In a Windchill client application, attributes of Windchill objects are rendered in 2 modes the input mode for Create and Edit and the view mode (on the Information pages, Tables, etc). The data-type of these attributes is restricted to the Windchill supported data-types exposed in the Information Modeler and the Attribute Manager. Standard data acquisition, translation, rendering and form processing mechanisms are required to maintain consistent attribute handling behavior across all client applications. The consistency is achieved by using the JCA framework. This framework provides re-usable components for building the UI components to represent attributes, from the server-side objects that represent them. The framework also provides extension points for customization via the ability to override the standard data-translation and rendering behavior. This document describes the best practices for creating and rendering a HTML GUI component to represent a Windchill attribute. A data utility is used to create a GUI component for an attribute. The data used to create this GUI component is a combination of the attribute and constraint definitions, and the configurations listed in the Customization Points section on page 13-12. The renderer for the GUI component generates the HTML for rendering the component. The Property Panel section on page 10-26 and the Constructing and Rendering a Table Using the JSP Framework on page 13-23 describe how to configure an attribute for being rendered in the client. The GUI components and their renderers can also be used to represent attributes that are not Windchill attributes like drawing a simple check-box on a page to capture some input from the user. GUI components can be simple components such as a text-box or composite GUI components built using the simple components, like a component that uses a textbox and 2 combo-boxes, as shown below: Simple GUI component:

13-2

Windchill Customizers Guide

Composite GUI component:

The components generated by this framework also have some built-in client-side validations, based on the constraint definitions and the configurations.

Scope/Applicability/Assumptions
Applicability

This practice should be followed when developing clients that need to display the following attributes: Attributes whose type is a valid Windchill soft attribute type. Boolean Integer Floating point number Floating point number with Units String Date & Time wt.fc.EnumeratedType URL WTOrgRef: At this time, the framework has support to display the value of these types of attributes, but does not support the input/editing of those values. The Windchill Product Structure Explorer provides the necessary support to input values for these attributes. Classification Node

Attributes whose type is any of the following native Java types: primitive boolean, java.lang.Boolean primitive byte, short, integer, long, java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long primitive float, double, java.lang.Float, java.lang.Double java.lang.String java.sql.Timestamp

Special Windchill attributes

Presenting Information in the UI

13-3

Name Number Location Revision label Principal Status (work in progress state) Lifecycle state Lifecycle template Team template

Intended Outcome
Consistent attribute handling behavior (rendering, validation wherever applicable and attribute processing) on any Windchill client that uses a given Windchill attribute in a given mode.

Solution
Use the Windchill client framework for rendering attributes in a Windchill client application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The Windchill soft attributes, Attribute Manager, Type Manager, constraints that can be defined on attributes in the Type Manager. The InfoModeler and constraints that can be defined on attributes in the InfoModeler. Basic knowledge of the Windchill Client Architecture The Windchill JSP describeColumn , describeProperty tags AllClients.xml and Windchill preferences for customizations The management of RBINFO file customizations

13-4

Windchill Customizers Guide

Solution Elements

Element Windchill Info Modeler

Type

Description Used to define the modeled attributes of a Windchill class and to define the constraints on each of those attributes. Used to define the instance based attributes and the attribute constraints using this tool. Used to define rules and constraints on objects. Used to customize some of the attribute rendering behavior that needs to be applied to all attributes across all clients.

Windchill Attribute Manager and Type Manager Object Initialization Rules Administrator Windchill Preference Manager AllClients.xml Xml file

Used to customize some of the attribute rendering behavior that needs to be applied to a specific attribute across all clients. Used to customize some of the attribute rendering behavior that needs to be applied to a specific attribute in a specific client.

Jsp files

JSP

componentRB.rbInfo <your_file>.rbInfo Data utility delegate

rbInfo rbInfo java Contains localized strings, can be defined separately for each module. Implements the methods to create concrete GUI component objects for a given attribute. Configuration point for mapping components to data utilities to override default GUI component creation behavior The model for a GUI component class Implements the rendering of a GUI component Configuration point for mapping GUI components to renderers to override default rendering behavior

service.properties (xconf) files

properties

GUI Component GUI Component Renderer components.service.properti es

java java properties

Presenting Information in the UI

13-5

Element Form processing delegates

Type java

Description The classes that process the form data of the OOTB GUI components.

Determining the attribute handling approach


Attribute is a Windchill supported type, and no custom behavior is required (only the standard out-of-the-box attribute handling behavior is required) Configure the attribute as described the Using OOTB Attribute Handling Behavior section on page 13-8.
Attribute type is not a Windchill JCA framework supported type

If the type of your attribute is not one of the Windchill Client Architecture framework supported types listed in the Scope/Applicability/Assumptions section on page 13-3, or you need to augment/alter the data returned by a core API, implement a data utility as explained below in the Implementing a Data Utility section on page 13-8 to create a GUI component for that attribute. Example: The 9.0 Windchill Client Architecture does not support the handling of attributes of type java.sql.Date out-of-the-box. If you want to render an attribute of this type in a JCA client, you may need to implement a DataUtility that knows how to create a GUIComponent for this type.
Object getDataValue(String component_id, Object datum, ModelContext mc) throws WTException { Object rawValue = getAttributeValue(component, datum, mc); DateDisplayComponent gui = new DateDisplayComponent(label); if (rawVal != null && rawVal instanceof Date) { gui.setValue(new Timestamp(rawVal.getTime())); } return gui; }

If custom UI behavior is required for the attribute, you are familiar with the JCA GuiComponent that represents that attribute and the data held in this object is sufficient to provide the rendering behavior you require, implement a custom Renderer for rendering the GUI component outlined in the Implementing a GUI component renderer section on page 13-10. Example:

13-6

Windchill Customizers Guide

The OOTB Renderer implementation for rendering a GUI component for date & time renders the component like this:

Suppose you want the component to be rendered as:

In this case you would write a custom renderer for the DateInputComponent. If the desired behavior cannot be achieved by just implementing a Renderer, the next alternative is to implement a GUI component for the attribute as outlined in Implementing a GUI component section on page 13-11. You may need to create a special form processing delegate if you are trying to use custom GUI components. See the Wizard Processing section on page 14-19 and Building Wizards to Create a Single Object on page 14-38 for information on how to do this.
Attribute Type is Windchill supported type, but you need to modify the way it is rendered

Same as Attribute type is not a Windchill JCA framework supported type on page 13-6 except that you may need to implement a data utility only if you are creating a custom GUI component.
Data needs to come from a different source

You may be able to do this just by configuration using the target object as described in Data Acquisition Configuration Properties on page 12-2. If that does not meet your requirements, you can implement a data utility that knows how to interpret the data and create a GUI component from it.
Need to post-process the raw data returned by the core APIs before displaying it

Same as Attribute type is not a Windchill JCA framework supported type on page 13-6. You can post-process the raw data in the data utility before using it to create the GUI component. You may need to create a special form processing delegate if you are planning to use custom GUI components. For example, you may want to generate a hidden

Presenting Information in the UI

13-7

field to store some data that may be required in conjunction with the data from the GUI component in order to derive the actual value for an attribute. The generic OOTB form processors will not have any knowledge of this specific hidden field that was part of your custom GUI component and how it needs to be processed. In this case, you may need to write your own form processing delegate that knows how to process this field.

Using OOTB Attribute Handling Behavior


1. Define the attribute and its constraints in the Windchill Info Modeler or the Windchill Type and Attribute Manager. 2. Configure the client to display the attribute as described in the following sections: Building Wizards to Create a Single Object (see page 14-38) Information Pages (see page 15-2) Constructing and Rendering a Table Using the JSP Framework (see page 13-23) and Windchill Client Architecture Tree (see page 13-64)

3. Perform any necessary customizations as described in the Customization Points section on page 13-12. Refer to the Data Acquisition Configuration Properties on page 12-2 for details on how to get a report of all the available ids that you can add to your configurations, as well as what the data utility implementation class is for that id.

Implementing a Data Utility


When you find that configuration will not be enough to get your component to work, your next alternative is to extend JCA by implementing a data utility. Data utilities let you augment the data returned by a core API with additional information. 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. The DataUtility interface has two core methods:
Object getDataValue(String component_id, Object datum, ModelContext mc) throws WTException void setModelData(String component_id, List objects, ModelContext mc) throws WTException

Create a Data Utility implementation class

After defining your attribute and its constraints, you should be ready to implemenat a data utility to handle that attribute. Since data utilities are looked up using application context, your implementation class must be public, and have a public no-arg constructor.

13-8

Windchill Customizers Guide

Implement the getDataValue() method of the DataUtility interface:

The getDataValue method gets the value that should be placed within a particular table cell. Typically, the object that is returned by this method should be an instance of GUIComponent. 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 = myObjetc.get(component_id); String displayVal = rawVal + My extra text; TextDisplayComponent gui = new TextDisplayComponent(); gui.setValue(displayVal); return gui; }

Implement the setModelData() method of the DataUtility interface:

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, and is supplied in a list of all the objects that will be processed. You can take advantage of this call to do some multi-object queries. The FolderedDataUtility is one example that does this (it queries for all folder locations at once). If this method is implemented, then you must configure the data utility to be stateful.
Configure the data utility

Add an application context entry like the following:


<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.core.components.factory.dataUtilities.Pro jectDataUtility" 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.Folder edDataUtility" requestor="java.lang.Object" selector="location"

Presenting Information in the UI

13-9

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. Example: The FolderedDataUtility is configured with cardinality "duplicate". This is because the FolderedDataUtility is stateful, it does some multi-object querying in setModelData, and then holds on to this data for subsequent calls to getDataValue. Since the utility is stateful, you must create a new instance of the utility for each table rendering request. By registering the data utility as "duplicate", application context will instantiate a new data utility for you 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).

Implementing a GUI component renderer


When you find that configuration on the standard GUI components will not be enough to get the UI behavior you require, your next alternative is to extend JCA by implementing a custom Renderer for the GuiComponent. This requires you to be familiar with the specific GuiComponent. The Renderer interface has one core method:
void draw(T o, Writer out, RenderingContext renderContext) throws RenderingException;

Example: The OOTB Renderer implementation for rendering a GUI component for date & time renders the component like this:

Suppose you want the component to be rendered as:

13-10

Windchill Customizers Guide

In this case you would write a custom renderer for the DateInputComponent. 1. Implement the custom renderer
public abstract class MyDateRenderer implements Renderer { public void draw(T o, Writer out, RenderingContext renderContext) throws RenderingException { // render the textbox and icon for the calendar widget // render a new line // render the combo box for the hours, the combo box for the minutes and the time zone } }

2. Register your custom renderer. In your data utility, when creating the GuiComponent in the getDataValue method, register this custom renderer as your DateInputComponents renderer
DateInputComponent gui = new DateInputComponent(); gui.setRenderer(new MyDateRenderer());

It is recommended that when you implement a new Renderer, you extend the AbstractGuiComponent base class.

Implementing a GUI component


When you find that configuration on the standard GUI components and/or overriding the Renderer will not be enough to get the UI behavior you require, your next alternative is to extend JCA by implementing a GuiComponent. The GuiComponent interface has one core method: void draw( Writer out, RenderingContext renderContext ) throws RenderingException; The GUI component implementation holds the UI model of an attribute to be rendered. The recommended practice is to have the draw() method of the GUI component invoke the services of a GUI component Renderer to generate the HTML for the UI component to be rendered.
public class MyTextBox implements GuiComponent { private String value; private intwidth = 10;

Presenting Information in the UI

13-11

private int maxCharLimit = 20; protected Renderer renderer; public void draw(Writer out, RenderingContext renderContext) throws RenderingException { if (renderer != null) { renderer.draw((Object)this,out,renderContext); } } }

Using GUI component wrappers


Some GUI components have Gui component wrappers. These wrapper tags can be found at:
com.ptc.core.components.tags.components

Some examples of the usage of these tags can be found at:


Windchill/netmarkets/jsp/carambola/tags/tags.jsp

The TLD is
$WT_HOME/WEB_INF/tlds/wrappers.tld

Finding registered data utilities


The best way to find existing data utilities is explained in Data Acquisition Configuration Properties on page 12-2.

Customization Points
Windchill preferences
Parameter Default Value Display Mode (Site level) Default Value Pre-populate Possible Values Do not display Pre-populate Button Description Mode of displaying the default value in the Create and Update modes This applies to all attributes. Selection List Style (Site level) Buttons Buttons Dropdown List UI style for Discretesets/Enumerated set elements

13-12

Windchill Customizers Guide

Parameter Boolean Style (Site level)

Default Value Buttons

Possible Values Buttons Dropdown List

Description UI style for Boolean attributes A preference used to determine whether the input field for String attributes and URL IBA type attributes should be single-line or multi-line. Local time zone of the user will be used as the time zone for the display / input of date values. Determines the measurement system to be used for all numeric values that have a Unit of Measure. This will filter out special HTML characters from strings while displaying the string values. Used to control the number of characters displayed when the attributes value is displayed on a table. This is also known as the truncation length of an attribute value.

String Length Threshold For Multiline Input (Site level)

60

Any number >= 0

Local Time Zone(User)

Time zone set on the server.

All standard time zones

Measurement system(User)

SI

MKS SI USCS CGS

Ignore URL values found in a string(Site)

No

Yes No

Display length of attribute values in tables

30

Any number >= 0

Presenting Information in the UI

13-13

Parameter Display length of attribute values in the info page

Default Value 30

Possible Values Any number >= 0

Description Used to control the number of characters displayed when the attributes value is displayed on an info page. This is limited to the top attributes panel and the folder location (for folder info pages). Any table displayed on an info page will be based Display length for attribute value in tables. This is also known as the truncation length of an attribute value.

13-14

Windchill Customizers Guide

AllClients.xml
Codebase location: WT_HOME/codebase/config/logicrepository/xml/AllClients.xml Examples for the configuration are available in the documentation provided in this xml file.
Possible Values - none prePopulate - button selectionListStyle - buttons - dropdown stringLengthThres hholdForMultilineI nput inputFieldType multiLine Any number >= 0 No No UI style for Discrete-sets/Enumerated set elements A preference used to determine whether the input field for String attributes and URL IBA type attributes should be single-line or multi-line.

Parameter defaultValueDispl ayMode

Default Value

Req? No

Description Mode of displaying the default value in the Create and Update modes This applies to all attributes.

- singleLine - multiLine

No

dateInputFieldTyp e

dateOnly default value is assigned in the Java code

- dateOnly dateAndTi me - timeOnly

No

Need to know this for CREATE & EDIT modes so that the UI can be created accordingly. (It is not possible to obtain this info from the format because the formats will be localized and it is not easy to parse the localized formats to get this info) This determines the display format for the Timestamp values.

dateDisplayFormat

Entries should have these 2 parts: rbInfo=nam e of the rbInfo file key=name of the entry

ignoreUrls

- true - false

No

This will filter out special HTML characters from strings while displaying the string values.

Presenting Information in the UI

13-15

Parameter displayLengthInTa bles displayLengthInInf oPage

Default Value

Possible Values Any number >= 0 Any number >= 0

Req? No

Description Used to control the number of characters displayed when the attributes value is displayed on a table. Used to control the number of characters displayed when the attributes value is displayed on an info page. This is limited to the top attributes panel and the folder location (for folder info pages). Any table displayed on an info page will be based Display length for attribute value in tables. Determines if a numeric value should be formatted with the locale-specific percent format Determines if a numeric value should be formatted with the locale-specific currency format

No

percent

true false

No

currency

true false

No

13-16

Windchill Customizers Guide

JSP files
Parameter defaultValueDispl ayMode Default Values Possible Values - none - prePopulate - button Req? No Description Mode of displaying the default value in the Create and Update modes This applies to all attributes. Example: <jca:describeProperty id="defaultUnit" defaultValueDisplayMode=button /> selectionListStyle - buttons - dropdown No UI style for Discrete-sets/Enumerated set elements Example: <jca:describeProperty id="defaultUnit" selectionListStyle=buttons /> stringLengthThres hholdForMultilineI nput Any number >= 0 No A preference used to determine whether the input field for String attributes and URL IBA type attributes should be single-line or multi-line. <jca:describeProperty id="description" stringLengthThreshholdForMultilineIn put =500/> inputFieldType multiLine - singleLine - multiLine No Overrides the behavior determined by
stringLengthThreshholdForMultilineInput

Example: <jca:describeProperty id="description"


inputFieldType =singleLine/>

dateInputFieldTyp e

dateOnly default value is assigned in the Java code

- dateOnly dateAndTim e - timeOnly

No

Need to know this for CREATE & EDIT modes so that the UI can be created accordingly. (It is not possible to obtain this info from the format because the formats will be localized and it is not easy to parse the localized formats to get this info) Example: <jca:describeProperty id="startDate" dateInputFieldType= dateAndTime/>

Presenting Information in the UI

13-17

Parameter dateDisplayFormat

Default Values

Possible Values A format string specified as an entry in an rbInfo file. This format string shall use the format pattern letters specified by Javas SimpleDateF ormat class. Standard Windchill formats are defined in \ wcCliSource\ UICommonR esources\src\ com\ptc\ core\ui\ componentR B.rbInfo And these can be used by specifying the entries in \Windchill\ DevModules\ CommonCo mponents\ src_web\ netmarkets\ jsp\ components\ standardAttri buteConfigs.j spf

Req?

Description This determines the display format for the Timestamp values. Example: <jca:describeProperty id="startDate" dateDisplayFormat="${standardDateTi me}"/>

13-18

Windchill Customizers Guide

Parameter displayLengthInTa bles

Default Values

Possible Values Any number >= 0

Req? Yes

Description Used to control the number of characters displayed when the attributes value is displayed on a table. This is also known as the truncation length of an attribute value. Example: <jca:describeProperty id="description"
displayLengthInTables =15/>

displayLengthInInf oPage

Any number >= 0

Yes

Used to control the number of characters displayed when the attributes value is displayed on an info page. This is limited to the top attributes panel and the folder location (for folder info pages). Any table displayed on an info page will be based Display length for attribute value in tables. This is also known as the truncation length of an attribute value. Example: <jca:describeProperty id="description" displayLengthInInfoPage=15/>

percent

true false

Determines if a numeric value should be formatted with the locale-specific percent format Example: <jca:describeProperty id="percentComplete" percent=true/>

currency

true false

Determines if a numeric value should be formatted with the locale-specific currency format Example: <jca:describeProperty id="cost" currency=true/>

inputRequired

true false

Used to mark fields as Required fields even though they may not have a Required constraint. Example: <jca:describeProperty id="startDate" inputRequired=true/>

Presenting Information in the UI

13-19

Parameter isInfoPageLink

Default Values

Possible Values true false

Req?

Description Applicable to Name and Number and Principal attributes only. Used to specify if the attribute is to be displayed as a hyperlink to the Info Page. This would override the default behavior. Example: <jca:describeProperty id="name" isInfoPageLink=false/>

componentRB.rbInfo file
Parameter CALENDAR_PAR SE_DATE in \ wcCliSource\ UICommonResour ces\src\com\ptc\ core\ui\ componentRB.rbIn fo HOUR_FORMAT in \wcCliSource\ UICommonResour ces\src\com\ptc\ core\ui\ componentRB.rbIn fo Default Value Possible Value A legal localized date format defined using valid dateformat characters. 12 24 Req? Description Date input format (dd/mm/yyyy vs. mm/dd/yyyy etc) This is required so that the entered value can be parsed according to the format.

12 Hour/ 24 Hour format This determines the entries in the hours dropdown (0 - 12 AM/PM vs. 024)

Additional Resources
See the following sections for more information. Building Wizards to Create a Single Object (on page 14-38) Building Wizards to Edit a Single Object (on page 14-90) Data Acquisition Configuration Properties (on page 12-2) Presenting Information in the UI chapter - various sections on tables (starting on page 13-1) Property Panel (on page 10-26)

13-20

Windchill Customizers Guide

Soft Attributes and SCAs


The values returned for following logical 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 ALL_SOFT_ATTRIBUTES Description Returns a list of all soft attributes associated with the retrieved object as well as values for all of those attributes. Returns a list of all soft attributes associated with the classification(s) of the retrieved object as well as values for all of those attributes. Returns a list of all soft attributes associated with the retrieved object which are NOT associated with the type of the retrieved object as well as values for all of those attributes. Returns a list of all soft attributes associated with the type of the retrieved object as well as values for all of those attributes. Returns a list of all soft attributes associated with the type indicated by the context of the constructed AttributeTypeIdentifier as well as values for all of those attributes. Returns a list of all soft attributes associated with the retrieved object which are NOT associated with the classification(s) of the object, as well as the values for those attributes.

ALL_SOFT_CLASSIFICATION_ATTR IBUTES

ALL_SOFT_NON_SCHEMA_ATTRIB UTES

ALL_SOFT_SCHEMA_ATTRIBUTES

ALL_SOFT_SCHEMA_ATTRIBUTES_ FOR_INPUT_TYPE

ALL_SOFT_NON_CLASSIFICATION_ ATTRIBUTES

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.

Presenting Information in the UI

13-21

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 ALL_SOFT_NON_CLASSIFICATION_ SCHEMA_ATTRIBUTES Description Returns a list of all soft attributes associated with the type of the retrieved object which are NOT associated with the classification(s) of the retrieved object as well as values for all of those attributes. Returns a list of all custom hard 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.

ALL_CUSTOM_HARD_ATTRIBUTES _FOR_INPUT_TYPE"

13-22

Windchill Customizers Guide

Constructing and Rendering a Table Using the JSP Framework


Objective
You want 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. Tables with many actions will display a menu bar. Each menu title provides a pulldown list of actions. The shortcut tool bar displays a subset of actions from the 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. Sorting allows the user to control the presentation of table data. 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. The status glyph column(s) convey status and messaging information about individual objects in the table. The object icon column displays the appropriate icon for that object.

Menu Bar Shortcut Tool Bar

Column Header/Sorting Selection

Status Glyph Columns

Object Icon Column

Presenting Information in the UI

13-23

Element

Description

Action Column(s)

The action columns in the content area of a table contain the row-level actions for specific objects in a table. The data rows of a table contain attributes for a given object in the table. This section covers table scroll bars. 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.

Data Rows

Footer

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:

13-24

Windchill Customizers Guide

Solution
Use Table Component to display the information in tabular format.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving HTML, JSP, JavaScript and Custom taglibs. Overview of Windchill Client Architecture tags. The actions framework in the Windchill client architecture. Configuring views. Data acquisition, Data Utilities, GUI component

Presenting Information in the UI

13-25

Solution Elements
Element Type Description

<your_page>.jsp <your>service.properties

JSP properties

Your Windchill Client Architecture Table implementation JSP file. Data utilities and services are defined here. Run time Location: <Windchill>\ codebase

<your>action.properties

properties

Action attributes defined here. Run time Location: <Windchill>\ codebase

<your>actions.xml

xml

Actions can be defined here. Run time Location: <Windchill>\ codebase\ config\actions

<your>actionModels.xml

xml

Action models can be defined here. Run time Location: <Windchill>\ codebase\config\actions

components.tld

tld

Tags can be defined here: Run time Location: <Windchill>\ codebase\WEB-INF\tlds\

<your>action.rbInfo

rbInfo

Contains localized strings, can be defined separately for each module.

Procedure Configuring Table Common Component


Include necessary artifacts

You should include the necessary artifacts in your configuring JSP file e.g. /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopup.jspf file and /netmarkets/jsp/end.jspf file. You also need to declare jcataglib directive. (uri=http://www.ptc.com/windchill/taglib/components)
Configure Table
<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/core" prefix="wc"%>

13-26

Windchill Customizers Guide

<%-->Build a table descriptor and assign it to page variable td<-%> <jca:describeTable var="tableDescriptor" id="netmarkets.project.list" configurable="true" type="wt.projmgmt.admin.Project2" label="Project List"> <jca:setComponentProperty key="actionModel" value="project list"/> <jca:describeColumn id="name" label="Name" sortable="true"/> <jca:describeColumn id="nmActions" /> <jca:describeColumn id="owner" need="containerInfo.ownerRef"/> <jca:describeColumn id="container" label="Host" need="containerReference"/> <jca:describeColumn id="category"/> <jca:describeColumn id="phase"/> <jca:describeColumn id="state" need="containerTeamManagedInfo.state"/> <jca:describeColumn id="projectHealthStatus" need="healthStatus"/> <jca:describeColumn id="completionStatus"> <jca:setComponentProperty key="percent" value="true"/> </jca:describeColumn> <jca:describeColumn id="modifyStamp" need="thePersistInfo.modifyStamp" sortable="true" defaultSort="true" /> </jca:describeTable> <%-->Get a component model for our table<--%> <wc:getCurrentUser var="user"/> <jca:getModel var="tableModel" descriptor="${tableDescriptor}" serviceName="com.ptc.netmarkets.project.NmProjectService" methodName="getProjects"> <comp:addServiceArgument value="${user}"/> </jca:getModel> <%-->Get the NmHTMLTable from the command<--%> <jca:renderTable model="${tableModel}"/> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

The first thing the JSP page does is defines a table using the describeTable tag. This tag creates a table descriptor object and assigns it to the page variable specified by the var attribute. This allows the descriptor to be referenced in the JSP using the JSP expression language (EL). The table defines a type, in this case Project2. The type is optional, and is only used to do some defaulting of values. In this example, it is only being used to default the labels for model-based column ids. The actionModel property indicates the name of the action model (from actionmodels.xml) that should be rendered in the table's toolbar. The columns in the table each have their own describeColumn tag. Each column's cell values will be produced by a data utility.

Presenting Information in the UI

13-27

Once the table descriptor is set up, it is passed in to the getModel tag. The getModel tag takes your table descriptor plus a way to get table data and returns a model object that can be used to render the table. Like the describeTable tag, the result of the getModel tag is placed in the pagescoped variable defined by the var attribute. The rendering portion of the table is simply done by passing your model object (defined by the getModel tag) into the renderTable tag. The Default Sorted column is defined with the defaultSort="true" attribute on the column tag.

Customization Points describeTable tag attributes


describeTable describes a Table common component that can be plugged in to Windchill Client Architecture getModel and renderTable tags. Its tag class is com.ptc.core.components.tags.components.DescribeTableTag and the body content is "scriptless".
Possible Values Any java.lang.String value

Parameter id

Default Value -

Req? Yes

Description The identifier for this table descriptor. If this table supports configurable views, then this id may be used to look up the view configurations, unless it is overridden by the configurableTableId attribute. Name of the exported scoped variable for the table descriptor. The type of the variable is com.ptc.core.components.descriptor.Co mponentDescriptor. The name of the scope to export the var attribute to.

var

Any java.lang.String value

Yes

scope

Can be (caseinsensitive): page, request, session or application -

No

type

No

Name of the main type of object displayed in this table. This can be either a modeled or soft type. When specified, the infrastructure will use the type to look up labels and other default values when it can't find them otherwise.

13-28

Windchill Customizers Guide

Parameter label

Default Value -

Possible Values Any java.lang.String value java.lang.String value of a com.ptc.core.ui.r esources.Compo nentMode java.lang.String value of a com.ptc.core.ui.r esources.Compo nentMode boolean -

Req? No

Description The localized label for this component.

mode

No

The name of one of the modes defined in the com.ptc.core.ui.resoureces.Component Mode enum. VIEW is the default mode if not specified. The name of one of the component types defined in the com.ptc.core.ui.resoureces.Component Type enum. TABLE is the default if not specified. Whether or not this table supports configurable views. The id to use to look up configurable views. If unspecified, then defaults to the table id. Only used if configurable is set to 'true' When this property is true, and the table is configurable, then this property will change the table rendering so that the table view edit wizard is launched directly from the table, as opposed to launching the table view manager. This is useful when the table does not support views, but still needs to allow the user to select columns and sort order.

componentTyp e

No

configurable viewId

false -

No No

singleViewOnl y

true/false

toolbarName

Any java.lang.String value Any java.lang.String value

No

The name of the action model to use for toolbar actions. The name of the action model to use for menubar actions. The help context for this table. No help icon will be displayed if no help context is specified.

menubarName

No

helpContext

No

Presenting Information in the UI

13-29

Parameter targetObject

Default Value -

Possible Values -

Req? No

Description Allows the developer to provide more objects for a single table row. Typically the infrastructure treats each index of the array returned by the getModel tag's API as a &quot;row&quot; object. This row object is passed to each column's DataUtility. If a different object is needed for some DataUtilities then that object can be specified as the targetObject in the describeTable or describeColumn tag. The original row object must have a getter method for the name specified as the target object. (i.e. targetObject="my_related_part" would mean the object needs a getMy_related_part() method). The target object will be used in the following places: The row object supplied to data utilities. The object that soft attributes will be extracted from The context object for the row checkbox

summary

No

A localized summary of the information in this table, which is used for accessibility compliance. Flag to indicate enable or disable collapse/expand action. It will work only when useJSCA=false This property when set to true, then current table will be considered for column freezing. By default the value is true.

disableAction

No

isFreezable

Boolean

No

13-30

Windchill Customizers Guide

Additional attributes set via the setComponentProperty sub tag Parameter actionModel scrollType Possible Values java.lang.String java.lang.String Description value that corresponds to an entry in an *actionmodel.xml file Value that represents constants from the JSTableConstants class under keys .JSTABLE_IMPL* "default" - chooses the browser default "D" = Dom based scrolling, the default for tables in popup wizard pages.

selectable

true/false

Determines if the checkbox column will be displayed. If set to false there will not be any check box column for table as well as tree.

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".
Possible Values Any java.lang.String value Can be (caseinsensitive): page , request, session or application java.lang.String of a fully qualified class name

Parameter var

Default Value -

Req? Yes

Description Name of the exported scoped variable for the descriptor. The name of the scope to export the var attribute to.

scope

No

serviceName

No

The name of the service class to use to get model data. This property is mutually exclusive with the queryCommand or statementSpec attributes. If this attribute is specified, then methodName must be specified as well. Arguments to the method can be specified with the addServiceArgument tag. The service class must either be a registered Windchill service or implement wt.method.RemoteAccess.

Presenting Information in the UI

13-31

Parameter methodName

Default Value -

Possible Values Any java.lang.String value

Req? No

Description The name of the method to use to get model data. This property is mutually exclusive with the queryCommand or statementSpec attributes. If this attribute is specified, then serviceName must be specified as well. Arguments to this method can be specified with the addServiceArgument tag. The StatementSpec to use to get model data. Note that QuerySpec implements StatementSpec. This property is mutually exclusive with the queryCommand, serviceName, and methodName attributes. The AbstractQueryCommand to use to get model data. This property is mutually exclusive with the statementSpec, serviceName, and methodName attributes. The descriptor to base the component model on

statementSpec

Is of type wt.pds.Statemen tSpec

No

queryComman d

Is of type com.ptc.core.que ry.command.co mmon.Abstract QueryCommand Is of Type com.ptc.core.co mponents.descri ptor.Component Descriptor java.lang.String of a fully qualified class name Any integer value

No

descriptor

True

treeHandler

No

The selector for the TreeHandler to use to build the data model. The tree handler should be registered in application context. The number of rows to display per page in the table. This attribute has been moved from renderTable tag to getModel tag and henceforth will be deprecated for renderTable tag.

pageLimit

No

13-32

Windchill Customizers Guide

Parameter fullListLimit

Default Value 10000

Possible Values INteger

Req? No

Description Specify a different maximum value of rows to be displayed in a table when the full list action is clicked. To keep the browser from crashing with too much html. The objective of shifting fullListLimit parameter to getModel tag was to provide a two-pass approach for Table model generation for performance enhancement. If fullListLimit is specified at getModel tag, then paging happens at MethodServer side and only the populated table model is sent to tomcat for rendering which improves performance considerably.

renderTable tag attributes


renderTable renders a JCA Table. f the var attribute is set, then the tag will set page-scoped attribute with an NmHTMLTable based on the supplied ComponentModel. If the var tag is empty, then the NmHTMLTable is created and drawn. The tag also supports drawing a pre-built NmHTMLTable by specifying the table attribute. Its tag class is com.ptc.core.components.tags.components.RenderTableTag and the body content is "scriptless". "pageLimit" and "fullListLimit" attributes should be defined at getModel tag and not at renderTable tag. Support for pageLimit and fullListLimit attributes on renderTable tag will be depricated in future.
Parameter var Default Value Possible Values Any java.lang.String value Req? No Description The name of the scoped variable to assign the NmHTMLTable to. If this is not specified, then the table is drawn by the tag. The name of the scope to export the var attribute to.

scope

Can be (caseinsensitive): page , request, session or application Of type com.ptc.core.compo nents.descriptor.Com ponentModel

No

model

No

The component model to create (and optionally draw) an NmHTMLTable from. If unspecified, then an NmHTMLTable must be specified using the table attribute.

Presenting Information in the UI

13-33

Parameter table

Default Value -

Possible Values Of type com.ptc.netmarkets.u til. table.NmHTMLTabl e boolean

Req? No

Description The NmHTMLTable to render. If this is not specified, then a ComponentModel must be specified from which a table will be created. Optionally show the count of objects in the table title area. The count is displayed as X of Y total objects, if Table has filter view displayed, else X total objects. X is number of objects displayed in current page & view of the table. Y is total number of objects in current view of the table across all pages. Determines whether the table is paged. Determines whether or not to show The customize view link in the view drop down. The number of rows to display per page in the table. If this was specified by the getIeModel tag, it does not need to be re-specified here.Its deprecated and will be specified henceforth in getModel tag. Specify a different maximum value of rows to be displayed in a table when the full list action is clicked. To keep the browser from crashing with too much html. Its deprecated and will be specified henceforth in getModel tag.

showCount

No

showPaging Links showCustom ViewLink pageLimit

true -

boolean boolean

No No

integer

No

fullListLimit

10000

integer

viewAllLink helpContext

URL to the view all page. Any java.lang.String value boolean boolean

No No

Option to show a view all link at the bottom of the table. The help context for this table. No help icon will be displayed if no help context is specified. Single Select mode. Use Radio buttons or checkboxes for the row selection. Specifies that the table should use scrollbars to keep the header and actions in view when looking down at the items in the bottom of the table.

singleSelect scroll

false

No No

13-34

Windchill Customizers Guide

Parameter rowBasedOb jectHandle

Default Value -

Possible Values boolean

Req? No

Description Whether objectHandles are needed for each row. By default, the value of this attribute is false. Set to true to render a table for creating/editing multiple objects in a create/edit wizard. JavaScript method to execute after the table has been rendered or re-rendered as a result of sorting etc. Specifies whether the table should use JSCA. If this attribute is set the rules are ignored and the passed in value is used to determine whether or not to use JSCA. Set to true to force the table to use JSCA. Set to false to force the table to use JCA The "preferenceContext" variable is used to control the scope of the preference. For e.g. user may or may not want the preference to be applied even when the context object is changed.

afterJS

Any java.lang.String value boolean

No

useJSCA

false

preferenceCo ntext

false

Any java.lang.String value

Configuring Tables - Overview


Building a table requires three main steps: Creating a JSP page and define table attributes. Defining a method of retrieving the table data. Specifying any special data utilities that format the data.

To start with, make sure the page includes the begin and end JSPF files. Also, include the common components tag library file. The code for the same is as follows:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ include file="/netmarkets/jsp/util/end.jspf"%

Every JSP page can be structured into three main parts: Creating the table descriptor object Defining the component model Rendering

Presenting Information in the UI

13-35

Details on configuring tables The following table configuration topics are included in the following subsections: Configuring Tables - Defining Table Attributes on page 13-36 Configuring Tables Set Table Model for Data acquisition on page 13-37 Configuring Tables Render Table on page 13-38 Configuring Tables Set sortable columns on page 13-39 Configuring Tables Adding Toolbar on page 13-40 Configuring Tables Adding row-level actions on page 13-41 Configuring Tables Adding Menu Bar on page 13-42 Configuring Tables Enabling row selection on page 13-43 Configuring Tables Enabling single/multiple row selection on page 13-44 Configuring Tables Adding the help icon on page 13-44 Configuring Tables Adding pagination and page limit on page 13-45 Configuring Tables Specify DataUtility for columns on page 13-46 Configuring Tables Adding an info page hyperlink to table data on page 13-47 Configuring Tables Enabling views on page 13-48 Configuring Tables - Defining Table Attributes on page 13-36 Configuring Tables - Show custom view Link on page 13-54 Configuring Tables Enable Scrolling on page 13-59 Configuring Tables Accessibility compliance on page 13-59 Configuring Tables Enable Table Count on page 13-60 Configuring Tables Hiding column of the table on page 13-60 Configuring Tables Display view all link on page 13-60 Configuring Tables Customize Preferences on page 13-60

Configuring Tables - Defining Table Attributes

The table attributes can be defined using the describeTable tag. This tag creates the table descriptor object and assigns it to the page variable specified by the var attribute. The id attribute stores the identifier for this table descriptor.

13-36

Windchill Customizers Guide

The label attribute is the localized label for this component and is displayed as the table header in the UI. The columns in the table are produced by adding the describeColumn subtag. 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, which has the same semantics when used in table components. The id attribute for this tag is used to look up default properties for the column. The code for the same is as follows:
<%-->Build a descriptor and assign it to page variable tableDescriptor<--%> <describeTable var="tableDescriptor" type="wt.part.WTPart" id="netmarkets.test.table" label="${tableName}" > <describeColumn id="name"/> <describeColumn id="number"/> </describeTable>

Here <describeTable> is the tag which is responsible for rendering the columns in the table . The label of the column can be fetched from the resource file. For this we need to make the entry in the rbInfo file and give the key as a label in the <describeColumn> tag. To add/remove columns in the Table, insert/remove describeColumn tag from the describeTable tag. The column order is the order in which the columns are defined using the describeColumn tag in describeTable tag in a JSP file. Each column has a guiComponent corresponding to the value to be shown in the column. Each guiComponent has a reference to renderer object that is responsible for generating the html. To change the default renderer we need to change the guiComponent or the renderer reference for that guiComponent. GuiComponent are created using the dataUtility. To hide a column, use hidden attribute in the <describeColumn> tag. When true, the column will not be shown in the displayed page but can be used in sorting and filtering. This allows custom sorting and filtering options. The default value is false.
Configuring Tables Set Table Model for Data acquisition

We can pass the table descriptor to the getModel tag. In the data acquisition phase, the developer combines a component descriptor with some additional information on how to actually go and get the data that will back the component. This takes the table descriptor and a way to get the table data and returns a model object that will be used to render the table. The table descriptor variable must be specified in the descriptor attribute. The serviceName attribute is used to specify the Java API service class that retrieves the table data.

Presenting Information in the UI

13-37

When serviceName is included, the methodName attribute must also be used. The name of the method within the service class is indicated using this attribute. The code for the same is as follows:
<%-->Get a table model using our descriptor and query command, assign model to page variable tableModel<--%> <getModel var="tableModel" descriptor="${tableDescriptor}" queryCommand="${queryCommand}"/>

Configuring Tables Render Table

The rendering part is done by passing the model object into the renderTable tag. The variable for the model object specified in the getModel tag should be passed to the renderTable. If the model attribute is not specified, then NmHTMLTable must be specified using the table attribute. The code for the same is as follows:
<%-->Render the table model<--%> <renderTable model="${tableModel}"/>

Thus the entire generated JSP will look as followed:


<%-->Build a descriptor and assign it to page variable tableDescriptor<--%> <describeTable var="tableDescriptor" type="wt.part.WTPart" id="tableId" menubarName = "tabular input toolbar" label="${tableName}" configurable="true"> <setComponentProperty key="actionModel" value="product list"/> <setComponentProperty key="selectable" value="true"/> <describeColumn id="name" sortable="true" defaultSort="true" /> <describeColumn id="number" sortable="false"/> </describeTable>

<%-->Get a query command and assign it to page variable queryCommand<--%> <cmb:getTypeInstanceCommand var="queryCommand" descriptor="${tableDescriptor}"/>

<%-->Get a table model using our descriptor and query command, assign model to page variable tableModel<--%> <getModel var="tableModel" descriptor="${tableDescriptor}" queryCommand="${queryCommand}"/>

<%-->Render the table model<--%> <renderTable model="${tableModel}"/>

13-38

Windchill Customizers Guide

Configuring Tables Set sortable columns

A table column can be made sortable by setting the sortable attribute to true. If we want to sort the table by default with a specific column, then we can mark the column as defaultSort. The code for the same is as follows:
<describeColumn id="name" sortable="true" defaultSort="true" />

This code snippet will sort the column name at the page load time (defaultSort="true"). As well as user can sort the column as and when required (sortable=true). This will generate the Table as follows:

Note: If a column in a table is marked as non-sortable in a JSP through describeColumn, then the respective change should be done in the view configuration as well (through ConfigurableTable class). The table column definition in the JSP should be in synch with ConfigurableTable class. If the column definition in JSP is not in sync with the view definition then it can result into anomalies at the user interface.
Sorting Behavior

Sorting behavior differs in following scenario: 1. For Paging tables a. If the table had no selected rows: If the user is on page X then, table refresh resulted because of sort action will show the table vertically positioned at the first row of the first page. b. If the table had selected rows:

Presenting Information in the UI

13-39

When the table is refreshed because of sort action, the table will page to the page that contains the last of the pre-sort selected rows. The selected rows will be retained. 2. If the table is a scrolling table, i.e. do not have pagination enabled or a full list table a. If the table had no selected rows: On sort action, the table will be positioned at the first row in the table. b. If the table had selected rows: On sort action, the table will scroll to show the last row that was selected. The selections are retained. 3. If column freeze is applied on the table the horizontal scroll position is always maintained after a sort action. 4. The "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.
Configuring Tables Adding Toolbar

Adding a toolbar to the table is achieved by using the setComponentProperty tag. setComponentProperty tag configures properties of its parent tag that aren't exposed as attributes of the parent tag itself. This gives the infrastructure and the developer flexibility about the metadata they'd like to be available, without always requiring a tld update to do so. This is a helper tag that sets properties on the component descriptor managed by a parent describe tag. The key attribute and the value attribute are the key and value for the properties map of the target ComponentDescriptor, respectively. 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. The code for the same is as follows:
<describeTable var="tableDescriptor" type="wt.part.WTPart" id="tableId" menubarName = "tabular input toolbar" label="${tableName}" configurable="true"> <setComponentProperty key="actionModel" value="customToolbar"/> <setComponentProperty key="selectable" value="true"/> <describeColumn id="name" sortable="true" defaultSort="true" /> <describeColumn id="number" sortable="false"/> </describeTable>

This example uses a toolbar named customToolbar that contains pre-existing folder actions.

13-40

Windchill Customizers Guide

If the table uses a new action model for the toolbar, it must be registered in the actionModels.xml file.
<model name="CustomToolbar"> <action <action <action <action <action <action </model> name="list_cut" name="list_copy" name="fbpaste" name="list_delete" name=" separator " name="create" type="object"/> type="object"/> type="object"/> type="object"/> type="separator"/> type="document"/>

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. The "cross page functionality" allows the user to select multiple rows across multiple pages and apply the tool bar actions to the rows across multiple pages. Here is the simple table example with the custom toolbar added:

Configuring Tables Adding row-level actions

Use <describeColumn id="nmActions" sortable="false"/> in the table. NmActions Data Utility gets the "Actions" hyperlink by default, but can be configured with properties to get any NmHTMLActionModel or NmAction. The drop down is generated using the Menu component. By default this data utility will return the Actions hyperlink. And by default the Actions hyperlink will display the action model flagged with menufor="<someObjectType>" in an actionmodels.xml file, where <someObjectType> is the type of the row object (e.g. wt.part.WTPart) This is determined dynamically, you should not have to configure which action model to use, even if your table has multiple object types. To have this data utility return an Actions hyperlink to an action model other than the default use the "actionModel" property. In a jsp it would be like:
<jca:describeColumn id="nmActions">

Presenting Information in the UI

13-41

<setComponentProperty key="actionModel" value="<action_model_name>"/> </jca:describeColumn>

From a data utility class it would be like: descriptor.setProperty(DescriptorConstants.ActionProperties.ACTION_MODEL, "<action_model_name>"); Where <action_model_name> is the name of some action model in an actionmodels.xml. Note: To avoid inconstancies in ordering/grouping of the actions and issues with finding all the action models to adjust when adding new actions, it is preferred to have one action model per object type that represents the Actions list across the system (meaning in represents the actions list used in tables/trees and also on the info page). Action validation should be used to filter the list.
Configuring Tables Adding Menu Bar

To add a menu bar, the menubarName attribute from the describeTable tag must be included The name of the action model to use for the menu bar actions is specified in this attribute
<describeTable var="tableDescriptor" type="wt.part.WTPart" id="tableId" menubarName = "customMenubar" label="${tableName}" configurable="true"> <setComponentProperty key="actionModel" value="customToolbar"/> <setComponentProperty key="selectable" value="true"/> <describeColumn id="name" sortable="true" defaultSort="true" /> <describeColumn id="number" sortable="false"/> </describeTable>

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. Code for the same is as follows:
<model name="customMenubar"> <submodel name="fileMenu"> <submodel name="editMenu"> </model> <model name="fileMenu"> <action name="list_cut" <action name="list_copy" <action name="fbpast" <action name="list_delete" </model> <model name="editMenu">

type="object"/> type="object"/> type="object"/> type="object"/>

13-42

Windchill Customizers Guide

<action name="create" </model>

type="document"/>

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:
object.fileMenu.description=File object.editMenu.description=Edit

The entries for the File and Edit actionModels would look like:
object.fileMenu.description.value=File object.editMenu.description.value=Edit

Adding the menu bar will produce the following results:

Since "cross page functionality" is now provided which allows the user to select multiple rows across multiple pages, the menu bar actions will now be applicable to the rows across multiple pages.
Configuring Tables Enabling row selection

Making the rows selectable can be done by adding another setComponentProperty tag. The key attribute must be set to selectable and the value attribute must be set to true. This will provide the checkbox for each of the rows in the table, by which the user can select any of the records for the update or deletion. Code for the same is as follows:
<describeTable id="tableId" var="tableDescriptor" label="${componentName}" >

Presenting Information in the UI

13-43

<setComponentProperty key="selectable" value="true"/> <describeColumn id="name" label="${columnName}" /> </describeTable>

Configuring Tables Enabling single/multiple row selection

We can also give 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 of the tag <renderTable> to true. 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. The code for the same is as follows:
<renderTable model="${tableModel}" showPagingLinks singleSelect="true"/>

Configuring Tables Adding the help icon

The help page can easily be integrated in the table. The help page can be localized. The tag for the same is <renderTable> and attribute for the same is helpContext. This tag will pick up the entry from service.properties.xconf. The entry in service.properties.xconf will be as follows
<Option requestor="java.lang.Object" resource="online.accessible.ATTablesUse" selector="TEST_HELP"/>

online/accessible/TTablesUse.html is the path for the help page. The code to be written for the help page will be as follows
<renderTable model="${tableModel}" helpContext="TEST_HELP"/>

The table with help page will look as follows

13-44

Windchill Customizers Guide

Adding help page will produce the following results:

On click of the ? sign the pop up will open up which will show up the help for the table.
Configuring Tables Adding pagination and page limit

Depending on the number of records in the table, the pagination facility can be given. The tag used for the pagination is <renderTable>. If the attribute showPagingLinks is set to true, the pagination will be enabled. We can also specify the number of records that are to be shown on each page. This can be set by setting the maximum number of records to be displayed to the attribute pageLimit. If the value for pageLimit is not defined, it would be fetched from the preference value. The code for the same is as follows:
<jca:getModel var="tableModel" pageLimit="10"/>

Presenting Information in the UI

13-45

Adding the pagination will produce the following results:

Configuring Tables - Adding pagination in header

You can can add the paging links in header. This option can be set through preference manager. By default this option is disabled and if set it will display the paging links in header as well as footer.

Configuring Tables Specify 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 dataUtilityId attributes of the describeColumn tag.

13-46

Windchill Customizers Guide

<describeColumn id="iconType" label="${columnName}" dataUtilityId="typePicker.iconType" />

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.dataUtiliti es.IconTypeDataUtility" requestor="java.lang.Object" selector="typePicker.iconType" cardinality="duplicate"/> </Service>

Configuring Tables Adding an info page hyperlink to table data

We can specify the name columns link to the info page of the row object. When the user clicks on that link, the new page (Infopage) will open up. This can be done by setting the isInfoPageLink attribute of the <describeColumn> tag to true. The code for the same is as follows.
<describeColumn id="name" isInfoPageLink="true"/>

The isInfoPageLink attribute overrides the default behavior of the column to add or remove a hyperlink to the info page of the context object. The attribute is only applicable for the name and number columns. By default the number is a hyperlink to the info page and name is not. Adding the link will produce the following results:

Displaying table data as hyperlink can also be achieved using a data utility. The data utility can be configured in service.properties file.

Presenting Information in the UI

13-47

Configuring Tables Enabling views

To filter data for a table one has to use customized views. If the table has the customized view option available then using that, we can filter the data. The view wizard has a "set filters" step, which can be helpful in setting the filtering rules. There are two main steps to defining a configurable table: Define the columns, filter criteria, etc that you want to show up in the configurable view wizard Register your table, and set up your JSP page to enable configurable tables

In order for a table to be configurable, you must explicitly specify this in the JSP. To do this, add a configurable="true" attribute to the describeTableTag, as follows:
<describeTable id="someTable" configurable="true" ... />

Setting configurable="true" adds the Current View drop-down to the top-right corner of the table. If you want your table to use a configurable table id that is different from the table id, you can use the new "viewId" attribute:
<describeTable id="someTable" viewId="my_view_Id" ... />

Note that setting viewId implicitly sets configurable to "true".

Configuring Tables - Create a customized view

Table views intended for JCA are required to extend the com.ptc.core.htmlcomp.components.JCAConfigurableTable class. Once the table is implemented, it needs to be registered in an application context in order for the infrastructure to find it. For that, add a service to the service.properties.xconf file and the serviceClass attribute must match the location of the JCAConfigurableTable class. The selector must match your table's id. 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.

13-48

Windchill Customizers Guide

Available Attribute Report:


http://<server>:<port>/<context>/netmarkets/jsp/carambola/createta bleview/availableAttributesReport.jsp

The table currently displays the "Sample View" created in the configurable table implementation. 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. 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.
Configuring Tables - Creating a Configurable Table Instance

The way to define a new configurable table is by implementing the com.ptc.core.htmlcomp.tableview.ConfigurableTable interface. This interface has methods that allow the configurable table wizard to find out what wizard steps, columns and types should be available. In general, this interface should not be implemented directly. Table views intended for the Windchill Client Architecture are required to extend the com.ptc.core.htmlcomp.components.JCAConfigurableTable base class. This is required so that the appropriate mapping between Windchill Client Architecture and CADX attribute ids can occur. For more information, see com.ptc.core.htmlcomp.components.JCAConfigurableTableAdapter.
Controlling Which Steps Are Displayed

Each step can be hidden or displayed in the create and edit view wizard by overriding the appropriate method. Return true to display the step and false to hide it. By default all steps are displayed. showSetNameStep() - This step allows the user to set\edit the name for the view. This step is usually hidden when only allowing a single user-editable view. showChooseItemTypesStep() - This step allows the user to set\edit the set of types that will be displayed in the view. This step is usually hidden if the table only contains a single type. showFilteringStep() - This step allows the used to define filtering criteria used to filter the data displayed in the table. This step is usually hidden if attribute filtering is not supported or is supported by other means. (i.e. Search)

Presenting Information in the UI

13-49

showSetColumnsStep() - This step allows the user to select the set of columns that will be displayed in the table. There is currently no reason to ever hide this step. showSortingStep() - Select sorting step. There is currently no reason to ever hide this step.

Example
// Hide the name step public boolean showSetNameStep(){ return false; }

Defining Which Types Are Available

There are two methods that define the list of types that can appear as rows in the table. getClassTypes() - Defines the list of available types. This method should construct and return an array of java.lang.Class objects. This list of types, along with any child types, will show up in the "Choose Item Types" step. getAttributeOnlyClassTypes() - The types defined here will not appear in the "Choose Item Types" step, but will be used to generate attributes for the "Select a Column" step.

This information is used to determine the set of available columns that can be selected for the table. For example, if the class list includes WTPart.class, then the infrastructure knows that there are a few columns that should always be available for parts (like name, number, etc). If null is returned from this method, all of the columns will be determined by getSpecialTableColumnsAttrDefinition(Locale).
Example
public Class[] getClassTypes() { return new Class[] { WTPart.class }; }

Defining Which Attributes Are Available

The available attributes factory is responsible for determining the initial list of attributes for each configurable table. Attributes are defined per type in the available attribute xml files. The list of types defined in the configurable table is passed to the available attribute factory and the list of attributes for those types is returned. This base list can be added to or filtered differently for each step.
Removing Attributes

An attribute can be removed from any step by overriding the appropriate method and returning false for the attribute's id.

13-50

Windchill Customizers Guide

canAttributeBeUsedInFilter(String) - Removes the attribute from the attribute filtering step. isAttributeValidForColumnStep(String) - Removes the attribute from the list of available columns. isAttributeValidForSortingStep(String) - Removes the attribute from the list of sortable columns.

Example
// Sorting on the info page action doesn't make sense, so it is being removed public boolean isAttributeValidForSortingStep(String key) { return !key.equals(ColumnIdentifiers.INFO_ACTION); }

Special Columns

The getSpecialTableColumnsAttrDefinition(Locale) method tells the configurable view wizard about columns that it cannot find out about automatically (this is what makes these columns "special"). Automatic columns are discovered by looking up the global columns that map to each data type returned by getClassTypes. The getSpecialTableColumnsAttrDefinition method returns a list of com.ptc.core.htmlcomp.createtableview.Attribute.AbstractAttribute objects. Each one of these attributes represents a column that a user can choose to include in the table view. The primary value of these attribute definitions is that they allow the table view wizard to know how to present filter criteria for the column. For example, if a column is represented by a BooleanAttribute, then the wizard knows that to filter on this column, the user should select either true or false. There are 5 concrete types of AbstractAttributes: BooleanAttribute - A column that contains a boolean value CustomAttribute - Not used by the Windchill Client Architecture DateAttribute - A column that contains a Date value TextAttribute - A column that contains a String value ListAttribute - A column that contains a list of predefined values

The IDs for the attributes returned here should correspond to the ids used to define data utilities for the columns, if needed Most columns will not need to be listed here. It is very unlikely that a table will have more than a few special columns. Only add a column here if it is specific to the table. A common exception to this rule is the Actions column. Since it is not defined globally, you will need to add it here if you want that column.

Presenting Information in the UI

13-51

Example
public List getSpecialTableColumnsAttrDefinition(Locale locale) { List result = new ArrayList(); // add the actions column as a special column result.add(new Attribute.TextAttribute(ACTIONS, projectRb.getString(projectResource.ACTIONS), locale)); ... return result; }

Defining OOTB Views

The getOOTBTableViews(String, Locale) method returns a list of com.ptc.core.htmlcomp.tableview.TableViewDescriptor objects, where each descriptor represents a view that should appear in the view selection list by default. These views are loaded into the database the first time the table is visited by the user. Because these OOTB view definitions are loaded into the database, the loaded definitions will need to be cleared after making changes for them to take effect. Each TableViewDescriptor contains a Vector of com.ptc.core.htmlcomp.tableview.TableColumnDefinition objects. Each TableColumnDefinition represents a column that should appear in the view. The TableViewDescriptor has a few flags that are of interest: system - Flags the view as a system loaded view. This prevents the user from being able to delete or edit it. The user can, however, still choose not to show it in the view manager. This should be false if the table only supports a single user-editable view. global - No longer used. This property is ignored. match - Whether or not to match all or any criteria. If set to true, the criterion are ANDed together. If false, they are ORed.

Configurable table implementations that extend com.ptc.core.htmlcomp.tableview.AbstractConfigurableTable (JCAConfigurableTable extends this) can take advantage of some reusable helper methods. There are helpers to get: Latest version/revision criterion. (See getAdvVersionLatestCriterion() and getAdvRevisionLatestCriterion()) Latest version/revision column. (See getAdvVersionAttrDef(Locale), getAdvRevisionAttrDef(Locale) and getAdvVersIterAttrDef(Locale, String, String)) Localized OOTB table view names and descriptions. (See getResourceEntryKey( String classname, String propertyName))

When possible, use the column ids defined in DescriptorConstants.ColumnIdentifiers.

13-52

Windchill Customizers Guide

View Filtering

Views can have filters, or TableViewCriterion, attached to them that filter the table rows based on a set of criteria. In order to properly filter on object type, the criterion must be formed properly. This is required in order to show the proper object types selected in the Select Object Types Step of the create and edit view wizard. To form the criterion properly, the method com.ptc.core.htmlcomp.createtableview.AttributeHelper.getObjTypeKey(Class) should be used. To get localized enumerated type filters, use getStringValue() on the enumerated type value.
Example
public List getOOTBTableViews(String tableId, Locale locale) throws WTException { // The list of all ootb views List<TableViewDescriptor> ootbViews = new ArrayList<TableViewDescriptor>(); // The columns that make up one ootb view Vector<TableColumnDefinition> columns = new Vector<TableColumnDefinition>(); columns.add(TableColumnDefinition.newTableColumnDefinition(ColumnI dentifiers.FOO, /*lockable*/false)); columns.add(TableColumnDefinition.newTableColumnDefinition(ColumnI dentifiers.BAR, /*lockable*/false)); // The criteria for this ootb view Vector<TableViewCriterion> criteria = new Vector<TableViewCriterion>(); criteria.add(TableViewCriterion.newTableViewCriterion(ColumnIdenti fiers.STATE, OperatorConstants.EQUALTO, ProjectState.RUNNING.getStringValue(), null)); criteria.add(TableViewCriterion.newTableViewCriterion(ColumnIdenti fiers.ICON, OperatorConstants.EQUALTO, AttributeHelper.getObjTypeKey(Milestone.class), null); // Get the localized name an description of the view String name = getViewResourceEntryKey(RESOURCE, fooResource.MY_VIEW_NAME); String description = getViewResourceEntryKey(RESOURCE, fooResource.MY_VIEW_DESCRIPTION); TableViewDescriptor desc = TableViewDescriptor.newTableViewDescriptor(name, tableId, /*system*/ true, /*global*/ true, columns, criteria, /*match*/ true, description); // Add the descriptor to the list of all ootb views

Presenting Information in the UI

13-53

ootbViews.add(desc); // Create additional TableViewDescriptors and add them to ootbViews as needed ... return ootbViews; }

Configuring Tables - Making a Windchill Client Architecture Table Configurable

In order for a table to be configurable it must be explicitly declared in the JSP. To do this, add a configurable="true" attribute to the describeTableTag. If a configurable table id that is different from the table id is required, the "configurableTableId" attribute can be used.
<jca:describeTable id="someTable" configurable="true" ... >

OR
<jca:describeTable id="someTable" configurableTableId="someConfigurableTableId" ... >

Note that setting a configurableTableId implicitly sets configurable to "true".


Configuring Tables - Show custom view Link

Customization of the configurable table can be removed by adding showCustomViewLink="false" to the renderTable tag. This will remove the "Customize..." link from the view drop down.
Example
<jca:renderTable model="${tableModel}" showCustomViewLink="false"/>

Configuring Tables - Restricting View Creation

In some scenarios it may not make sense to allow the user to create multiple views. By adding singleViewOnly="true" to the describeTable tag, the view drop down will be replaced with a customize table icon that links directly to the edit wizard for the current view. If used, the name step should not be shown and only one view should be loaded OOTB.
Example
<jca:describeTable var="tableDescriptor" id="my.table" configurable="true" singleViewOnly="true" ... >

Configuring Tables - Linking the JSP Table to the Configurable Table Instance

Once the table is implemented, it needs to be registered in application context in order for the infrastructure to find it.

13-54

Windchill Customizers Guide

Example
<Service context="default" name="com.ptc.core.htmlcomp.tableview.ConfigurableTable"> <Option requestor="java.lang.Object" selector="my.table.id" serviceClass="com.ptc.my.ConfigurableTableImpl"/> </Service>

Configuring Tables - Developing Configurable Tables

Though the initial configuration is via Java code (through the ConfigurableTable interface), at runtime, table view information is persisted in the database. The first time that a configurable table is requested, the infrastructure reads in the ConfigurableTable Java class, and persists this information in the database. This means that if changes are made to the configurable table implementation class (to change the OOTB views for example), the configurable table information needs to be cleared from the database in order for the changes to show up. To do this, run the following SQL commands:
DELETE FROM TableViewDescriptor; DELETE FROM ActiveViewLink; commit;

Note that this will delete all user view information from the system, so it should not be used in a production environment. In a production environment you will need to delete the loaded ActiveViewLink and TableViewDescriptor individually. This can be done while the system is running, and things should continue to work.
Configuring Tables - Optimizing a Query Based on the View

If a query should be optimized for a specific table view, a call can be made to get the current selected view for a given table id allowing the query to adjust accordingly.
//The result is the resource bundle key that has the localizable names of the view. String result = com.ptc.core.htmlcomp.components.TableViewBean.getCurrentView("car ambola.appcontext.report");

Configuring Tables - Available Attributes

The AvailableAttributes.xml files define the attributes available for each type. Adding or removing attribute definitions from this file will affect the list of attributes available when creating or editing table views. The main AvailableAttributes.xml file is located at:
\wt_ma_services\modules\CoreHtmlComp\src_web\com\ptc\core\ htmlcomp\createtableview\AvailableAttributes.xml

It is recommended that you define customized attributes in a new file and then register that file as follows in your site.xconf:
<AddToProperty name="com.ptc.core.htmlcomp.createtableview.AvailableAttributesDig

Presenting Information in the UI

13-55

ester.fileLocation" value="ext/config/attributes/MyPartAttributes.xml" />

To derive the list of available attributes, the available attributes factory first asks your configurable table instance for the list of available types. Using this type list it then builds a list of attribute definitions from those defined in AvailableAttributes.xml for each type.
Debugging

To view debugging information about available attributes, set the following Log4J properties:
log4j.logger.com.ptc.core.htmlcomp.createtableview.AvailableAttrib uteFactory=TRACE log4j.logger.com.ptc.core.htmlcomp.createtableview.AvailableAttrib uteCache=TRACE log4j.logger.com.ptc.core.htmlcomp.util.TypeHelper=TRACE log4j.logger.com.ptc.core.htmlcomp.createtableview.labels=TRACE

To view a listing of available attributes for a given type, use the following report:
http://<machine name>/<WindchillAppName>/netmarkets/jsp/carambola/createtableview/ availableAttributesReport.jsp

Attribute Labels

Any label defined in the AvailableAttributes.xml will be used first. After that the com.ptc.core.htmlcomp.jstable.JSStandardColumnDescriptorFactory is used. The JSStandardColumnDescriptorFactory can retrieve attribute labels for certain common attributes. It is not recommended to edit the JSStandardColumnDescriptorFactory to accommodate attribute labels for Windchill Client Architecture table views. If the JSStandardColumnDescriptorFactory can not find a label for the attribute, it will attempt to find a label in com.ptc.core.ui.componentRB using the JCA id as the key. If it still can not find a label for the attribute, it will use the label retrieved from introspection.

13-56

Windchill Customizers Guide

AvailableAttributes.xml Syntax

Map Tag Defines attribute id mappings between legacy JS Tables and Windchill Client Architecture ids. JS ids are defined in JSPropertyDataConstants and are needed to maintain backward compatibility with older CADX tables. Windchill Client Architecture ids should match those used for data utilities. Child of the Class tag.
Syntax Element Description

id jsId

Windchill Client Architecture id. Required. JS id. Required.


<Map id="type_icon" jsId="objType"/>

Class Tag Encompasses attribute definitions for the declared type.


Syntax Element Description

name

The type. This can be either a hard or soft type and should be formatted as a TypeIdentifier. Required.
<Class name="wt.part.WTPart">

Attribute Tag Defines an attribute for the given type causing this attribute to be available to users when they are creating and editing table views. Child of the Class tag.
Syntax Element Description

id

Windchill Client Architecture id. This should match the id that id mappings for things such as validators or data utilities are mapped to. Required.
<Attribute id="description"/>

schemaId

If the id does not match the modeled attribute name, the schemaId should be set to the attribute name. This id needs to work with both webjects (logical attribute should exist) and BeanUtils (getter and setter should exist for the type).
<Attribute id="creator" schemaId="creator.name"/>

Presenting Information in the UI

13-57

Syntax Element

Description

type boolean date list text

The type of the attribute. This will affect what kind of criteria is available when creating filter criteria. Displays a true or false dropdown. Displays the date picker. Displays a drop down of the enumerated type values. See enumClass. Displays a text field.
<Attribute id="iterationInfo.latest" type="boolean"/>

enumClass

When type is set to "list", an EnumeratedType class must be supplied to populate the list of possible values.
<Attribute id="category" schemaId="theCategory" type="list" enumClass="wt.change2.Category"/>

Include Tag Includes the attribute definitions defined within another Class tag. Child of the Class tag.
Syntax Element Description

name

The name of the class to include attribute definitions from. Required.


<Include name="wt.enterprise.RevisionControlled"/>

Label Tag Defines a key and a resource bundle or EnumeratedType to retrieve the attribute's label from. Child of the Attribute tag.
Syntax Element Description

resource

Resource bundle location.


<Label resource="com.ptc.core.ui.viewRB" key="ICON"/>

13-58

Windchill Customizers Guide

Syntax Element

Description

enumClass

Enumerated type class to retrieve label from.


<Label enumClass="wt.project.Role" key="CHANGE ADMINISTRATOR I"/>

key

Key of attribute label within the supplied resource. Required.


<Label resource="com.ptc.core.ui.viewRB" key="ICON"/>

Troubleshooting Common Attribute Problems

The label of my attribute is "???attribute id???" in the create/edit view wizard available column list Enable the table view label logging:
log4j.logger.com.ptc.core.htmlcomp.createtableview.labels=TRACE

Review the process used to find attribute labels and ensure the label for your attribute is defined in one of those locations. The column name in my table is incorrect Try enabling the common components label logging:
log4j.logger.com.ptc.core.components.labels=TRACE

It is up to the data utility defined to retrieve the label for the table column header. When I edit my OOTB view, my attribute does not appear as a selected column despite being included in the active view If you've edited your OOTB view definitions, you need to reset your table views. Otherwise it is possible that the table view class is loading OOTB views with incorrect ids. Ensure you are using the ids defined in DescriptorConstants.ColumnIdentifiers.
Configuring Tables Enable Scrolling

The table can be made scrollable by using the scroll attribute of the renderTable tag. You can provide a boolean value for this attribute. true value will provide scrolling whereas false does not.
<renderTable model="${tableModel}" scroll="true" />

Configuring Tables Accessibility compliance

If developers are writing any custom code that generates HTML (e.g. data utility generating HTML), then it should be ensured that the html is Section 508

Presenting Information in the UI

13-59

compliant. Section 508 compliance standards provide guidelines to generate accessible HTML. The default HTML generated by Table component is complying to these standards.
Configuring Tables Enable Table Count

The number of objects in the table (count) is normally provided in the title bar area. You can remove this using the showCount attribute of the renderTable tag. It takes a boolean value. true value will provide the table count whereas false does not.
<renderTable model="${tableModel}" showCount="true" />

Configuring Tables Hiding column of the table

Table component gives us the flexibility to hide any of the column displayed the in the table as per the user requirement. This can be done by setting the value of the attribute hidden to true in the tag <jca:describeColumn> . By default, this value is false. The code for the same is as follows.
<jca:describeColumn id="number" hidden="true"/>

Configuring Tables Display view all link

The Table footer can display View Entire List link, which would allow the user to see the entire data. When View Entire List link is displayed, Pagination is not displayed. To enable this link, specify viewAllLink parameter in <renderTable>.
<jca:renderTable model="${tableModel}" viewAllLink="netmarkets/jsp/work/listAssignments.jsp" helpContext="Overview_Assignments_Help" showPagingLinks="${tableShowPagingLinks}" pageLimit="${param.maxRows}"/>

You must specify the jsp name in the "viewAllLink" parameter. When the user clicks on "View All" in the Table footer, the user is taken to the JSP mentioned in this parameter and that JSP would display list of all items in the Table. All the Home -> Overview tables use "viewAllLink" parameter. You can disable the footer by adding "jcaPageModel.setPageFooter("false")" in the jsp after the include of begin.jspf.
Configuring Tables Customize Preferences

To see Table preferences, navigate to Utilities Page > Preference Manager. One can see a section of table related properties.

Some of the available Table preferences are:

13-60

Windchill Customizers Guide

Assignment Table Size: Indicates the actual number of assignments to fetch. This preference is ignored if it is less then the overview table size. Overview Table Size: The overview sub tab under the home tab contains three summary tables with limited rows in them. This preference controls the number of rows in these tables. The default is seven. Paging Limit for Tables: Controls the number of rows to display per page in tables that have paging. It only affects tables that have paging turned on by default. The number of rows per page can be temporarily overridden by using the all link in the paging section. View All Table Size Limit: View All Table Size Limit

Configuring Table - Freeze Column and Selected Only view

Tables can be configured so as to support "Freeze Column" and "Selected Only" view. It's a toolbar level menu which allows user to freeze columns there by switching to "Freeze column" menu as well as "Unfreeze" those there by switching to "Unfreeze Columns" menu. The "Freeze columns" menu can be configured either through view manager (for table with views) and through "isFreezable" attribute of tag "describeTable". (For tables without view) . The selected only menu allows user to select multiple rows across multiple pages. User when switches to "Selected only" view, can see the rows across multiple pages in "Full List" mode. The selected only view is enabled only when the table has rows which are multi selectable.

Limitations
None.

Presenting Information in the UI

13-61

Sample Code
<%@ <%@ <%@ <%@ <%@ <%@ include file="/netmarkets/jsp/util/begin.jspf"%> taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> taglib uri="http://www.ptc.com/windchill/taglib/carambola" prefix="cmb"%> taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> taglib uri="http://www.ptc.com/windchill/taglib/core" prefix="wc"%>

<fmt:setLocale value="${localeBean.locale}"/> <fmt:setBundle basename="com.ptc.carambola.carambolaResource"/> <fmt:message var="tableName" key="PART_TABLE_LABEL"/> <fmt:message var="actionsName" key="ACTIONS_COLUMN_LABEL"/> <%-->Build a descriptor and assign it to page variable tableDescriptor<--%> <describeTable var="tableDescriptor" type="wt.part.WTPart" id="netmarkets.test.table" label="${tableName}" > <describeColumn id="name"/> <describeColumn id="number"/> </describeTable> <%-->Get a query command and assign it to page variable queryCommand<--%> <cmb:getTypeInstanceCommand var="queryCommand" descriptor="${tableDescriptor}"/> <%-->Get a table model using our descriptor and query command, assign model to page variable tableModel<--%> <getModel var="tableModel" descriptor="${tableDescriptor}" queryCommand="${queryCommand}"/> <%-->Render the table model<--%> <renderTable model="${tableModel}"/> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

13-62

Windchill Customizers Guide

Examples of Usage in Windchill Code


Table Description Location

Search results table

This table can be accessed by executing simple or advance search. This table can be accessed by clicking on Folders subtab from Program/Product/Project/Orga nization tab. This table can be accessed by clicking on Overview subtab on Home tab. This table can be accessed by clicking Edit structure action on any part info page. This table can be accessed by clicking Advanced Search.

JSP: <Windchill>/netmarkets/jsp/se arch/executeSearch.jsp JSP (For Product tab): <Windchill>/netmarkets/jsp/pr oduct/listFiles.jsp

Folder browser table for Project, Product, Organization

Assignments table on Home -> Overview

JSP: <Windchill>/netmarkets/jsp/w ork/listOverviewAssignments.j sp JSP: <Windchill>/netmarkets/jsp/pa rt/tabular_input.jsp JSP: <Windchill>/codebase/netmar kets/jsp/search/queryBuilder.js p

Tabular Input Edit Structure

Search Criteria / Query Builder Table

Other Resources
Adding Actions and Hooking Them Up in the UI chapter (starting on page 11-1) Customizing the UI with Ajax (on page 10-4) Data Acquisition Configuration Properties (on page 12-2)

Presenting Information in the UI

13-63

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, 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

13-64

Windchill Customizers Guide

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

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.
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.

Scope/Applicability/Assumptions
It is assumed that your <MyPage>.jsp file in which you are implementing the Windchill Client Architecture tree includes /netmarkets/jsp/begin.jspf file and /netmarkets/jsp/end.jspf files

Presenting Information in the UI

13-65

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: JSP, JavaScript and Custom taglibs. The actions framework in the Windchill client architecture. Windchill Client Architecture Table component. Configuring views. Data acquisitions, Data Utility, GUI component.

13-66

Windchill Customizers Guide

Solution Elements

Element <your_page>.jsp <your>service.properties.x conf <your>action.rbInfo <your>actions.xml <your>actionModels.xml

Type JSP xconf rbInfo xml xml

Description Your Windchill Client Architecture Tree implementation JSP file. DataUtilities and services are defined here. Action attributes defined here. Actions can be defined here. Action models can be defined here.

Another key constituent in the solution is the TreeHandler, which is responsible for populating the tree content. These are the methods of a TreeHandler that you must implement: 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 icon 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

Presenting Information in the UI

13-67

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; 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; }

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 its 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. In the given example, the method first checks to see if the configSpec is not initialized from the previous method. If it isnt, then it calls the getDefaultConfigSpec method, which gets the default ConfigSpec from the

13-68

Windchill Customizers Guide

WTPart class via the ConfigHelper. A Map variable named result is then initialized. This will store the mapping of the child nodes for each of the parent nodes and is returned. A three-dimensional array is also initialized using the getUsesWTParts method from the WTPartHelper class. This method navigates from many used-by parts (parents) to their uses part masters (children) and applies a ConfigSpec to select the Iterations of the uses parts. It returns a 3D array of Persistable objects where the first dimension corresponds to the used-by parts passed in. The second dimension corresponds to the part usage links from the used-by part. The third dimension is a two element array where [0] is the WTPartUsageLink and [1] is the uses WTPart or WTPartMaster if the ConfigSpec did not select an iteration of the uses part. After the 3D array is initialized, it continues by iterating through the List of parent nodes. A 2D array of Persistable named branch is initialized that stores the child nodes of the given parent if any exist. If no children exist, it will continue to the next iteration. If children do exist, they are added to an ArrayList named children. Lastly, the parent nodes with its corresponding children are added to the Map, and the Map is returned.
public Map<Object,List> getNodes(List parents) throws WTException { if (configSpec == null) { configSpec = getDefaultConfigSpec(); } Map<Object,List> result = new HashMap<Object,List>(); //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);

Presenting Information in the UI

13-69

Custom tree handlers need to be registered. 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 doesnt 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 see the NmObject Utilities section in the Gathering the Data for the UI chapter on page 12-15 for more information. 2. Your Element will have an attribute named "nmObject" with its value an instanceof NmObject Otherwise, to show non-persistables, you can write a wrapper class extending from NmObject and override getOid() method to return proper NmOid.

Procedure Configuring Windchill Client Architecture Tree


Building the shell - Include necessary artifacts

You should include the necessary artifacts in your configuring JSP file e.g. /netmarkets/jsp/begin.jspf and /netmarkets/jsp/end.jspf file. You also need to declare tree taglib directive.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ include file="/netmarkets/jsp/util/begin.jspf"%> ----------<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Configure Tree

This can be structured into three steps 1. Creating tableTree descriptor object using describeTableTree tag. a. This tag creates the tableTree descriptor object and assigns it to the page variable specified by the var attribute b. The id attribute stores the identifier for this table descriptor.

13-70

Windchill Customizers Guide

c. The label attribute is the localized label for this component and is displayed as the table header in the UI. d. The columns in the table are produced by adding the describeColumn subtag. The id attribute for this tag is used to look up default properties for the column.
id="wcaDemo_tree_example4" var="wcaDemo_tree_descriptor4" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" expansion="full" helpContext="DEFAULT_HELP_PAGE" disableAction="false" summary="test"> <jca:setComponentProperty key="selectable" value="true"/> <jca:setComponentProperty key="actionModel" value="wcaDemo_tree_toolbar"/> <jca:describeColumn id="number" /> <jca:describeColumn id="name" /> </jca:describeTableTree> <jca:describeTableTree

2. Defining the component model by passing the tableTree descriptor into the getModel tag. a. This takes the tableTree descriptor to get the tableTree data and returns a model object that will be used to render the tree b. The tableTree descriptor variable must be specified in the descriptor attribute. c. The treeHandler attribute is used to specify the JAVA API service class that retrieves the tree data.
<jca:getModel var="wcaDemo_tree_model4" descriptor="${wcaDemo_tree_descriptor4}" treeHandler="wcaDemoTreeHandler1"/>

3. Rendering the tableTree by passing the model object into the renderTableTree tag. a. The variable for the model object specified in the getModel tag gets passed into the model attribute. b. If the model attribute is not specified, then a NmHTMLTableTree must be specified using the tree attribute instead.
jca:renderTableTree model="${wcaDemo_tree_model4}" showTreeLines="true" />

Your entire JSP will be


<%@ taglib uri="http://www.ptc.com/windchill/taglib/component" prefix="jca"%>

Presenting Information in the UI

13-71

<%@ include file="/netmarkets/jsp/util/begin.jspf"%> ------<!-- TREE CONFIGURE START --> <%-->Build a descriptor and assign it to page variable treeDescriptor<--%> <jca:describeTableTree id="wcaDemo_tree_example4" var="wcaDemo_tree_descriptor4" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" expansion="full" helpContext="DEFAULT_HELP_PAGE" disableAction="false" summary="test"> <jca:setComponentProperty key="selectable" value="true"/> <jca:setComponentProperty key="actionModel" value="wcaDemo_tree_toolbar"/> <jca:describeColumn id="number" /> <jca:describeColumn id="name" /> </jca:describeTableTree>

<%-->Get a component model for our tree<--%> <jca:getModel var="wcaDemo_tree_model4" descriptor="${wcaDemo_tree_descriptor4}" treeHandler="wcaDemoTreeHandler1"/>

<%-->Render the NmHTMLTableTree from the command<--%> jca:renderTableTree model="${wcaDemo_tree_model4}" showTreeLines="true" /> <!-- TREE CONFIGURE END --> ------<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Customization Points describeTableTree tag attributes


describeTableTree describes a tree component that can be plugged into Windchill Client Architecture getModel tag. Its tag class is

13-72

Windchill Customizers Guide

com.ptc.core.components.tags.components.DescribeTableTreeTag and the body content is scriptless.


Parameter id Default Value Possible Values Any java.lang.String value Req? Yes Description The identifier for this tree descriptor. If this tree supports configurable views, then this id may be used to look up the view configurations, unless it is overridden by configurableTableId attribute. This id is also used to define the NmObjectUtility for the tree if required. Name of the exported scoped variable for the descriptor. The type of the variable is com.ptc.core.components.descriptor. ComponentDescriptor. The name of the scope to export the var attribute to.

var

Any java.lang.String value

Yes

scope

request

Can be (caseinsensitive): page, request, session or application -

No

type

No

Name of the main type of object displayed in this tree. This can be either a modeled or a soft type. When specified, the infrastructure will use the type to look up labels and other default values when it can't find them otherwise. A localized display label for this component The name of one of the modes defined in the com.ptc.core.ui.resoureces.Compone ntMode enum. The name of one of the component types defined in the com.ptc.core.ui.resoureces.Compone ntType enum. The name of the column that will be used to display node labels. The column value must be an NmString or a TextComponent.

label

Any java.lang.String value

No

mode

VIEW

No

componentType

TABLE

No

nodeColumn

name column

No

Presenting Information in the UI

13-73

Parameter configurable viewId

Default Value false -

Possible Values boolean -

Req? No No

Description Whether or not this tableTree supports configurable views. The id to use to look up configurable views. If unspecified, then defaults to the tree id. Only used if configurable is set to "true" Determines whether to launch the view manager or view edit wizard. The edit wizard is launched directly when you have a tree that does not support having multiple views, but still wants to allow the user to select columns and set sort order. The name of the action model to use for toolbar actions. The name of the action model to use for menubar actions. The help context for this tree. No help icon will be displayed if no help context is specified.

singleViewOnly

false

boolean

No

toolbarName

Any java.lang.String value Any java.lang.String value Any java.lang.String value

No

menubarName

No

helpContext

No

13-74

Windchill Customizers Guide

Parameter targetObject

Default Value

Possible Values

Req? No

Description Allows the developer to provide more objects for a tree row. Typically, the infrastructure treats each index of the array returned by the getModel tag's API as a "row" object. This row object is passed to each column's DataUtility. If a different object is needed for some DataUtilities then that object can be specified as the targetObject in the describeTableTree or describeColumn tag. The original row object must have a getter method for the name specified as the target object. (i.e. targetObject="my_related_part" would mean the object needs a getMy_related_part() method). The target object will be used in the following places: The row object supplied to data utilities. The object that soft attributes will be extracted from The context object for the row checkbox

selectionObject summary String

No No

Deprecated A localized summary of this table, which is used for accessibility compliance. Controls the initial expansion level of the tree. none (fully collapsed), one (first level of tree is expanded), full (tree is fully expanded). Flag to indicate enable or disable collapse/expand action.

expansion

full

none, one or full

No

disableAction

false

boolean

No

getModel tag attributes


getModel Creates a component model based on the supplied component descriptor. The resulting model is assigned to a scoped variable specified by the var attribute. Its tag class is

Presenting Information in the UI

13-75

com.ptc.core.components.tags.components.GetModelTag and the body content is scriptless.


Paramter var Default Value Possible Values Any java.lang.String value Can be (caseinsensitive): page , request, session or application Is of Type com.ptc.core.comp onents.descriptor.C omponentDescript or Req? Yes Name of the exported scoped variable for the descriptor. The name of the scope to export the var attribute to.

scope

request

No

descriptor

Yes

The descriptor to base the component model on

treeHandler

No

The selector for the TreeHandler to use to build the data model. The tree handler should be registered in application context

renderTableTree tag attributes


renderTableTree renders a netmarkets tree. If the var attribute is set, then the tag will set a page-scoped attribute with an NmHTMLTableTree based on the supplied ComponentModel. If the var tag is empty, then the NmHTMLTableTree is created and drawn. The tag also supports drawing a pre-built NmHTMLTableTree by specifying the tree attribute. Its tag class is com.ptc.core.components.tags.components.RenderTableTreeTag and the body conetent is scriptless.
Paramter var Default Value Possible Values Any java.lang.String value Can be (caseinsensitive): page , request, session or application Req? No The name of the scoped variable to assign the NmHTMLTableTree to. If this is not specified, then the tree is drawn by the tag. The name of the scope to export the var attribute to.

scope

request

No

13-76

Windchill Customizers Guide

Paramter model

Default Value -

Possible Values Of type com.ptc.core.comp onents.descriptor.C omponentModel

Req? No The component model to create (and optionally draw) an NmHTMLTableTree from. If unspecified, then an NmHTMLTableTree must be specified using the tree attribute. The NmHTMLTableTree to render. If this is not specified, then a ComponentModel must be specified from which a tree will be created. The help context for this tree. No help icon will be displayed if no help context is specified. Whether or not to trail-enable links in the tree. The preference context for this tree Single Select mode. Use Radio buttons or checkboxes for the row selection. Determines whether or not to show the customize view link in the view drop down. Specifies that the table should use scrollbars to keep the header and actions in view when looking down at the items in the bottom of the table. Optionally show the count of objects in the table title area. Whether objectHandles are needed for each row. By default, the value of this attribute is false. Set to true to render a table for creating/editing multiple objects in a create/edit wizard. JavaScript method to execute after the table has been rendered or rerendered as a result of sorting etc.

tree

Of type com.ptc.netmarkets .util.treetable.NmH TMLTableTree Any java.lang.String value boolean boolean

No

helpContext

No

useTrail preferenceConte xt singleSelect

false false

No No No

showCustomVie wLink scroll

true

boolean

No

false

boolean

No

showCount rowBasedObject Handle

true false

boolean boolean

No No

afterJS

No

Presenting Information in the UI

13-77

Paramter showPagingLink s pageLimit showTreeLines

Default Value false

Possible Values

Req? No No Determines whether the tree is paged. The number of rows to display per page in the tree. Determines if tree lines will be displayed to show structure in the tree The maximum number of rows to display per page in the tree when the full list action is clicked. The number can be set to a level so as to keep the browser from crashing. It is used to get some out of the box features; explained in the Configuring Tree - useJSCA property section on page 13-88

false

boolean

No

fullListLimit

integer

useJSCA

false

boolean

Configuring Tree Defining Node Column


The id of the column that you want to display node labels should be given to the nodeColumn attribute from the describeTableTree tag.
<jca:describeTableTree id="wcaDemo_tree_example4" var="wcaDemo_tree_descriptor4" type="wt.part.WTPart"label="${treeName}" nodeColumn="number" configurable="true"expansion="full" --------->

-----</jca:describeTableTree>

Configuring Tree Adding ToolBar


To add a tool bar, the toolbarName attribute from the describeTableTree tag must be included. The name of action model to use for the tool bar actions is specified in this attribute.
<jca:describeTableTree id="wcaDemo_tree_example5" var="wcaDemo_tree_descriptor5" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" singleViewOnly="true"expansion="one" disableAction="false" menubarName="wcaDemo_tree_menubar" toolbarName="wcaDemo_tree_toolbar" >

-----</jca:describeTableTree>

13-78

Windchill Customizers Guide

Adding toolbar to a tree can also be achieved by using setComponentProperty tag. Its a helper tag that sets properties on the component descriptor managed by a parent describe tag. The key attribute and the value attribute are the key and value for the properties map of the target ComponentDescriptor, respectively. 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. Please see the Windchill Client Architecture Action Framework Overview section in the Adding Actions and Hooking Them Up in the UI chapter on page 11-1 for more information.
<jca:describeTableTree id="wcaDemo_tree_example4" var="wcaDemo_tree_descriptor4" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" expansion="full" helpContext="DEFAULT_HELP_PAGE" disableAction="false" summary="test"> <jca:setComponentProperty key="actionModel" value="wcaDemo_tree_toolbar"/> -----</jca:describeTableTree>

Configuring Tree Adding MenuBar


To add a menu bar, the menubarName attribute from the describeTableTree tag must be included. The name of action model to use for the menu bar actions is specified in this attribute.
<jca:describeTableTree id="wcaDemo_tree_example5" var="wcaDemo_tree_descriptor5" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" singleViewOnly="true"expansion="one" disableAction="false" menubarName="wcaDemo_tree_menubar" toolbarName="wcaDemo_tree_toolbar" >

-----</jca:describeTableTree>

Presenting Information in the UI

13-79

Configuring Tree Adding Row Level Actions


To add row level actions column, you need to define a column using describeColumn which has id=nmActions. Using the setComponentProperty tag, set the actionModel. Please refer Refer <Action/ ActionModel Document> for more information.
<jca:describeTableTree id="wcaDemo_tree_example2" var="wcaDemo_tree_descriptor2" type="wt.part.WTPart" label="${treeName}" nodeColumn="name" expansion="one"> ------------<jca:describeColumn id="nmActions" label="Actions" sortable="false"> <jca:setComponentProperty key="actionModel" value="read only BOM"/> </jca:describeColumn> </jca:describeTableTree>

Configuring Tree Enabling selectable rows


Making the rows selectable can be easily done by adding another setComponentProperty tag. The key attribute must be set to selectable and the value attribute must be set to true
<jca:describeTableTree id="wcaDemo_tree_example2" var="wcaDemo_tree_descriptor2" type="wt.part.WTPart" label="${treeName}" nodeColumn="name" expansion="one"> <jca:setComponentProperty key="selectable" value="true"/> <jca:describeColumn id="name" /> -------</jca:describeTableTree>

Windchill Client Architecture Selectable & Non-Selectable Trees

13-80

Windchill Customizers Guide

Configuring Tree Enabling sort able columns


Making the columns sortable can be done by using the sortable attribute of describeColumn tag. The value attribute must be set to true to make it sortable and false to make it non-sortable.
<jca:describeColumn id="name" sortable="false"/>

Configuring Tree Specify DataUtility for columns


To specify the data utility for a column can be done by using dataUtilityId attributes of the descriveColumn tag.
<jca:describeColumn id="columnId" label="${columnName}" dataUtilityId="your_column_data_utility_id" />

Custom data utilities need to be registered. Following is a sample data utility entry.
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="your_data_utility_class" requestor="your_object" selector="your_column_data_utility_id" cardinality="duplicate"/> </Service>

Configuring Tree Enabling views


1. To make a tree configurable you must explicitly specify that while defining the tableTree descriptor. This can be done by adding a configurable="true" attribute to the describeTableTree Tag. 2. Your view implementation needs to be registered in application context in order for the infrastructure to find it. If you have specified viewId attribute explicitly, then that should be used as the selector, if not id attribute.
<jca:describeTableTree id="wcaDemo_tree_example5" var="wcaDemo_tree_descriptor5" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" -----configurableTableId="wcaDemo_tree_viewId1"> -------</jca:describeTableTree>

3. Custom view implementation helpContext keys need to be registered. Following is a sample entry.
<Service context=default name="com.ptc.core.htmlcomp.tableview.ConfigurableTable"> <Option serviceClass="your_ConfigurableTableImpl_class" requestor="your_object" selector="your_view_id" /> </Service>

Presenting Information in the UI

13-81

4. When implementing getOOTBTableViews and defining out-of-the-box 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 Attribute Report:
http://<server>:<port>/<context>/netmarkets/jsp/carambola/creat etableview/availableAttributesReport.jsp

5. You can control the visibility of Customize link in the view drop down by using showCustomViewLink attribute of renderTableTree tag. false hides the link whereas true shows the link which is the default behavior.
<jca:renderTableTree model="${wcaDemo_tree_model6}" showCustomViewLink ="true" />

6. If the tree has only one view and you want to modify the columns (visibility, order etc), you need to set singleViewOnly attribute of describeTableTree tag to true.
<jca:describeTableTree id="wcaDemo_tree_example5" var="wcaDemo_tree_descriptor5" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" configurable="true" singleViewOnly ="true" -----configurableTableId="wcaDemo_tree_viewId1"> --------

13-82

Windchill Customizers Guide

</jca:describeTableTree>

Tree with views

Tree with single view customize

Configuring Tree Control Level of Tree Expansion


When the Tree is populated and presented for the first time, you can control the level to which its expanded. 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.
<jca:describeTableTree id="wcaDemo_tree_example5" var="wcaDemo_tree_descriptor5" type="wt.part.WTPart" label="${treeName}" nodeColumn="number" expansion=none ------ > -------</jca:describeTableTree>

Configuring Tree Adding Help


Tree can be enabled with help either by using describeTableTree tag or by using renderTableTree tag. If you define using both the tags, the latter will be respected.
<jca:describeTableTree id="wcaDemo_tree_example4" ----helpContext ="your_help_context_key" > -----</jca:describeTableTree>

Presenting Information in the UI

13-83

<jca:renderTableTree model="${wcaDemo_tree_model4}" helpContext ="your_help_context_key" />

Custom helpContext keys need to be registered. Following is a sample helpContext key entry.
<Service context="default" name="wt.help.HelpTemplate"> <Option requestor="your_object" selector="your_help_context_key" resource ="online.cust.helpFile"/> </Service>

This means that the help file is $WT_HOME/codebase/wt/helpfiles/help_<locale>/online/cust/helFile.html

Configuring Tree Hide Expand/Collapse icon


Expand/collapse icon presentation is controlled by using disableAction attribute of the describeTableTree tag. You can provide a boolean value for this attribute. true value will present the expand/collapse icon whereas false value will hide them.
<jca:describeTableTree id="wcaDemo_tree_example3" var="wcaDemo_tree_descriptor3" type="wt.part.WTPart" label="${treeName}" nodeColumn="name" expansion="none" disableAction="true" ---->

-----</jca:describeTableTree>

Configuring Tree Enable Scrolling


The tree can be made scrollable by using scroll attribute of the renderTableTree tag. You can provide a boolean value for this attribute, true value will provide scrolling whereas false not.
<jca:renderTableTree model="${wcaDemo_tree_model2}" scroll="true" />

Configuring Tree Set single/multi select


The trees row selection is controlled by using singleSelect attribute of the renderTableTree tag. You can provide a boolean value for this attribute, true value will present the tree in a single select (radio buttons) mode whereas a false value will present it in a multi select (checkboxes) mode.

13-84

Windchill Customizers Guide

<jca:renderTableTree model="${wcaDemo_tree_model2}" singleSelect="true" />

Single & multi select Windchill Client Architecture Tree

Configuring Tree Enable Tree Count


The number of objects in the tree(count) is normally provided in the title bar area. You can remove them using showCount attribute of the renderTableTree tag. It takes a boolean value. true value will provide the tree count whereas false does not.
<jca:renderTableTree model="${wcaDemo_tree_model3}" showCount="false" />

Configuring Tree Enable Tree Lines


You can show tree lines to display the structure in the tree by using showTreeLines attribute of the renderTableTree tag.

Presenting Information in the UI

13-85

<jca:renderTableTree model="${wcaDemo_tree_model2}" showTreeLines="true" />

Windchill Client Architecture Tree with and without Tree Lines & Count

Configuring Tree Disable selection for some tree rows


You may require your tree to be presented with some rows pre-selected. This can be achieved by using getNonSelectables tag in combination with renderTableTree parent tag. The name of the service class that does the processing should be provided for the className attribute and the name of the method should be provided for the methodName attribute. The signature of the method should be public static ArrayList<NmOid> your_method_name( NmModel nmModel ) throws WTException 1. Create NmHTMLTableTree from component model.
<jca:renderTableTree var="wcaDemo_tree_nmModel6" model="${wcaDemo_tree_model6}" > <jca:getNonSelectables className = "com.ptc.carambola.svc.wcaDemoTreeHandler2" methodName ="getPartNonSelectables" /> </jca:renderTableTree>

2. Render the NmHTMLTableTree

13-86

Windchill Customizers Guide

<jca:renderTableTree tree="${wcaDemo_tree_nmModel6}" model="${wcaDemo_tree_model6}"/> public static ArrayList<NmOid> getPartNonSelectables( NmModel nmModel ) throws WTException { ArrayList<NmOid> nmOid_list = null; NmDefaultHTMLTableTree table_tree = (NmDefaultHTMLTableTree)nmModel; NmDefaultHTMLTable table = (NmDefaultHTMLTable)table_tree.getTable(); for (int i = 0; i < table.getRowCount(); i++) { NmObject nmObj = (NmObject)table.getObject(i); if(nmObj instanceof NmPart){ NmPart nmPart = (NmPart)nmObj; //your logic goes here if((number_string.lastIndexOf("2")!= -1) || (number_string.lastIndexOf("4")!= -1) ) { if(nmOid_list == null) nmOid_list = new ArrayList<NmOid>(); //add the NmOid into the List nmOid_list.add(nmObj.getOid()); } } } return nmOid_list; }

Configuring Tree Enable the Pagination


There are three ways to make a tree paginated Use pageLimit attribute of getModel/getIeModel tag. This usage is highly recommended for performance reasons. The componentModel that you get from this tag which will be passed to the renderTableTree will have only objects specific for the page to be displayed. Use pageLimit attribute of renderTableTree tag. Note that this attribute is not supported in renderSimpleTree tag. If the pageLimit attribute is specified in getModel/getIeModel, then there is no need to specify it again at this tag level; even if you have specified it won't be respected. Use of the property available in <Windchill>\codebase\wt.properties
com.ptc.netmarkets.treeSizeLimit = <integer value>

Using this you can set the number of rows of a tree in a page and this will be applicable to all the trees across Windchill system. Its usage is highly discouraged and in the coming release this property will be deprecated.

Presenting Information in the UI

13-87

Configuring Tree - Describe the scroll type of a tree


You can specify the type of scrollbars on a tree by setting scrollType property in "describeTableTree" tag. Possible values of scrollType are ""V" for Viewport ""D" for DOM ""default" for browser default.

<jca:describeTableTree id="wcaDemo_tree_example3" > <jca:setComponentProperty key="scrollType" value="V"/> </jca:describeTableTree>

For popup pages, the default scrollType is DOM. But, it is recommended to use Viewport. Also. it is recommended to use "Viewport" scrollType in case of non editable form fields.

Configuring Tree - useJSCA property


You can set useJSCA property to true to get following out of the box features on tree. 1. Selection across the pages. a. Selection is persisted across pages for a paginated tree. If a user selects some objects (say 5) on a page (say page 1), navigates to some other page (say page 3) and selects some more objects (say 3), than the row count information in the table footer will show '8 of 120 total objects selected' (where 120 is the total number of rows in the table across all pages). Again if the user navigates back to initial page (i.e. page 1), he / she will see the objects (i.e. 5) visually selected. b. Selection is persisted across table paging modes. If user makes some selections across pages in a paginated tree and moves to full list view or vice versa, the appropriate objects remain visually selected. c. Selection is NOT persisted in case of view change. If user makes some selections in a paginated tree or full list tree and decides to change the tree view from the drop down list, the selections would not be retained. A confirmation alert message will be shown and the tree view will be changed only if the user agrees to proceed. d. Table footer row count information will be different for paginated tree and full list tree.

13-88

Windchill Customizers Guide

If the tree is paginated, the row count message shown in the tree footer will be format 'X of Y total objects selected'. But for the full list trees the row count message will be 'X objects selected'. e. Actions can be performed on selections made across pages for a paginated tree. The tree toolbar level and menu level actions would be performed on all the selections that the user has made across all pages of the tree. f. Client side JavaScript function to fetch all selected object information. A JavaScript function named getSelectedItems() can be used to fetch selected objects from all the tree present in a page. Another function named getJCASelectedTableItems(tableId) can be used to fetch selected objects for a particular tree. 2. Clear all selections Clear across pages feature is used to clear all the checkbox selections across multiple pages. This feature is provided for the trees where paging is enabled. Clear all selection feature will be disabled if there are no checkbox selections available and it will get enable as soon as user selects checkbox. With this feature user can reduce the pain of deselecting checkboxes individually. 3. Preserving right-left scroll position For paging trees If the tree had no selected rows: If the user is on page X then, tree refresh resulted because of sort action will show the tree vertically positioned at the first row of the first page. If the tree had selected rows: When the tree is refreshed because of sort action, the tree will page to the page that contains the last of the pre-sort selected rows. The selected rows will be retained. If the tree is a scrolling tree, i.e. do not have pagination enabled or a full list tree If the tree had no selected rows: On sort action, the tree will be positioned at the first row in the tree. If the tree had selected rows: On sort action, the table will scroll to show the last row that was selected. The selections are retained

Presenting Information in the UI

13-89

4. Multi column click to sort "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. 5. Paging controls in table header User can add the paging links in header. This option can be set through preference manager. By default this option is disabled and if set it will display the paging links in header as well as footer. 6. Find In List One can find an object in tree.

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

13-90

Windchill Customizers Guide

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 Handling on page 13-2 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

Presenting Information in the UI

13-91

Attribute Tables
Objective
This design pattern 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 design pattern 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 design pattern should have a basic understanding of JSP, tag libraries and JSTL.

Consequences
By following this design pattern 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 objects 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.

Packaging
The attributes table component itself is located in the Windchill vob under the CommonComponents module:
ProjectLink\NetMarkets\src_web\netmarkets\jsp\object\attribute.jsp (the default attributes table) ProjectLink\NetMarkets\src_web\netmarkets\jsp\util\ showSoftAttribute.jsp (the attributes table component)

13-92

Windchill Customizers Guide

Windchill\DevModules\CommonComponents\src\com\ptc\core\components\ beans\AttributesTableBean.java Windchill\DevModules\CommonComponents\src\com\ptc\core\components\ util\ComponentUtility.java Windchill\DevModules\CommonComponents\src_web\com\ptc\core\ components\tags\core\TypeBasedImportTag.java Windchill\DevModules\CommonComponents\src_web\WEB-INF\tags\ core.tag Windchill\DevModules\CommonComponents\src_web\WEB-INF\tlds\ components.tld

Here are the locations of some example info pages:


ProjectLink/Netmarkets/src_web/netmarkets/jsp/document/attributes. jsp ProjectLink/Netmarkets/src_web/netmarkets/jsp/part/attributes.jsp codebase/netmarkets/jsp/document/attributes.jsp codebase/netmarkets/jsp/part/attributes.jsp

What is the component


It 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.

Presenting Information in the UI

13-93

Using the component


Create a JSP for your object type


Creating a JSP

Creating a JSP Registering the 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. 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-appname>/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.
Registering 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

13-94

Windchill Customizers Guide

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 xconf format:


<!--Info page fragments, Resource is the filepath to a jsp fragment 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" />

Presenting Information in the UI

13-95

<jca:describeProperty id="name"/> <jca:describeProperty id="number"/> <jca:describeProperty id="creatorName" /> <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 soft 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.

13-96

Windchill Customizers Guide

Generating the Name Attribute Server


Objective
You want to make the name attribute server generated.

Background
This section will describe making the name attribute server generated. This attribute is not server generated out of the box. It will make the name attribute behave exactly as the number attribute. This means the name attribute will also respond to other OIRs that only apply to number out of the box, including ServerPreGenerated and Immutable.

Scope/Applicability/Assumptions
Assume you have a need to have the name attribute be server generated.

Intended Outcome
The name attribute is server generated for all objects that have the ServerAssigned constraint specified in the OIR for name.

Solution
Create your own custom DataUtility for the name attribute and set up the required properties.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Data Utilities GUI Components Object Initialization Rules

Solution Elements

Element Site.xconf RuleConfigurableTypeAttribute. properties

Type Configuration Configuration

Description Contains the configuration information required. Contains the rule configurable attribute lists for each object type. codebase/com/ptc/core/rule/server/delegate/init/Rul eConfigurableTypeAttribute.properties

Presenting Information in the UI

13-97

Element GeneratedNameDataUtility

Type Java class

Description The new Data utility that will be created during this procedure to enable Name to support server generation. An out of the box data utility that knows how to handle server generation for the number attribute. \codebase\netmarkets\jsp\document\ createDocumentSetAttributesWizStep.jsp

NumberDataUtility createDocumentSetAttributesWi zStep

Java class JSP file

Procedure Make document name attribute server generated


Confirm your attribute is Rule Configurable.

1. Look in the file


codebase/com/ptc/core/rule/server/delegate/init/RuleConfigurabl eTypeAttribute.properties

2. Find your object type. For this example we are looking for WTDocument and out of the box we have:
wt.doc.WTDocument=number,lifeCycle.id,lifeCycle,teamTemplate,te amTemplate.id,folder.id,organization.id

3. Notice that name is not an attribute that is available for rules so we need to add it in. In your site.xconf file add the following:
<Configuration targetFile="codebase/com/ptc/core/rule/server/delegate/init/Rul eConfigurableTypeAttribute.properties"> <Property name="wt.doc.WTDocument" default="name,number,lifeCycle.id,lifeCycle,teamTemplate,tea mTemplate.id,folder.id,organization.id"/> </Configuration>

Load your Object Initialization Rules

Using the Object Initialization Rules administrator, add the following rules to the OIR for WTDocument:
<!-- set the name to a generated number --> <AttrValue id="name" algorithm="com.ptc.windchill.enterprise.revisionControlled.server. impl.NumberGenerator"> <Arg>{GEN:wt.enterprise.SequenceGenerator:WTDOCUMENTID_seq:10:0 }</Arg> </AttrValue>

13-98

Windchill Customizers Guide

<AttrConstraint id="name" algorithm="com.ptc.core.rule.server.impl.GatherAttributeConstraint s"> <Value algorithm="com.ptc.core.rule.server.impl.GetServerAssignedConstrai nt"/> <Value algorithm="com.ptc.core.rule.server.impl.GetImmutableConstraint"/> </AttrConstraint>

Note: For this purposes of this demonstration we will reuse the number generator that exists out of the box. You will probably want to replace this with your own custom generator. See the online help for the Object Initialization Rules Administrator for additional information.
Create your new Data Utility

The simplest way to get a data utility to use the server generation property is to extend the NumberDataUtility. The minimum amount of code you will need to write is to override the getColumnId method to return your column ID. In our case this is name. So we would create the following data utility.
package com.ptc.carambola.customization.examples.wizard; import com.ptc.core.components.descriptor.DescriptorConstants; import com.ptc.core.components.factory.dataUtilities.NumberDataUtility; public class GeneratedNameDataUtility extends NumberDataUtility { @Override protected String getColumnId() { return DescriptorConstants.ColumnIdentifiers.NAME; } }

Create your new GUI Component

By Default, for the wizards, the NumberDataUtility is returning a NumberInputComponent. For the purposes of this example this component is sufficient. If it is not sufficient for your purposes you can create a custom component. Please see the Implementing a Data Utility section on 13-8 for additional information.
Register your new Data Utility for your attribute

1. Since for this example we only want the name attribute behavior to be changed for documents we will create a new attribute we will call "documentName" to use. In your site.xconf file add the following:

Presenting Information in the UI

13-99

<Configuration targetFile="codebase/com/ptc/core/components/components.dataUtilit ies.properties"> <Option serviceClass=" com.ptc.carambola.customization.examples.wizard.GeneratedNameDa taUtility" requestor="java.lang.Object" selector="documentName" cardinality="duplicate"/> </Configuration>

2. You will then have to modify the UIs for Document that display this attribute to include documentName instead of name. In the file createDocumentSetAttributesWizStep.jsp change
<jca:describeAttributesTable var="attributesTableDescriptor" ... <jca:describeProperty id="name" htmlId="NameInputId"/> ... </jca:describeAttributesTable>

To:
<jca:describeAttributesTable var="attributesTableDescriptor" ... <jca:describeProperty id="documentName" htmlId="NameInputId"/> ... </jca:describeAttributesTable>

Modifying the behavior for all object types

If you wanted to modify the behavior of the name attribute for all object types you could simply configure the following with out changing any UIs.
<Configuration targetFile="codebase/com/ptc/core/components/components.dataUtilit ies.properties"> <Option serviceClass=" com.ptc.carambola.customization.examples.wizard.GeneratedNameDa taUtility" requestor="java.lang.Object" selector=" name" cardinality="duplicate"/> </Configuration>

Customization Points
None.

Limitations
Since Number is a String attribute this quick customization is only relevant for generated attributes of String Type that do not have a discrete set defined.

13-100

Windchill Customizers Guide

Sample Code Examples of Usage in Windchill Code


com.ptc.core.components.factory.dataUtilities.NumberDataUtility.

Packaged Samples
com.ptc.carambola.customization.examples.wizard.GeneratedNameDataUtility

Additional Resources Related Customization Documentation


Windchill Client Architecture Overview on page 8-2 Gathering the Data for the UI on page 12-1 Attribute Handling on page 13-2

Presenting Information in the UI

13-101

Partial Activation of JSCA


In release 9.1, JSCA is not enabled for all pages. JSCA will be turned on by default for all display tables and for pickers. JSCA will be turned off (JCA used) by default for all other tables in wizards or other popups. You can override this default behavior in an individual JCA table or tree by adding a new useJSCA param to the renderTable Tag. This parameter is only for version 9.1 and will will be removed in version 10 when JSCA will be enabled for for all tables. Example:
<jca:renderTable model="${tableModel}" pageLimit="-1" helpContext="CheckedOutTable_help" useJSCA="false"/>

If you want to test how a table works with JSCA vs JCA, you can toggle between the two with a URL parameter. If a developer wishes to test to see how a table works with JSCA vs JCA we have also provided a url param that can be added to toggle the table between JSCA and JCA. See example below: Example:
http://machinename.ptcnet.ptc.com/Windchill/netmarkets/jsp/user/li stCheckedOutWork.jsp?useJSCA=true

The useJSCA URL paramter name is case sensitive but the value is not case sensitive and it will accept any form of true and false. It will also accept 1 for true and 0 for false. JSCA is not enabled by default. You can use the url param above to test single pages. If you prefer to turn JSCA on as it will be when we ship you can modify the file
windchill\codebase\WEB-INF\tlds\components.tld

and remove the default that has been temporarily specified to turn jsca off (remove the line in bold below):
<attribute> ... <name>useJSCA</name> <required>false</required> <type>boolean</type> <default>false</default> </attribute>

Note: Old Netmarkets architecture Tables and Trees (those that were not converted to JCA) are currently using the JSCA rendering and do not at this time support any methods of going back to the JCA rendering. The current recommendation is that if you need an old legacy table to use JCA instead of JSCA you will need to convert the table to JCA and use the tag attribute as described above.

13-102

Windchill Customizers Guide

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 in Rational Rose. This icon will be used when an object of this type is displayed. In case of soft types, the Type Manager allows the user to associate an icon to be used to represent this soft type 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 wt.part.WTPart wt.epm.EPMDocument wt.doc.WTDocument IconDelegate com.ptc.windchill.enterprise.part.commands.delegate. WTPartIconDelegate wt.epm.identity.EPMDocumentIconDelegate wt.doc.DocumentIconDelegate

If the user needs different icons on types (other than the OOTB) or for his own modeled/soft types, 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.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:

Presenting Information in the UI

13-103

Java Windchill Type Identifiers

Solution Elements

Element <custom_IconDelegate>.java

Type java

Description 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>

Authoring the custom IconDelegate

1. You can extend either wt.fc.IconDelegate or an existing subclass of wt.fc.IconDelegate. 2. There are few APIs that you need to over-ride, where you have to put your icon determining logic.

13-104

Windchill Customizers Guide

a. These two APIs returns an IconSelector object, which holds the information of the icon for the specific Windchill object.
API Signature public IconSelector getStandardIconSelector() throws WTException, IllegalAccessException, InvocationTargetException; public IconSelector getOpenIconSelector() throws WTException, IllegalAccessException, InvocationTargetException; Get a selector for when the object is opened (for example when a folder is opened) Description Get the standard selector for the icon

b. This API returns the localized tooltip value that need to be shown for the icon.
API Signature public String getToolTip() Description 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 protected Boolean inflateRequired() Description 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. } } 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

Presenting Information in the UI

13-105

sure that they are properly populated when you invoke getStandardIconSelector() or getOpenIconSelector().
API Signature protected void initAttributes(Set<AttributeTypeIdentifier> attributes) Description Update <AttributeTypeIdentifier> with attributes that drive-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); 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){

13-106

Windchill Customizers Guide

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; 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 {

Presenting Information in the UI

13-107

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 WT_HOME/codebase/service.properties file via xconfmanager.
<Service context="default" name="wt.fc.IconDelegate"> <Option cardinality="duplicate" requestor="<your_type>" serviceClass="<your_IconDelegate>"/> </Service>

13-108

Windchill Customizers Guide

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

Pre-Validation Post-Select Validation Post-Submit 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 next step in a wizard because the data theyve entered in the current step is

Presenting Information in the UI

13-109

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 containers 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 containers 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 objects 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. 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.

13-110

Windchill Customizers Guide

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 youll 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.

The Additional Resources section below includes references to many or all of these subjects.

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 StandardUIComponentValidation Service Type Java class Description Often referred to as the 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.

Presenting Information in the UI

13-111

Element UIValidationCriteria

Type Java class

Description 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. 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 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.

13-112

Windchill Customizers Guide

Element UIComponentValidator

Type Java interface

Description This is the interface that all 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 valiadtors 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. This is the interface that all filter implementations need to implement. However, filters should not implement this interface directly. Rather, they should extend DefaultSimpleValidationFilter or DefaultUniversalValidationFilter. 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. Filters 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.

ValidationFilter

Java interface

Presenting Information in the UI

13-113

Element SimpleValidationFilter

Type Java interface

Description This is the interface that all 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 intervace

This is the interface that all universal filter implementations need to implement. However, universal filters should not implement this interface directly. Rather, they should extend DefaultUniversalValidationFilter. 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. This is a default implementation of the UniversalValidationFilter interface. All universal filter implementations should extend this class. This is an interface that all 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.

DefaultUniversalValidationFilter

Java class

UIComponentSolutionGroup

Java interface

*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(s)

There are multiple satellite 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.

13-114

Windchill Customizers 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.

Client Infrastructure

Validation Service

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

13-115

If the cache of invalid solution-based keys contains the current validation key, the validation service sets the components 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.

Client Infrastructure

1 2a

Cache of invalid components for the installed solutions

Validation Service

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 users 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.

13-116

Windchill Customizers Guide

If the role-based UI service returns a status of hidden or disabled, the validation service sets the components 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.

Client Infrastructure

1 2a

Cache of invalid components for the installed solutions

Validation Service 2b

Role-Based UI Service

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.

Presenting Information in the UI

13-117

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 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 actions 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 actions 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

13-118

Windchill Customizers Guide

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 components status correspondingly and does not perform any additional 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.

Client Infrastructure

1 2a

Cache of invalid components for the installed solutions

Validation Service 2b

2c Role-Based UI Service

Applicable Filters

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

13-119

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.

Client Infrastructure

1 2a

Cache of invalid components for the installed solutions

Validation Service 2b

2c Role-Based UI Service 2d Validator

Applicable Filters

13-120

Windchill Customizers 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.

Presenting Information in the UI

13-121

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-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.

Client Infrastructure

1 2a

Cache of invalid components for the installed solutions

Validation Service 2b

2c Role-Based UI Service 2d Validator

Applicable Filters

13-122

Windchill Customizers 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

13-123

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.

Client Infrastructure

Validation Service

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.

13-124

Windchill Customizers 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.

Client Infrastructure

Validation Service

Validator

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 displayed. If the status is denied, the user is redirected to the previous page, and

Presenting Information in the UI

13-125

if the validator returned a message indicating why the action was denied, that message is displayed to the user.

Client Infrastructure

Validation Service

3 Validator

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.

13-126

Windchill Customizers 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 postsubmit 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.

Client Infrastructure

Validation Service

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 wizards Next or OK action. As is the case with pre-validation and post-select validation, a validator is associated with a wizards 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. 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

Presenting Information in the UI

13-127

associated with the Next or OK action, the validation service calls that validator to get a validation status for the action.

Client Infrastructure

Validation Service

Validator

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 denied, the user restricted from moving to the next wizard step or submitting the

13-128

Windchill Customizers Guide

wizard, and if the validator returned a message indicating why the action was denied, that message is displayed to the user.

Client Infrastructure

Validation Service

3 Validator

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

13-129

Pre-Validation Procedures
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 13-130 Implementing Solution-Based Pre-Validation on page 13-131 Implementing Role-Based Pre-Validation on page 13-134 Implementing Validation Filters on page 13-134 Implementing Validators for Pre-Validation on page 13-138

Distinguishing between Pre-Validation Statuses

Depending on whether youre validating actions or attributes, the validation statuses youll 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 youre implementing a filter or validator to perform pre-validation logic, youll 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 cant 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 is more context information available that can disable or deny the user. Youre almost always better off showing a user an action they cant perform than hiding an action that they should be able to perform.

13-130

Windchill Customizers Guide

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 wasnt 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 Statues

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 attributes name nor value is never displayed in the UI. The hidden value status means that the attributes name will be displayed, but not its value. The read only status is used to indicate that an attributes name and value are displayed, but that user may not modify the value. And the visible status is used to indicate that the attributes 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 arent 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.
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.

Presenting Information in the UI

13-131

Implementing a Solution Group

Implementing a solution group class is very easy. All you need to do is create a class that implements the UIComponentSolutionGroup Interface, and in your class, implement the getInvalidInstallKeys() method. In that method, you check to see which solutions are installed, and return a list of validation keys representing actions or UI components that should never be available based on the installed solutions. The class on the following page is an simple example of a solution group whose getInvalidInstallKeys() method checks to see if Pro/INTRALINK is installed. If Pro/I is installed, it returns a list of validation keys representing actions or components that should never be available.
package com.ptc.windchill.enterprise.myPackage;

import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import wt.log4j.LogR; import wt.util.InstalledProperties; public class MySolutionGroup implements UIComponentSolutionGroup { private static UIValidationKey listKey = UIValidationKey.newInstance("list", "change"); private static UIValidationKey crKey = UIValidationKey.newInstance("listChangeRequests", "change"); private static UIValidationKey cnKey = UIValidationKey.newInstance("listChangeNotices", "change"); private static UIValidationKey viewKey = UIValidationKey.newInstance("view", "change"); /* * DEFINE ADDITIONAL ACTIONS AND UI COMPONENTS AS NEEDED */ private static Logger logger = LogR.getLogger(MySolutionGroup.class.getName()); public List getInvalidInstallKeys() { if (logger.isDebugEnabled()){ logger.debug("ENTERING MySolutionGroup.getInvalidKeys"); } ArrayList invalidList = new ArrayList(); // if PRO-I is installed, the following UI components are not valid. if (InstalledProperties.isInstalled(InstalledProperties.PRO_I)){ invalidList.add(listKey); invalidList.add(crKey); invalidList.add(cnKey); invalidList.add(viewKey);

13-132

Windchill Customizers Guide

} /* * ADD ADDITIONAL SOLUTION-BASED CHECKS AS NEEDED */ if (logger.isTraceEnabled()){ logger.trace("RETURNING " + (List)invalidList); } if (logger.isDebugEnabled()){ logger.debug("EXITING MySolutionGroup.getInvalidKeys"); } return invalidList; } }

If youre wondering how to determine which values to include in the validation key factory methods, it depends on whether youre creating a validation key for an action or an attribute. If youre 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 youre creating a validation key for an attribute, simply use the descriptor ID used for that attribute in the Windchill client architecture. For example, to create a validation key for the attribute whose descriptor ID is iteration, you would call UIValidationKey.newInstance(iteration);
Registering a Solution Group

Once you've created and built your solution group, the only thing left to do is register it. You register a solution group in *service.properties.xconf by creating an entry like this:
<Service context="default" name="com.ptc.core.ui.validation.UIComponentSolutionGroup"> <Option requestor="null" serviceClass="[your fully-qualified SolutionGroup class name]" selector="[any unique key, e.g., "ChangeMgmtSolutionGroup")]" /> </Service>

The propagated entry in *service.properties should look like this:


wt.services/svc/default/com.ptc.core.ui.validation.UIComponentSolu tionGroup/[any unique key, e.g., "MySolutionGroup"]/null/0=[your fully-qualified solution group class name]

Presenting Information in the UI

13-133

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 Functions - Attribute Visibility section on page 9-8.
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 youll 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. To implement, it is 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, youll 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.

13-134

Windchill Customizers Guide

The following class skeleton is an example of a simple filter that would hide an action if the context object is marked for delete. (NOTE: Obviously, this is an overly-simplified example. A production-quality class would have exception handling, logging, etc.)
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: (NOTE: Obviously, this is an overly-simplified example. A production-quality class would have exception handling, logging, etc.)
public class MarkedForDeleteFilter extends DefaultUniversalValidationFilter{ @Override public UIValidationStatus preValidateAction(UIValidationKey key, UIValidationCriteria criteria){ // ENABLE by default UIValidationStatus status = UIValidationStatus.ENABLED; WTReference contextObj = criteria.getContextObject(); if (/*contextObj.isMarkedForDelete() == */ true){ status = UIValidationStatus.HIDDEN; } return status; } }

Registering Filters

Once you've created a filter, the next step is to register it. Depending on the type of filter you implement (universal or simple), your filter registry will differ. When providing a selector in your registry, the convention is to use the filter class name with replacing the first letter with a lower-case letter,

Presenting Information in the UI

13-135

and eliminating the "filter" suffix (e.g., "MarkedForDeleteFilter" would have a selector of "markedForDelete"). The following details should clarify: To register a universal filter, in *service.proeprties.xconf, create an entry like this:
<Service context="default" name="com.ptc.core.ui.validation.UniversalValidationFilter"> <Option serviceClass="com.ptc.windchill.enterprise.markedfordelete.validat ors.MarkedForDeleteFilter" selector="markedForDelete" requestor="null" /> </Service> When registering a simple filter, the only difference is the name attribute of the Service element: <Service context="default" name="com.ptc.core.ui.validation.SimpleValidationFilter"> <Option serviceClass="com.ptc.windchill.enterprise.somepackage.validators. MarkedForDeleteFilter" selector="markedForDelete" requestor="null" /> </Service>

Associating and Dissociating Actions with a Filter

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

13-136

Windchill Customizers Guide

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" > <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

13-137

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.
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 youll 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 dont 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. Its 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 validators

13-138

Windchill Customizers Guide

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. Full Pre-Validation Explained On the other hand, suppose youre pre-validating an action in a drop-down list of actions in a table row, or on an info page. Since were 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, well 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 validators 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 validators 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 youve created a validator class skeleton, if youre adding pre-validation logic for an attribute, youll want to implement the performLimitedPreValidation() method. If youre adding pre-validation logic for an action, youll 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

Presenting Information in the UI

13-139

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() (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; } }

13-140

Windchill Customizers Guide

Registering Validators

Once youve created your validator and implemented the appropriate prevalidation 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 attributes 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.validation.UIComponentVali dator/[action name/attribute descriptor ID]/null/0=[your fullyqualified Validator class]/duplicate

Note that in this case, the requestor attribute is null, meaning the actions 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 actions 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" ...> <action name="create" > ... </action> ... </objecttype>

Presenting Information in the UI

13-141

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.ChangeMgmtCreateWizardsVali dator 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.ChangeMgmtCreateWizardsVal idator) 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.
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.

13-142

Windchill Customizers Guide

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 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

Presenting Information in the UI

13-143

create:problemReport(wt.change2.WTChangeIssue) -> com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat eWizardsValidator

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 on page 13-139 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 youre 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 UIValidationResult validateSelectedAction() (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);

13-144

Windchill Customizers Guide

return result; } @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; } }

Presenting Information in the UI

13-145

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 on page 13-139 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; } }

13-146

Windchill Customizers Guide

Miscellaneous Tips, Tricks, and Things to Avoid


This section contains the following topics: Working with Access Permissions on page 13-147 Rule of Thumb: One Validator per Action/Attribute/Component on page 13-148 Do Not Inflate WTReferences on page 13-149 Handle Null Values on page 13-150 Use the @Override Annotation on page 13-150 UIValidationCriteria.toString() on page 13-150

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){

Presenting Information in the UI

13-147

accessPermissions = AccessControlManager.getPermissions(...); criteria.setCachedAccessPermissions(accessPermissions); }

Additional notes regarding access permissions: wt.access.AccessControlManager has the following APIs available in singleand 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 users 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

Dont 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 is that in a given action menu, either actionA or actionB should appear, but never

13-148

Windchill Customizers Guide

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. Dont 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 in bold italic 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())){ ... } if (!PDMLinkProduct.class.isAssignableFrom(containerRef.getReferenced Class())){ ... } }

Presenting Information in the UI

13-149

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.
Use the @Override Annotation

Its 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)

13-150

Windchill Customizers Guide

If the Level of the Logger matches with the Level provided, the method will return the information. Since the method performs some costly calculations, its suggested to use this it wisely.

Presenting Information in the UI

13-151

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>

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

13-152

Windchill Customizers Guide

"getValue(String, Hashtable, HashTable, boolean)" of the file "Windchill\ DevModules\Foundation\src\wt\part\LoadPart.java". 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("")) { 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 accordance with the terms of the license agreement.

Presenting Information in the UI

13-153

* * ecwti */ package wt.part; import import import import java.lang.String; wt.part.ValidateFindNumbersDelegate; wt.part.WTPartUsageLink; wt.util.WTException;

//##begin user.imports preserve=yes import wt.util.WTPropertyVetoException; //##end user.imports

// Preserved unmodeled dependency

//##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 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 **/

13-154

Windchill Customizers Guide

//##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 { //##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];

Presenting Information in the UI

13-155

// 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. // SPR 1457664 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 )); } 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 )); } } } } } } //##end user.operations }

13-156

Windchill Customizers Guide

14
Constructing Wizards
This chapter describes how to construct wizards. Topic Page

Windchill Client Architecture Wizard ..............................................................14-2 Wizard Processing...........................................................................................14-19 Building Wizards to Create a Single Object ...................................................14-38 Building Wizards to Edit a Single Object .......................................................14-90

14-1

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. 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 a single step or multiple steps. Each multiple steps wizard will have navigation buttons (BACK / NEXT) at the bottom, which you can use to navigate from one step to another. 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.

Multi-Step Wizard

14-2

Windchill Customizers Guide

Single Step Wizard

Multi-Step Clerk

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. Scrolling is enabled for table inside wizard as well as table inside picker. 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

Constructing Wizards

14-3

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.

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, 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\ components

<your_wizard_page>.jsp <your_wizard_step>.jsp <*-actions>.xml actionmodels.xml

jsp jsp xml xml

The jsp file in which your wizard implementation is defined. The jsp file, which contains contents of the wizard step. The actions for the wizard as well as each wizard step are defined in this XML file. 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.

14-4

Windchill Customizers Guide

Element

Type

Description

<resourceBundle>.rbInfo

rbInfo

This is another option where you can specify locale specific Strings and properties for wizard step and wizard actions. 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.

formProcessorController

java

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. 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. Windchill will now expect create.jsp to be located in <Windchill>\codebase\netmarkets\jsp\changeTask\ folder. Since this action is for the wizard, you need to specify windowType as popup inside the <command> tag. 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, you need to specify windowType as wizard_step.
<objecttype name="changeTask" class="wt.change2.WTChangeActivity2"> <action name="create"> <command windowType="popup"/> </action> <action name="affectedAndResultingItemsStep"> <command windowType="wizard_step" /> </action> </objecttype>

Create the Wizard page

Create a new jsp page inside <Windchill>\codebase\netmarkets\jsp\changeTask\ folder and name it as create.jsp. The first thing that you need to do is to declare the components tag library that contains the necessary tags for constructing the wizard and wizard steps. Next you need to include some files that will be used by the wizard infrastructure namely;

Constructing Wizards

14-5

/netmarkets/jsp/components/beginWizard.jspf and /netmarkets/jsp/components/includeWizBean.jspf. Define the wizard using the <wizard> tag. All the steps for this wizard will be defined inside <wizard> tag using <wizardStep> tag. Finally, include "/netmarkets/jsp/util/end.jspf" file to close the form.
<%@ 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" /> </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.
Specify localized Strings / properties for wizard step and wizard actions
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 Task changeTask.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

14-6

Windchill Customizers Guide

changeTask.create.icon.pseudo=false changeTask.create.moreurlinfo.value=width=800,height=700 changeTask.create.moreurlinfo.pseudo=false

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
Create the wizard step page

This can be any JSP page, which can contain any other component(s) as well as plain HTML contents.

Customization Points
This section contains the following topics: <action>.xml attributes <wizard> tag attributes <wizardStep> tag attributes Providing user defined buttons to Wizard Providing user defined form processor controller Providing server side validation before / after processing a wizard step Loading the wizard step content when it is visited Marking a wizard step as required Hiding a wizard step Displaying the hidden / dynamic step at runtime Providing user defined SUBMIT function Providing client side validations before a wizard step is displayed Providing client side validations after a wizard step is finished

<action>.xml attributes

Parameter id

Default Value <type>.<action>

Possible Values Any String

Req? No

Description Overrides the id of the wizard step (default is type.action).

Constructing Wizards

14-7

Parameter afterJS

Default Value -

Possible Values Any String

Req? No

Description Specify the javascript function name to invoke client side validation for a wizard step when step is finished. Specify the javascript function name to invoke client side validation for a wizard step when step is loaded. Specify the server validator name to invoke server side validation for a wizard step when step is loaded. Specify the server validator name to invoke server side validation for a wizard step when step is finished. Specifies that wizard step is to be downloaded when wizard is launched. Specifies that wizard step is to be hidden at first, or for the action to be rendered as non-clickable. Specifies that wizard step is required.

beforeJS

Any String

No

beforeVK

Any String

No

afterVK

Any String

No

preloadWizardPa ge hidden

true false

false / true false / true

No No

required

false

false / true

No

<wizard> tag attributes

Parameter buttonList

Default Value DefaultWizard Buttons

Possible Values Any String

Req? No

Description The action model containing the list of buttons to display in the wizard. The default set is the DefaultWizardButtons action model. The FormProcessorController class that should be used to process the wizard when it is submitted. If not specified, DefaultFormProcessorController will be used.

formProcessorCo ntroller

DefaultFormPr ocessorControlle r

Any String

No

14-8

Windchill Customizers Guide

Parameter title

Default Value -

Possible Values Any String

Req? No

Description The overriding title to display instead of the default title in the rbInfo file or action.properties file. This title will not be localized / internationalized by default. You need to take care of passing a localized title. The selector key to identify help file from services.properties file. Identifies whether wizard is of type clerk or not. If "clerk" is specified, the wizard will be displayed as per clerk UI. This allows for text to be displayed above the progress bar using the UI standard.

helpSelectorKey type

wizard

Any String Wizard/clerk/dia log

No No

progressMessage

Any String

No

<wizardStep> tag attributes

Parameter action type objectHandle

Default Value -

Possible Values Any String Any String Any String

Req? Yes Yes No

Description The name of the action to include in the wizard parent tag. The type of the action to include in the wizard parent tag. 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.

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.

embeddedHelp

Any String

No

A small optional text help to be displayed on top of the wizard step content.

Constructing Wizards

14-9

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>

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 e.g. In <your_wizard_page>.jsp
<jca:wizard formProcessorController = "com.ptc.windchill.enterprise.change2.forms.controllers.Effectivit yAwareIframeFormProcessorController">

14-10

Windchill Customizers Guide

</jca:wizard>

Note: For more information see the Wizard Processing on page 14-19.

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 e.g.
<action name="setAttributesWizStepForCreateMultiPart" beforeVK = "nameNumberValidation"> <command windowType="wizard_step"/> </action>

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.CreateMu ltiPartNameNumberValidator" /> </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 e.g.
<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.

Constructing Wizards

14-11

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 e.g.
<action name="setClassificationAttributesWizStep" required="true"> <command windowType="wizard_step"/> </action>

You can also mark a wizard step as required at runtime. You need to use a javascript function called setStepRequired which is defined in wizard.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 e.g.
<script src="/netmarkets/javascript/components/wizard.js"></script> <table border="0"> <tr> <td align="left" valign="top" NOWRAP> <w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>" value="<%=NmObjectHelper.CB_COPY%>" checked="true" onclick="removeStep(<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 e.g. 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 wizard.js file. You need to pass the id of the

14-12

Windchill Customizers Guide

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 e.g. In <your_wizardstep_page>.jsp
<script src="/netmarkets/javascript/components/wizard.js"></script> <table border="0"> <tr> <td align="left" valign="top" NOWRAP> <w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>" value="<%=NmObjectHelper.CB_COPY%>" checked="true" onclick="removeStep(<type>.<action >);"/> </td> </tr> </table>

Note: Clerk does not make 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 wizard.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 e.g. 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
<script src="/netmarkets/javascript/components/wizard.js"></script> <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>

Constructing Wizards

14-13

</tr> </table>

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 e.g.
<script language="javascript"> function user_validate() { 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 e.g. In <*-actions>.xml
<action name="setClassificationAttributesWizStep" beforeJS =" validatePreviousStep"> <command windowType="wizard_step"/> </action>

In any JSP page or Javascript file accessible to wizard


<script language="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

14-14

Windchill Customizers Guide

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 e.g. In <*-actions>.xml
<action name="setClassificationAttributesWizStep" afterJS =" validateStep"> <command windowType="wizard_step"/> </action>

In any JSP page or Javascript file accessible to wizard


<script language="javascript"> function validateStep() { ... ... return true; } </script>

Configuring Wizard - Suppressing enter key


You can suppress form submission on enter key .
<script language="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; } } }

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>

Constructing Wizards

14-15

<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. 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 e.g.
<%@ 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 the case of a clerk, while navigating between steps you may not get required fields in Server validators, so you need to take care and apply logic accordingly.

14-16

Windchill Customizers Guide

For example, while creating a new document the first step has a required field type (type of document). However, in a clerk the user is free to navigate between other tabs while clicking on other tabs, the user might not have selected required field type in the first step. In that case the server validator cannot get the value of the type attribute.

Constructing Wizards

14-17

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 (can be accessed through wizard actions on table examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\ wizard\newWizardExampleOne.jsp

Wizard example two (can be accessed through wizard actions on table examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\ wizard\wizardExampleTwo.jsp

Clerk example one (can be accessed through wizard actions on table examples):
<Windchill>\netmarkets\jsp\carambola\customization\examples\ clerk\clerkExampleOne.jsp

14-18

Windchill Customizers Guide

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 doPost() method of the WizardServlet. 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 performs an RMI call to a FormProcessorController class in the MethodServer. 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 14-38 and Building Wizards to Edit a Single Object on page 14-90 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.

Intended Outcome
Perform a database operation(s) related to one or more Windchill object.

Constructing Wizards

14-19

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 WizardServlet

Type Java class; runs in the servlet container

Description 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: <WT_HOME>/srclib/CommonCompone nts-web.jar

FormProcessorController

Java interface; implementations run in the Method Server

Classes implementing this interface instantiate and call ObjectFormProcessor(s) to execute wizard tasks. Runtime location: <WT_HOME>/srclib/CommonCompone nts.jar

14-20

Windchill Customizers Guide

Element DefaultFormProcessorControll er

Type Java class; runs in the Method Server

Description A default implementation of 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: <WT_HOME>/srclib/CommonCompone nts.jar

ObjectFormProcessor

Java interface; implementations run in the Method Server

Classes implementing this interface perform the database and related tasks appropriate to the wizard using the form data. Each wizard will have only one ObjectFormProcessor class but multiobject wizards may have multiple instances of that class. ObjectFormProcessors may call ObjectFormProcessorDelegates to perform subtasks. Runtime location: <WT_HOME>/srclib/CommonCompone nts.jar

DefaultObjectFormProcessor

Java class; runs in the Method Server

A default implementation of ObjectFormProcessor that contains the logic to execute ObjectFormProcessorDelegates and perform several other common tasks. This is the base class that should be extended by wizard-specific processors. Runtime location: <WT_HOME>/srclib/CommonCompone nts.jar

Constructing Wizards

14-21

Element ObjectFormProcessorDelegate

Type Java interface; implementations run in the Method Server

Description Classes implementing this interface are called by ObjectFormProcessors to perform processing subtasks. Multiple ObjectFormProcessorDelegates 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: <WT_HOME>/srclib/CommonCompone nts.jar

DefaultObjectFormProcessorD elegate

Java class; runs in the Method Server

A default implementation of ObjectFormProcessorDelegate. This 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: <WT_HOME>/srclib/CommonCompone nts.jar

ObjectBean

Java class; runs in the Method Server

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: <WT_HOME>/srclib/CommonCompone nts.jar

ProcessorBean

Java class; runs in the Method Server

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: <WT_HOME>/srclib/CommonCompone nts.jar

FormResult

Java class; runs in the Method Server and client

A class used to pass method results between server methods and from the server to the WizardServet. Runtime location: <WT_HOME>/srclib/CommonCompone nts.jar

14-22

Windchill Customizers Guide

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 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

Constructing Wizards

14-23

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 14-36 for more information about ObjectFormProcessorDelegates. Both ObjectFormProcessor and ObjectFormProcessorDelegate classes have preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods for carrying out tasks during each 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

14-24

Windchill Customizers Guide

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 it's 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(). 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

Constructing Wizards

14-25

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

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~430512131997223~! <someAdditionalText>" value="" size="60" maxlength="60" type="text">

In the example above, "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:

14-26

Windchill Customizers Guide

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 put a "rowBasedObjectHandles" attribute on the renderTable tag:
<jca:renderTable model="<your model name>" rowBasedObjectHandles="true" />

The dynamically generated object handle will represent the time in nanoseconds when the row was created. 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 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

Constructing Wizards

14-27

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.
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 it's 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

14-28

Windchill Customizers Guide

the ProcessorBean.newCollection() method which will group the ObjectBeans into ProcessorBeans as follows:

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 1 ProcessorInstance1. preProcess (ObjectBean in Processor Bean 1) ProcessorInstance2. preProcess(ObjectBeans in Processor Bean 2) ProcessorInstance1.doOperation( ObjectBean in Processor Bean 1) ProcessorInstance2.doOperation( ObjectBeans in Processor Bean 2) ProcessorInstance1.postProcess(O bjectBean in Processor Bean 1) Task Performed create an instance of a WTChangeOrder2 and store it in the "object" attribute of the bean create three instances of WTChangeActivity2 and store them in the "object" attributes of the beans persist the WTChangeOrder2 persist the WTChangeActivity2 instances create the associations between the change notice and the change tasks

3 4 5

Constructing Wizards

14-29

Method 6 7 ProcessorInstance2.postProcess(O bjectBeans in Processor Bean 2) ProcessorInstance1.postTransacti onProcess(ObjectBean in Processor Bean 1) ProcessorInstance2.postTransacti onProcess (ObjectBeans in Processor Bean 2)

Task Performed none none

none

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. 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

14-30

Windchill Customizers Guide

(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 Wizards with Multiple Target Objects

Wizards with a Single Target Object

This process consists of the following steps: Create your processor class Specify the processor class for the wizard on the wizard action Create any necessary ObjectFormProcessorDelegate classes for your wizard Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard

Create your processor class

Three processors for handling object creation and editing wizards are delivered with the product: com.ptc.core.components.forms.CreateObjectFormProcessor com.ptc.core.components.forms.DefaultEditFormProcessor com.ptc.core.components.forms.EditWorkableFormProcessor

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:

Constructing Wizards

14-31

public public public public public public public public public public

Map<String,List<String>> getChangedComboBox() Map<String,String> getChangedRadio() Map<String,String> getChangedText() Map<String,String> getChangedTextArea() Map<String,List<String>> getChecked() Map<String,List<String>> getUnChecked() List getRemovedItemsByName(String paramName) List getAddedItemsByName(String paramName) String getTextParameter(String key) String[] getTextParameterValues String key)

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: Whether the wizard window should be closed. Determined from the status and nextAction variables. Whether the window from which the wizard was launched should be refreshed.

14-32

Windchill Customizers Guide

Determined from the nextAction variable. The javascript you would like executed in the response, if any. Determined from the nextAction and javascript variables. Whether a new URL should be loaded into the launch window and, if so, what that URL should be loaded. Determined from the nextAction and URL variables. What 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. See the javadoc for the FormResult, FormProcessingStatus, and FormResultAction 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 WizardServlet which will set the variables of the FormResult as follows: status - FormProcessingStatus.FAILURE nextAction - FormResultAction.NONE 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.
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 class="com.ptc.core.components.forms.CreateObjectFormProcessor" windowType="popup" /> </action>

Constructing Wizards

14-33

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. 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. Typically, a delegate will only pass back a status and, possibly, feedback messages in the FormResult. The ObjectFormProcessor will set and pass back the nextAction in the FormResult it sends to the FormProcessorController since it knows the launch context of the specific wizard in which the delegate is being used. Like ObjectFormProcessor methods, ObjectFormProcessorDelegate methods can throw exceptions. How these are handled depends on the ObjectFormProcessor calling it.

14-34

Windchill Customizers Guide

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.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 Abstract GuiComponent, 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.

Constructing Wizards

14-35

Wizards with Multiple Target Objects

This process consists of the following steps: Create your processor class Specify the processor class for the wizard on the wizard action Create any necessary ObjectFormProcessorDelegate classes for your wizard Specify the ObjectFormProcessorDelegate(s) to be used in your wizard Create a FormProcessorController, if needed Specify the FormProcessorController to be used in your wizard, if needed

Create your processor class

The same as for a wizard with a single target object. See Create your processor class on page 14-31.
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 14-33.
Create any necessary ObjectFormProcessorDelegate classes for your wizard

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 14-33.
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 14-35. 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"

14-36

Windchill Customizers Guide

formProcessorController="com.ptc.windchill.enterprise.change2.form s.controllers.ChangeItemFormProcessorController">

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.

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.FormResultNextAction 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

14-37

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 section of this topic on page 14-41. 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 soft type 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 you can ignore such implementation details. This document describes the reusable common components upon which most Windchill create 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 create instances of a custom type. If your type is a modeled or soft subtype of a Windchill business class for which a wizard with a type picker is already

14-38

Windchill Customizers Guide

available, you may be able to use the out-of-the-box wizard for your purposes. The out-of-the-box wizards will automatically find subclasses and soft types 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 MyPart, it will be displayed in the New Part wizard as follows:

Constructing Wizards

14-39

Input fields for any non-association attributes you have defined for your subtype will automatically be displayed on the Set Attributes step of the New Part wizard below the out-of-the-box attributes:

Attributes in the table will be ordered as follows: 1. Out-of-the-box attributes ordered as listed in the JSP file 2. Custom modeled attributes ordered alphabetically by display name 3. Custom soft attributes ordered alphabetically by display name 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.

14-40

Windchill Customizers Guide

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 the Building Wizards to Edit a Single Object section on page 14-90 of the Windchill Customizers Guide 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.

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 have an understanding of the following: Java programming Basic web development using JSPs , custom tags, and HTML forms How to create modeled or soft Windchill business object types. See the following chapters in the Windchill Customizers Guide for more information on creating your business object classes using the Information Modeler and Rational Rose: Getting Started With Windchill Customization chapter on page 3-1 Modeling Business Objects chapter on page 4-1 System Generation chapter on page 31-1 Developing Server Logic chapter on page 35-1

See the Type and Attribute Manager chapter of the Windchill Business Administrators Guide for more information on creating soft types and attributes. The use of actions to launch jsp pages and wizards. See the Adding Actions and Hooking Them Up in the UI chapter on page 11-1 for information on how to create actions. The Windchill framework for creating wizards and processing wizard data.

Constructing Wizards

14-41

See the rest of the Constructing Wizards chapter on page 14-1 for more information on this topic. Also, see the Adding Actions and Hooking Them Up in the UI chapter on page 11-1 for information on how to create actions. The use of tables and property panels to present information in the UI and how to acquire the data for these components. See the following chapters of the Windchill Customizers Guide for more information: Customizing HTML Clients Using the Windchill JSP Framework on page 10-1 Gathering the Data for the UI on page 12-1 Presenting Information in the UI on page 13-1

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 the Presenting Information in the UI chapter on page 13-1 for more information.

The use of the UI Validation Service for validating the users ability to perform actions and for validating the data entered in wizards. The Windchill service APIs or other APIs necessary to perform the data processing tasks appropriate to the wizard

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.

14-42

Windchill Customizers Guide

Definition of Terms Used in This Section


Term base type Definition A hard or soft type 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. The container (Product, Library, Project, etc.) in which you are creating the object(s).

context

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. 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. An object attribute defined in a Java class. An object type defined in a Java class. Hard types are typically modeled using Rational Rose and may extend out-of-the-box Windchill business object classes. A Java class or soft type defining the attributes and behavior of the business object(s) you want to create. An attribute of the object defined in the Windchill Type and Attribute Manager client. 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. An object type defined using the Type and Attribute Manager rather than in a Java class. Soft types may extend other soft types but all have a hard type as their root type. The object you are creating in your wizard.

driver attribute

hard attribute hard type

object type soft attribute

soft type

target object

Solution Elements
Element Tags All the tags below are defined in the <WT_HOME>/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. Type Description

Constructing Wizards

14-43

Element initializeItem

Type Tag

Description 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/co mponents/InitializeItemTag

describeAttributesTable

Tag

Builds a table descriptor for a twocolumn table of object attributes used for entering attribute values. The left column is the attribute name and the right is the attribute value.

See the javadoc for the DescribeAttributesTableTag for more information. Tag handler: com/ptc/core/components/tags/co mponents/DescribeAttributesTabl eTag

14-44

Windchill Customizers Guide

Element describePropertyPanel

Type Tag

Description Builds a table descriptor for a twocolumn panel of object attributes. The left column is the attribute label and the right is the attribute value. Typically used to display read-only information gathered in previous wizard steps or from the launch context but can also be used for input fields.

Tag handler: com/ptc/core/components/tags/co mponents/DescribePropertyPanel Tag getModel Tag Acquires the attribute data needed for an attributes table or property panel previously defined by a describeAttributesTable or describePropertyPanel tag. Tag handler: com/ptc/core/components/tags/co mponents/GetModelTag renderPropertyPanel Tag Renders a property panel previously defined using describePropertyPanel and getModel tags. Tag handler: com.ptc.core.components.tags.pro pertyPanel.RenderPropertyPanelT ag renderTable Tag Renders a table previously defined using describeAttributesTable and getModel tags. Tag handler: com/ptc/core/components/tags/co mponents/RenderTableTag

Constructing Wizards

14-45

Element wizard

Type Tag

Description 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/co mponents/WizardTag

wizardStep JSPs

Tag

Specifies the action pointing to the main JSP for the step.

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 <WT_HOME>/codebase/netmarkets/jsp/object and <WT_HOME>/codebase/netmarkets/jsp/components directories. createEditUIText includeWizBean jspf file jspf file Contains some UI text common to create and edit wizards. Defines the CreateAndEditWizBean called during the generation of jsp pages to access wizard data. A JSP for the Set Context wizard step. 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. defineItemWizStep jsp file A default JSP that you may be able to use for the Define Object step of your wizard if it should contain a read-only property panel for the context name, a type picker, and a driver attributes table for entering attribute values.

setContextWizStep

jsp file

14-46

Windchill Customizers Guide

Element setAttributesWizStep

Type jspf file

Description A jsp file that can be included in the jsp for your Set Attributes wizard step. This will get the model data for and render your attributes panel and tables if you have named them per the instructions in this document. A jsp file that can be included in the jsp for your Set Attributes wizard step if your object type is a FormatContentHolder. It does the same things as the jsp above but, in addition, will render input fields for capturing primary content. Location: <WT_HOME>/codebase/netmark ets/jsp/document

setAttributesWizStepWithContent .jspf

jspf file

Beans CreateAndEditWizBean Java class; Runs in the servlet engine and the Method Server 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 object that is not a folder. If either is the case, a popup error message is displayed. Location: <WT_HOME>/codebase/netmark ets/javascript/util Java Classes You can use the classes below to help create and process your wizard. They are located in the <WT_HOME>/codebase/WEB-INF/lib/wncWeb.jar file.

Constructing Wizards

14-47

Element CreateAndEditModelGetter

Type Java class Runs in the Method Server

Description A class that may be called via a getModel tag to generate the data for property panels and attributes tables in create wizards. A class that may be called to validate the data in the Set Context wizard step. A class that may be called to validate the data in the Define Object wizard step. A class that may be called to validate the data in the Set Attributes wizard step. A class that may be used or extended to process your wizard form data. Extends DefaultObjectFormProcessor. A class that may be extended to implement various processing subtasks. 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. A class used to pass method results between server processor methods and from the server to the WizardServlet.

ContextWizardStepValidator

Java class; runs in the Method Server Java class; runs in the Method Server Java class; runs in the Method Server Java class; Runs in the Method Server

DefineObjectStepValidator

SetAttributesStepValidator

CreateObjectFormProcessor

DefaultObjectFormProcessorDele gate ObjectBean

Java class; Runs in the Method Server Java class; runs in the Method Server

FormResult

Java class; runs in the Method Server and client

Procedure Creating Your Wizard


You will need to perform the following tasks to create your wizard: Laying out your wizard steps and attributes (required) Create an action for the wizard (required) Create actions and/or service properties entries for the wizard steps Create jsp and/or jspf files for your wizard steps or portions thereof (required) Create a main jsp file for your wizard (required)

14-48

Windchill Customizers Guide

Create validators for the wizard data Create a form processor class and/or delegates to process the wizard data after submittal

The tasks noted as required are always required. The other tasks may or may not be needed, depending on the requirements of your wizard. If you have 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.
Laying out your wizard steps and attributes

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 soft attributes in the Attribute and Type Manager 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 soft 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 objects folder. In addition, access rules can be further refined based on the initial state of the default life cycle for the object type. 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 attributes 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:

Constructing Wizards

14-49

Organization Number Name (variant parts only) Folder location Life cycle template Team template 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. 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

14-50

Windchill Customizers Guide

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. Refer to the Loading the wizard step content when it is visited section on page 14-11 for information on pre-loaded 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. The standard layout of Windchill wizards is as follows: 1. Set Context step (for WTContained objects only) 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. 2. Define Object step The body of this step typically contains three sections: a read-only context property panel, a type picker, and a driver attributes property panel. Refer to

Constructing Wizards

14-51

the illustration below. All of these sections are optional, depending on the type of object being created.

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

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 soft types defined for the base type in the given organization container.

14-52

Windchill Customizers Guide

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. Determine a default folder location context for the new object. If a folder was selected on the launch page (for example, the wizard is launched from a folder browser and a folder is checked in the folder table or highlighted in the left pane) that folder will be used. Otherwise, if a folder is defined by an OIR for the base type and given container, that will be used. Otherwise, the default (top-level) cabinet for the objects container is used. (There are a few exceptions to these rules.) Based on the default initial life cycle state and the folder location, determine whether the user has create permission for each type. If not, filter that type from the list. Display the remaining types in the picker.

3.

4.

5.

The default value for the type picker is determined from a preference for some base types, as follows:
Base Type WTPart Preference Create and Edit -> Part Create Default Type Create and Edit -> Document Create Default Type Create and Edit -> Problem Report Create Default Type Create and Edit -> Change Request Create Default Type Create and Edit -> Change Notice Create Default Type

WTDocument

WTChangeIssue (ProblemReport)

WTChangeRequest2 (Change Request) WTChangeOrder2 (Change Notice)

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. When objects are being created from a template, such as creating a document from a template, the type picker is replaced by a template picker and the type of the new object is determined from the template. Driver attributes

Constructing Wizards

14-53

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 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. 3. Set Attributes step This step is where information for most non-driver attributes for the object is gathered. It generally consists of two to four parts, which may include the following: a read-only context property panel, primary content input fields (for FormatContentHolder objects only), an attribute input table, and

14-54

Windchill Customizers Guide

checkboxes for processing directives specific to the object type. Refer to the illustration below.

Context panel Read-only information about the object being created that is derived from the launch context or data entered on previous wizard steps. This will usually contain the object type. If the new object is WTContained it will also display the container name. If the new object is OrganizationOwned and the preference Display -> Expose Organization is set to true it will also display the organization id.

Primary content Wizards to create objects that are FormatContentHolders, such as WTDocuments, should have a section for the user to enter the primary content item. .

Attribute input table

Constructing Wizards

14-55

Typically contains all the soft and hard attributes for the object type that were not entered on previous steps, except for part classification attributes, which are entered on a following step. Note that one of the attributes typically presented in this table is folder location. As stated earlier, 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 Define Object step is based on a default folder derived from the launch context. The user could potentially select a different folder location in this step for which the access control policies vary. Thus it is possible the user could select a folder for which s/he does 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

for new RevisionControlled objects for creating documents from templates for creating document templates

If checked, the system checks out the object after creation If checked, the new document is checked out and downloaded If checked, the new template is immediately available for use

Checkout and download Enabled 4. Additional steps

Your wizard may contain additional steps pertinent to the type of object being created. Steps for which common components are available are: Classification attributes 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

14-56

Windchill Customizers Guide

includes a table of input fields for classification attributes. Refer to the illustration below.

Attachments step This step is typically included when creating objects that are ContentHolders. It allows the user to attach documents, links, and other content to the new object. See the Attachments section in the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for information on incorporating this step.

Some object types may require additional steps to capture other information needed to create the object. No jsp files are provided for such unique wizard steps. However, you can develop your own jsp files for unique steps using the same table, property panel, and javascript components used in the jsp files for common steps.

Creating the action for your wizard


An action is needed to launch your wizard. This should be defined in an appropriate *-actions.xml file inside of an objecttype tag for the base type of your wizard.

Constructing Wizards

14-57

A minimal action definition will look like this:


<action name="<your wizard action name>" > <command class="<path to your wizard form processor>" windowType="popup"/> </action>

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 above, the system would expect to find a jsp file named <WT_HOME>/codebase/netmarkets/jsp/<objecttype name>/<your wizard action name> to use for the main page of your wizard. 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> create<type of object> Example: createFromWorkspace Example: createSharedDocument

The command class is the java class that should be called to process the wizard data. Typically, this will extend CreateObjectFormProcessor. See Creating Your Form Processor and Form Processor Delegates section on page 14-75 for more information. Note that it is not necessary to specify a method attribute in the command tag if your form processor class extends DefaultObjectFormProcessor or CreateObjectFormProcessor.

14-58

Windchill Customizers Guide

Optional action tag attributes are shown in the table below.


Action tag attribute Default value Possible value Description

ajax

None

page component row

Specifies what portion of the parent page should 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. See Creating Your Form Processor and Form Processor Delegates section on page 14-75 for more information.

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.CreateMyPartF ormProcessor" onClick="validateCreateLocation(event)" windowType="popup"/> </action>

The validateCreateLocation() javascript method shown in the action above is applicable to create wizards that can be launched from a folder browser. See the Solution Elements section on page 14-43 for more information. See the Adding Actions and Hooking Them Up in the UI chapter on page 11-1 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 the section of Windchill Customizers Guide referenced above.

Constructing Wizards

14-59

Creating actions and/or service property entries for your wizard steps
Each wizard step requires an action. You may be able to use out-of-the-box action definitions for wizard steps that are common to multiple wizards. The following wizard step actions are defined out-of-the-box.
Step Set Context Object Type object Action definition / File location / Associated JSP page
<action name="setContextWizStep" id="setContextWizStep" preloadWizardPage="true" required="true" afterVK="setContextWizStep"> <command windowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/actions.xml Associated jsp page: <WT_HOME>/codebase/netmarkets/jsp/object/setContextWizStep.jsp Define Object object
<action name="defineItemWizStep" id="defineItemWizStep" preloadWizardPage="false" required="true" afterVK="defineItem" resourceBundle="com.ptc.core.ui.componentRB"> <command windowType="wizard_step" url="servlet/TypeBasedIncludeServlet?contextAction=d efineItemWizStep"/> </action>

Action file: <WT_HOME>/codebase/actions.xml Associated jsp page: <WT_HOME>/codebase/netmarkets/jsp/object/defineItemWizStep.jsp Set Attributes object
<action name="setAttributesWizStep" afterVK="setAttributesWizStep" id="setAttributesWizStep" preloadWizardPage="false" required="true" resourceBundle="com.ptc.core.ui.componentRB"> <command windowType="wizard_step" url="servlet/TypeBasedIncludeServlet?contextAction=s etAttributesWizStep"/> </action>

Action file: <WT_HOME>/codebase/actions.xml Associated jsp page: None Set Classificatio n Attributes part
<action name="setClassificationAttributesWizStep" id="setClassificationAttributesWizStep" hidden="true" required="true" preloadWizardPage="false"> <command windowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/ config/actions/PartManagementactions.xml. Associated jsp page: <WT_HOME>/codebase/netmarkets/jsp/part/setClassificationAttributesWi zStep.jsp

14-60

Windchill Customizers Guide

The associated jsp page shown in the table above is a default jsp that may be used for the step. Note there is no default jsp for the Set Attributes step, although there is a common action definition. 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. If these action definitions meet your requirements you do not need to define your own actions for your wizard. However, you will need to define your own action for a wizard step if either of the following is true: you need to define additional or different tag attributes for an action For the Set Context and Set Classification Attributes steps only: you need to use a different jsp page for your step. For the Define Object and Set Attributes steps, you can use a different jsp for your step without defining your own action through use of the TypeBasedIncludeServlet described below. Your step is unique to your wizard

The table below shows action tag parameters relevant to create wizard steps:
Action attribute tag name id Req? yes no Default value None <action type>.<act ion name> false Possible values any string any string Description The name of the action. Used as the name attribute on wizard step tags. Used to identify the step in certain javascript functions. If not specified the id <action type>.<action name> will be used. Specifies whether the user must navigate to the step or not. The Finish button will not be enabled until the user has completed all required steps. Specifies the name of a javascript function to call when the wizard step is loaded Specifies the name of a javascript function to call when the user clicks Next or OK on the wizard step. Can be used to do client-side validation of the form data. The name of a validator key specifying a Method Server validator to be called when the user navigates to the step using the Previous or Next button.

required

no

true or false any string any string

beforeJS afterJS

no

None None

beforeVK

no

None

any string

Constructing Wizards

14-61

Action attribute tag afterVK

Req? no

Default value None

Possible values any string

Description The name of a validator key specifying a Method Server validator to be called after the user clicks Next or Finish on the step. Can be used to do server-side validation of the form data. Specifies that the wizard step is to be downloaded when wizard is launched rather than when the user navigates to the step. Pre-loading wizard steps will make it faster to move to the next step. However, you should not preload wizard steps that are dependent on information gathered in previous steps.

preloadWizardPa ge

no

true

true or false

Note that the windowType attribute of the command subtag should always be set to wizard_step.
Creating service.properties Entries for the Define Object and Set Attributes Steps

You will notice that the command tag for both the Define Object and Set Attributes wizard step actions above contain a url attribute referencing the TypeBasedIncludeServlet. The TypeBasedIncludeServlet allows the system to look up the correct jsp page to use for a wizard step or part of a wizard step onthe-fly given an action name and the type of object to be created. Using this servlet for the url for wizard steps allows: wizards for different object types to share the same step action definition reuse of the same wizard action and main wizard jsp for different object types if the wizards are identical except for steps that use the TypeBasedIncludeServlet for jsp lookup. Typically this is most useful when you want to use the same wizard to create different subtypes of a base type.

For the Define Object step a default jsp is available, but you can override this by use of the TypeBasedIncludeServlet and still use the common action definition for your step. For the Set Attributes step, use of the TypeBasedIncludeServlet allows you to specify different step jsps for the different object types that might be selected by the user in the Define Object step without creating a new action for the step or a new wizard. The TypeBasedIncludeServlet looks up the correct jsp using ApplicationContextServices and service.properties files. It locates the file entry for the service com.ptc.netmarkets.util.misc.FilePathFactory that has a selector matching the contextAction parameter on the url in the action tag and a requestor object type matching the type of object the user has chosen to create. The value of that entry gives the path of the jsp page for the step, relative to <WT_HOME>/codebase. Entries are formatted as follows: Xconf file:

14-62

Windchill Customizers Guide

<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor=" <object type to be created> >" resource=" <jsp file path relative to WT_HOME/codebase>.jsp" selector="<contextAction parameter on url>"/> </Resource>

Corresponding property file entry generated by the xconfmanager:


wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFa ctory/<step action name>/ <object type to be created>/0=<jsp file path>

For example, say you want to use the jsp page <WT_HOME>/codebase/netmarkets/jsp/ext/part/myPart/setAttributesWizStep.js p for the Set Attributes step of wizards when the user elects to create an object of type ext.part.MyPart. You would add the following entry to a type-based services properties xconf file:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="ext.part.MyPart" resource= /netmarkets/jsp/ext/part/myPart/setAttributesWizStep.jsp selector="setAttributesWizStep"/> </Resource>

The service.properties files searched by the TypeBasedIncludeServlet are those listed in the following two properties in the codebase/wt.properties file:
wt.services.applicationcontext.TypeBasedServiceProviderFromProp erties.defaultPropertyFiles wt.services.applicationcontext.TypeBasedServiceProviderFromProp erties.customPropertyFiles

See the Adding a Custom Service Provider Property File section on page 5-27 for more information on service property files.
Creating Your Step JSP Pages

Standard includes for step jsps 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/createEditUIText.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"%>

Constructing Wizards

14-63

Non-preloaded steps should also have the following directive at the bottom of the step jsp:
<%@ include file="/netmarkets/jsp/util/end.jspf"%>

If a step is preloaded, none of these are needed. Attribute Input Tables and Panels Object creation wizards typically have property panels and/or tables for entering attribute values. These are implemented using describePropertyPanel and describeAttributesTable tags containing a describeProperty tag for each attribute to be displayed. The ids on the describeProperty tags identify the attribute you want to be displayed. Property Report The Property Report lists all the attributes defined for a given object type (for example, wt.doc.WTDocument) and whether or not a data utility is available for it. The property report can be accessed at: http://<WINDCHILL_HOSTNAME>/<WEBAPP NAME> /netmarkets/jsp/property/propertyReport.jsp. If you have a custom attribute for which no data utility, GUI component, and/or renderer exists you may need to write your own to display the attribute. Keep in mind that many of the attributes shown in the Property Report are not settable by the user and would not be appropriate to display in a create or edit wizard. The describePropertyPanel and describeAttributesTable tags for input fields should always have a mode parameter of CREATE and a componentType parameter of WIZARD_ATTRIBUTES_TABLE. This tells the dataUtilities to generate a special name attribute for each input field. The CreateObjectFormProcessor will recognize and set all attributes with such a special name attribute automatically after the wizard is submitted. The special name attributes consist of the following parts: <context information>___<AttributeIdentifier and other information about the attribute>___<input field type> (Note that the keys in the Maps returned by such methods as getTextArea(), getChangedTextArea(), getComboBox(), etc. of the ObjectBean class include only the text between the ___ separators.) These name attributes are not easily parsed and are not intended for use other than by the CreateObjectFormProcessor. If you want to set an attribute yourself in your form processing code and want to create a name for your attribute that you can identify, you can do one of two things: Create or override the data utility used for the attribute and call the setColumnName() method of the GUI component to set the name attribute. If there is a wrapper tag available for the GUI component you want to use, you could display the attribute outside of a table or panel using the wrapper

14-64

Windchill Customizers Guide

tag for the GUI component. In the name attribute of the wrapper tag you would specify the HTML name attribute for the input field. Using this method you would need to supply the attribute default value in the wrapper tag. See the javadoc for the wrappers tab library for the available GUI component wrappers. See the file WT_HOME/codebase/netmarkets/jsp/carambola/tags/tags.jsp for examples of how to use wrapper tags. Data acquisition The method getItemAttributes() in the class com.ptc.core.components.forms.CreateAndEditModelGetter is used by the getModel tags in all out-of-the-box wizards to acquire the data needed to populate attribute input tables and read-only tables in wizards. This is a TypeInstancebased method that can be used for custom tables also and should be adequate for most purposes.
Set Context Step JSP Page

If your wizard has a Set Context step, the out-of-the-box step jsp listed in the Solution Elements section on page 14-43 will usually suffice. The only time it might be necessary to develop your own step jsp is if you need to capture additional attribute values before you can display attributes presented on the Define Object step. For example, assume that: Your wizard launch point has no folder context You do not have any OIRs that set a default folder location for new objects You have 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 a 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 can you set the administrative domain parameter on the type picker based on the users folder selection in the Set Context step.) If you do develop your own Set Context jsp and want it to have a container picker, we recommend that you include the out-of-the-box jsp in it rather than copying the contents of the out-of-the-box jsp to your page. This will ensure your page will continue to behave correctly even if the context picker is modified in a future release.

Constructing Wizards

14-65

Define Object Step JSP Page

As stated in the Laying out your wizard steps and attributes section on page 14-49 your wizard may not need a Define Object step. If it does need one, you may be able to use the default jsp listed in the Solution Elements section on page 14-43. Even if you cannot use the default jsp as is, you may be able to reuse sub-jsps that it incorporates. The suggested name for this step JSP is: defineItemWizStep.jsp or defineItemWizStepFor<object type>.jsp (if there is more than one of these step jsps in the directory) If the Define Object step is the first step in your wizard or nothing in this step is affected by data on prior steps you can preload it. Otherwise, you should indicate it should not be preloaded in the step action. Typically, if your wizard has a Set Context step this step should not be preloaded. The default jsp (<WT_HOME>/codebase/netmarkets/jsp/object/defineItemWizStep.jsp) for this step contains a property panel with the following sections (from top to bottom of panel): A read-only subpanel displaying the container name. If your new object type is not WTContained you will need to modify this. A type picker If your wizard does not require a type picker or it needs to be configured differently than the default, you will need to develop your own step jsp. A driver attributes subpanel for input of the objects owning organization, if the new object type is OrganizationOwned. Note this is only displayed if the preference Display -> Expose Organization is set to true. If the new object is not OrganizationOwned the default JSP will display nothing in this subpanel. This subpanel is contained in a sub-jsp file that is looked up at runtime using the TypeBasedIncludeServlet. If you need to display additional attributes or dont want to display an organization picker, you need only write a jsp containing this panel and register it with a type-based service.properties file entry as described in the How to create a step with no driver attributes section on page 14-70 and the How to create a step with additional driver attributes section on page 14-70. You can still use the default JSP page for the step. The default Define Object Step jsp includes a number of other jsps located in <WT_HOME>/codebase/netmarkets/jsp/components and

14-66

Windchill Customizers Guide

<WT_HOME>/codebase/netmarkets/jsp/object, as shown in the table and picture below:


JSP defineItemWizStep.jsp Description Main jsp for step; includes configureTypePicker tag for presenting & configuring type picker Contains the describePropertyPanel tag for the read-only panel Contains describeProperty tags for the attributes in the read-only panel Looks up the JSP for the driver attributes panel and gets the data for and renders all the page elements. 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 any time the type value is changed. Makes an ajax call to the TypeBasedIncludeServlet to get the JSP containing the describePropertyPanel, getModel, and renderPropertyPanel tags for the driver attributes table. Unless overridden by a service.properties entry for a specific type, one of the following JSPs will be used: <WT_HOME>/codebase/netmarkets/jsp/ob ject/defineItemAttributesPanel.jsp (for OrganizationOwned objects) <WT_HOME>/codebase/netmarkets/jsp/ob ject/defineItemAttributesPanelEmpty.jsp (for all other objects) defineItemStepContextPanel.jspf contains the getModel and renderPropertyPanel tags for the read-only attributes subpanel

defineItemReadOnlyPropertyPanel.jspf defineItemReadOnlyProperties.jspf defineItem.jspf

driverAttributesSetup.jspf

Constructing Wizards

14-67

The sections below describe how to perform common customizations of this step. Please remember that you should always place your custom jsp and jspf files in a directory under wtSafeArea, as described in the Managing Customizations chapter on page 5-1.
How to create a step without a read-only property panel

1. Create a new main jsp file for the step 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/defineItemWizStep.jsp into your new file. 3. Delete the following line from the file:
<%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPane l.jspf"%>

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 <WT_HOME>/netmarkets/jsp/object/defineItemWizStep.jsp into your new main jsp file.

14-68

Windchill Customizers Guide

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/defineItemReadOnlyPropertyPane l.jspf"%>

Be sure to set the following attributes on your describePropertyPanel tag:


Attribute var id scope mode Value defineItemStepContextPanelDescriptor defineItemStepContextPanelDescriptor request VIEW

Alternatively, you could include a new jspf file that contains your describePropertyPanel tag instead of placing it in-line. See the Sample Code section on page 14-84 for an example.
How to create a step without a type picker

1. Create a new main jsp file for the step. 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/defineItemWizStep.jsp into your new file. 3. Delete the following line from the file:
<jca:configureTypePicker/>

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. Create a new main jsp file for the step, as described above. 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/defineItemWizStep.jsp into your new file. 3. Add the following line to the top of the file:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%>

Constructing Wizards

14-69

4. Add pickerParam subtags to the configureTypePicker tag as shown in the javadoc for the ConfigureTypePickerTag. See the Sample Code section on page 14-84 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/defineItemAttributesPanelEm pty.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 <WT_HOME>/codebase/netmarkets/jsp/object/defineItemAttributesPanel.js p as an example and list the attributes you want to display in the describePropertyPanel tag. Because the output of this jsp is parsed and inserted dynamically 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>

Developing Your Set Attributes Step JSP Page

Because the attributes on this step vary by object type, you will need to create your own main jsp for this step. However, once you describe the contents of the page there are jsp components available to help you acquire the data models for and render the elements. The suggested name for this step jsp is: setAttributesWizStep.jsp or

14-70

Windchill Customizers Guide

setAttributesWizStepFor<object type>.jsp (if there is more than one of these step jsps in the directory) If your wizard does not have a type or template picker and nothing on prior steps affects the attributes displayed on the Set Attributes step it can be preloaded. Otherwise, you should indicate this step should not be preloaded in the step action. Typically, the latter is the case. Typically, in the main jsp file for this step you will do the following, in this order: 1. Include the file /netmarkets/ jsp/components/setAttributesReadOnlyPropertyPanel.jspf, which inserts a describePropertyPanel tag for a read-only property panel displaying: the objects owning container (if the object is WTContained) the object type organization id (if the preference Display -> Expose Organization is set to true)

2. Include a describeAttributesTable tag listing the attributes you want to display in the input table. The mode attribute of the tag should be set to CREATE. You should also set the following attributes if you want to use the out-of-thebox jspf file described in the next step for getting the table model and rendering the table.
Attribute Value

var id scope

attributesTableDescriptor attributesTableDescriptor (recommended, not required) request

You can make use of the Property Report described in the section Attribute Input Tables and Panels earlier in this section to obtain the ids for the attributes you want to include in your table. Also, refer to theAttribute Handling section on page 13-2 and the Soft Attributes and SCAs section on page 13-21 of the Presenting Information in the UI chapter for a description of some server calculated attributes (SCAs) that you might want to include. If your object is a subtype of WTPart and you want to include a classification picker in your table, you would add the following property to your table:
<jca:describeProperty id="classification.id" label="${classificationLabel}"/>

and you must include the following hidden fields in the page:
<input id="selectedClfNodes" type="hidden" name="selectedClfNodes" >

Constructing Wizards

14-71

<input id="selectedClfNodesDisplayName" type="hidden" name="selectedClfNodesDisplayName" >

3. If your object is a FormatContentHolder and you want to capture primary content input on this step, include the file /netmarkets/jsp/document/setAttributesWizStepWithContent.jspf. This contains the tag primaryAttachmentWithMSOI, which will render input fields for capturing primary content. (See the Attachments section in the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for more information on this tag.) It also acquires the data for and renders the read-only property panel and the attributes input table, providing you have followed the naming conventions described in this section. If your object is not a FormatContentHolder, include the file /netmarkets/jsp/components/setAttributesWizStep.jspf. This does the same things as setAttributesWizStepWithContent.jspf except that it does not include a primaryAttachments tag. 4. .Include any checkboxes you desire to gather processing information. If your object is RevisionControlled and you want to include a Keep checked out checkbox, you can include the following jsp to display it:
/netmarkets/jsp/components/keepCheckedOutCheckbox.jspf

An example jsp is shown in the Sample Code section on page 14-84. To create steps that deviate from the normal pattern described above, see below.
How to create a step without a read-only property panel

Do not include the file setAttributesReadOnlyPropertyPanel.jspf in your step jsp.


How to modify the contents of the read-only property panel

Instead of including the file setAttributesReadOnlyPropertyPanel.jspf include your own jspf file with a describePropertyPanel tag for the panel or include a describePropertyPanel tag for the panel directly in your step jsp at the same location as the include. Your describePropertyPanel tag should include describeProperty tags for the attributes you want to display. Keep in mind that only property values that have been captured on previous steps can be displayed. Set the mode attribute of the tag to VIEW. Also set the following tag parameters if you want the setAttributesWizStep.jspf file to obtain the table data and render the panel for you.
Attribute Value

var id scope

attributesStepReadOnlyPanel attributesStepReadOnlyPanel (recommended, not required) request

14-72

Windchill Customizers Guide

Adding Set Classification Attributes and Attachments Steps

JSPs for these steps are available out-of-the-box. You need only include the step action in your main wizard JSP page.

Creating Data Validators for Your Steps


Validation of the data entered by users is done on a step-by-step basis. 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 servlet engine validation in a javascript method by specifying the method as the value of the afterJS attribute of the step action. Validation of data values against constraints defined for the attributes in the Rose model or Type Manager 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. Default server-side validators are available for the Set Context, Define Object, 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.ContextWizardS tepValidator" requestor="null" selector="setContextWizStep"/> <Option requestor="null" serviceClass="com.ptc.core.components.validators.DefineObjectSt epValidator" selector="defineItem" /> <Option serviceClass="com.ptc.core.components.validators.SetAttributesS tepValidator" requestor="null" selector="setAttributesWizStep"/> </Service>

The ContextWizardStepValidator just validates that the form data contains a valid container object reference. The DefineObjectStepValidator and SetAttributesStepValidators look at all the form data with the special name attribute described in the Creating Your Step JSP Pages section on page 14-63, Attribute Input Tables and Panels. They validate the data against all constraints that were defined for the attributes in the Rose model or Type Manager. They do that by calling the preProcess() method of the

Constructing Wizards

14-73

ObjectFormProcessor class for the wizard, which creates a in-progress instance of the object and validates all its attributes. The Set Classification Attributes step uses the same validator as the Set Attributes step. No validator is provided or needed for the attachments step. 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.

Creating Your Main Wizard JSP Page


Your main wizard JSP page should have the same standard includes as nonpreloaded wizard step JSPs. See Standard includes for step jsps on page 14-63 for more information. There are two major elements in your main wizard JSP page: an initializeItem tag a Wizard tag

See the Sample Code section on page 14-84 for example JSP pages.
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

14-74

Windchill Customizers Guide

See the <initializeItem> Tag Parameters section on page 14-82 for the attributes of this tag. The only required attribute is operation, which should be set to ${createBean.create} for object creation wizards.
Wizard tag

This tag has wizardStep subtags describing the steps of the wizard. The action parameter of these subtags points to the action defined for the step. If you are using the predefined action definition for a step, be sure the action parameter matches the name parameter of the action See Creating actions and/or service property entries for your wizard steps on page 14-60 for more information. The wizard tag also defines the buttons to be used Typically, wizards will use one of the two following button sets defined in codebase/actionmodels.xml: DefaultWizardButtonsNoApply (for multi-step wizards) NoStepsWizardButtons (for single-step wizards)

However, other buttons sets are available in actions.xml and custom button sets can be defined. The wizard tag has an optional formProcessorController attribute. This should not be needed for single-object create wizards. See the Windchill Client Architecture Wizard section on page 14-2 for more information on the wizard tag.
Attachment Step Requirements

See the Attachments section of the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for information on the elements that must be included to incorporate this step.

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 section on page 14-19.

Constructing Wizards

14-75

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: preprocess() method extracts all of the ObjectBean form data that has a special name attribute as described in the Attribute Input Tables and Panels section on page 14-64. 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 Manager or Rose model

14-76

Windchill Customizers Guide

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

setResultNextAction() method (called by the DefaultFormProcessorController) if the status of the FormResult is SUCCESS or NON_FATAL_ERROR, sets the nextAction on the FormResult to FormResultAction.REFRESH_OPENER; if the wizard was launched from a folder browser it also sets the refreshInfo attribute of the FormResult as follows: action = NmCommandBean.DYNAMIC_ADD oid = newly created object location = folder of new object

As a result, if launched from a folder browser, the wizard will be closed and the new object will be dynamically added to the folder in the right pane of the browser without refreshing the entire launch page; if not launched from a folder browser, the entire launch page will be refreshed. Any feedback messages put in the FormResult will be displayed to the user. Note that the ajax attribute on the wizard action must be set to row for dynamic row refresh to occur; if not set the entire launch page will be refreshed regardless of the values in the dynamicRefresh attribute. If the status set on the FormResult is FAILURE, sets the nextAction to FormResultAction.NONE. This will return the user to the wizard page on which OK was clicked.

Note the CreateObjectFormProcessor does not implement postProcess() or postTransactionProcess() methods so these are inherited from the DefaultObjectFormProcessor. See the javadoc for more information. 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

Constructing Wizards

14-77

CreateObjectFormProcessor. Some of these are shown in the table below. Consult the javadoc for these classes for more information on their behavior.
If your class extends: WTPart Use processor class: If creating a wizard to be launched from a workspace: com.ptc.windchill.enterprise.part.forms.CreatePartFrom WorkspaceFormProcessor If creating a wizard to be launched from the Edit Structure client: com.ptc.windchill.enterprise.part.forms.CreatePartFromT abularInputProcessor All other single-object creation wizards: com.ptc.windchill.enterprise.part.forms.CreatePartFormP rocessor WTDocument For creating a document from a template: com.ptc.windchill.enterprise.doc.forms.CreateDocFromT emplateFormProcessor For creating a document template: com.ptc.windchill.enterprise.doc.forms.CreateDocTempl ateFormProcessor For all other single-object create wizards: com.ptc.core.windchill.enterprise.doc.forms.CreateDocFo rmProcessor WTChangeIssue WTChangeRequest2 WTChangeOrder2 WTChangeActivity2 WTVariance com.ptc.windchill.enterprise.change2.forms.processors.C reateProblemReportFormProcessor com.ptc.windchill.enterprise.change2.forms.processors.C reateChangeRequestFormProcessor com.ptc.windchill.enterprise.change2.forms.processors.C reateChangeNoticeFormProcessor com.ptc.windchill.enterprise.change2.forms.processors.C reateChangeTaskFormProcessor com.ptc.windchill.enterprise.change2.forms.processors.C reateVarianceFormProcessor.

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 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

14-78

Windchill Customizers Guide

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 the Attribute Input Tables and Panels section on page 14-64 for more information. 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: 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.

Constructing Wizards

14-79

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 section in the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-4 and the javadoc for the FormResult, FormProcessingStatus, and FormResultAction classes for more information. 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 cant 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)

14-80

Windchill Customizers Guide

{ < do error handling > } 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); preProcessResult = mergeIntermediateResult(preProcessResult, delegatesResult); if (!continueProcessing(preProcessResult)) {

Constructing Wizards

14-81

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.

Customization Points <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.
Parameter operation Default Value None Possible Values CreateAndEditWizB ean.CREATE CreateAndEditWizB ean.EDIT objectHandle baseTypeName the type associated with the wizard action any Windchill type identifier string No Not used for single-object creation wizards The string form of the Windchill type 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 picker. Optional. If not specified, the type associated with the wizard action will be used. Req? Yes Description Indicates whether the object is being created or edited.

<configureTypePicker> Tag Parameters


Parameters to this tag are in the form of pickerParam subtags. Example syntax:
<jca:configureTypePicker>

14-82

Windchill Customizers Guide

<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 seedType

Default Value None

Possible Value any Windchill type identifier string (logical or external) any Windchill type identifier string (logical or external)

Req? No

Description The top-level type that should be used to generate the list of types. For example, "wt.part.WTPart". May include more than one of these parameters. The type that should be selected by default. For example, "wt.part.WTPart." May be a string, such as "Select a Type" rather than a type name.

defaultType

For certain types the default is taken from a preference (see Background on page 14-38) For all other wizards, the base type is used. None

No

filterType

any Windchill type identifier string (logical or external) true (to display hierarchy) false (to display flat list)

No

A type that should be excluded from the type list. For example, "SoftPartType1". The descendants of the filter type are also excluded. May include more than one of these parameters. Indicates whether the type list should be displayed as a flat list or in hierarchical form.

displayHierarch y

false

No

showRoot

true

true (to display seed types) false (to not display seed types)

Whether the seedTypes should not be displayed.

adminDomainR efString

domain associated with the default folder location (see Background on page 14-38)

any administrative domain reference string

No

String representation of the administrative domain reference that should be used for access-control filtering of the type list. For example, "wt.admin.AdministrativeDomain:7"

Constructing Wizards

14-83

Parameter type

Default Value BOTH

Possible Value ROOT_TYPES (only seedTypes will be displayed) SOFT_TYPES (only soft types will be displayed) MODELED_T YPES (only modeled types will be displayed BOTH (both modeled and soft types will be displayed)

Req? No

Description Indicates the kind of types to be displayed. Value should be one of the enum constant value defined in com.ptc.windchill.enterprise.picker.type .server.TypePickerTypes.

Sample Code Default JSP for the Define Object Wizard Step
Filename: <WT_HOME>/codebase/netmarkets/jsp/components/defineItemWizStep.jsp This jsp is mapped to the defineItemWizStep action for objecttype=object in <WT_HOME>/codebase/actions.xml. It is the default jsp that will be used for this step unless overridden for a specific type.
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.j spf"%> <jca:configureTypePicker/> <%@ include file="/netmarkets/jsp/components/defineItem.jspf"%> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Define Object Step of the New Part Wizard
Filename: <WT_HOME>/codebase/netmarkets/jsp/part/defineItemWizStep.jsp

14-84

Windchill Customizers Guide

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" 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"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <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>

Constructing Wizards

14-85

<%-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> <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"%> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Set Attributes step of the New Problem Report Wizard
Filename: <WT_HOME>/codebase/netmarkets/jsp/problemReport/create_details.jsp Elements typical to most Set Attributes step jsps are shown in bold.
<%@taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca" %><%@taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt" %><%@taglib uri="http://www.ptc.com/windchill/taglib/changeWizards" prefix="cwiz" %><%@include file="/netmarkets/jsp/components/beginWizard.jspf" %><%@include file="/netmarkets/jsp/components/createEditUIText.jspf"

14-86

Windchill Customizers Guide

%><%@ include file="/netmarkets/jsp/components/includeWizBean.jspf" %> <!-- Setup the localization string constants --> <fmt:setLocale value="${localeBean.locale}"/> <fmt:setBundle basename="com.ptc.windchill.enterprise.change2.change2ClientResour ce" /> <fmt:message var="tableTitle" key="ATTRIBUTES_TABLE"/> <%@ include file="/netmarkets/jsp/change/setAttributesReadOnlyPropertyPanel.js pf"%> <%-->Build a table descriptor and assign it to page variable td<-%> <jca:describeAttributesTable var="attributesTableDescriptor" id="create.problemReportDetailsStep" mode="CREATE" scope="request" componentType="WIZARD_ATTRIBUTES_TABLE" type="wt.change2.WTChangeIssue" label="${tableTitle}"> <jca:describeProperty id="number" /> <jca:describeProperty id="name" /> <jca:describeProperty id="requester" inputFieldType="singleLine" /> <jca:describeProperty id="theIssuePriority"/> <jca:describeProperty id="theCategory"/> <jca:describeProperty id="description" /> <jca:describeProperty id="ALL_CUSTOM_HARD_ATTRIBUTES_FOR_INPUT_TYPE"/> <jca:describeProperty id="ALL_SOFT_NON_CLASSIFICATION_SCHEMA_ATTRIBUTES"/> </jca:describeAttributesTable> <cwiz:initializeSubmitNow/> <%@include file="/netmarkets/jsp/components/setAttributesWizStep.jspf"%> <script language='Javascript'> loadAllRemainingNonRequiredSteps(); </script> <%@include file="/netmarkets/jsp/util/end.jspf"%>

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"%>

Constructing Wizards

14-87

<%@ 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"> <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"%>

14-88

Windchill Customizers Guide

Additional Resources Related Package/Class Javadoc


com.ptc.core.components.forms.CreateAndEditModelGetter com.ptc.core.components.forms.CreateObjectFormProcessor com.ptc.core.components.forms.DefaultObjectFormProcessor com.ptc.core.components.forms.DefaultObjectFormProcessorDelegate com.ptc.core.components.forms.FormResult com.ptc.core.components.forms.FormResultNextAction com.ptc.core.components.forms.DynamicRefreshInfo com.ptc.core.components.tags.components.InitializeItemTag com.ptc.core.components.tags.components.ConfigureTypePickerTag Common Components Tag Lib Javadoc

Constructing Wizards

14-89

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 Rose model or Attribute and Type Manager. 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

14-90

Windchill Customizers Guide

Scope/Applicability/Assumptions
Assume you have created a custom Persistable business object class or soft type 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 nonWorkable 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 soft attributes of custom subtypes on the Set Attributes step as shown below:

Constructing Wizards

14-91

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 soft 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.

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 the Building Wizards to Create a Single Object topic (see page 14-38 for more information), especially the Prerequisite knowledge section is on page 14-43.

14-92

Windchill Customizers Guide

Solution Elements
Element Tags autoCheckOutItem Note: All of the tags in the Solution Elements section of the Building Wizards to Create a Single Object topic are also applicable to edit wizards. This tag is in addition to those. See Building Wizards to Create a Single Object on page 14-38 for more information. (The Solution Elements section is on page 14-43.) 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_COPY_RE F_PARAMETER_NAME. This tag should be put in the main JSP for the wizard immediately below the initializeItem tag. Tag library: <WT_HOME>/codebase/WEBINF/tlds/workinprogress.tld Tag handler: com.ptc.windchill.enterprise.wip.tags.AutoCheck OutObjectTag JSPs setAttributesWizStep jspf file A jsp file (also used for create wizards) that can be included in the jsp for your Set Attributes wizard step. This will get the model data for and render your attributes panel and table if you have named them per the instructions in this document. Runtime location: <WT_HOME>/codebase/netmarkets/jsp/compon ents setAttributesWizStepWithContent .jspf jspf file A jsp file that can be included in the jsp for your Set Attributes wizard step if your object type is a FormatContentHolder. It does the same things as the jsp above but, in addition, will render input fields for capturing primary content. Location: <WT_HOME>/codebase/netmarkets/jsp/docume nt Beans CreateAndEditWizBean Java class; Runs in the servlet engine and the Method Server This bean is available to your jsps if you include the includeWizBean jspf file. It has getter methods for wizard data such as the operation (create or edit) and working copy object reference. Type Description

Constructing Wizards

14-93

Element Java Classes

Type

Description You can use the classes below to help create and process your wizard. They are located in the <WT_HOME>/codebase/WEBINF/lib/wncWeb.jar file.

CreateAndEditModelGetter

Java class Runs in the Method Server

A class that may be called via a getModel tag to generate the data for property panels and attributes tables in edit wizards. A class that may be called to validate the data in the Set Attributes wizard step. A class that may be used or extended to process wizard form data for nonWorkable objects. Extends DefaultObjectFormProcessor. A class that may be used or extended to process wizard form data for Workable objects. Extends DefaultObjectFormProcessor.

EditAttributesStepValidator DefaultEditFormProcessor

Java class; runs in the Method Server Java class; Runs in the Method Server

EditWorkableFormProcessor

Java class; Runs in the Method Server

Procedure Creating Your Wizard


You will need to perform the following tasks to create your wizard: Lay out your wizard steps and attributes Create an action for the wizard Create actions and/or service properties entries for the wizard steps Create jsp and/or jspf files for your wizard steps or portions thereof Create a main jsp file for your wizard Create validators for the wizard data Create a form processor class and/or delegates to process the wizard data after submittal

The tasks shown in bold are always required. The other tasks may or may not be needed, depending on the requirements of your wizard. If you have 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.
Laying out your wizard

Because the attributes described as driver attributes in the Single-Object Create Wizards Best Practice are not editable, edit wizards generally have fewer steps.

14-94

Windchill Customizers Guide

They are also usually less complex because refresh of wizard fields when other field values are changed is not required. Edit wizards for non-change objects generally have one to three steps as follows: 1. Set Attributes Step This step is common to almost all edit wizards and is where the user edits most of the objects attributes. It generally contains one to three parts: a readonly context property panel, primary content input fields (for FormatContentHolder objects only), and an attribute input table. Refer to the illustration below.

Context panel Read-only information about the object being edited. This varies by object type. Typically, the object type is displayed. If the object is WTContained it also usually displays the container name. If the new object is OrganizationOwned and the preference Display -> Expose Organization is set to true it also typically displays the organization id.

Constructing Wizards

14-95

You will need to decide what, if any information needs to be displayed in this panel for your object type. Primary content Wizards to create objects that are FormatContentHolders, such as WTDocuments, should have a section for the user to modify the primary content item. Attribute input table This typically contains input fields for all the editable soft and hard attributes for the object type, except for part classification attributes, which are entered on a following step. A few non-editable attributes, such as Name in the illustration above, may be displayed at the top of the table in read-only mode. You will need to decide what attributes should be displayed in this table. 2. Set Classification Attributes 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(s) of the part in view mode at the top and then includes a table of input fields for classification attributes.

14-96

Windchill Customizers Guide

3. Attachments Step This step only applies to objects that are ContentHolders. It allows the user to add and delete documents, links, and other content for the object. See the Attachments section of the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for information on incorporating this step.
Creating the Action for Your Wizard

An action is needed to launch your wizard. This task is very similar to creating an action for a create wizard. Refer the Creating the Action for Your Wizard procedure in the Building Wizards to Create a Single Object section on page 14-97. 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 section on page 14-93 or a subclass of one of those classes. We recommend you name your action (and main wizard jsp file) edit. If there will be multiple edit actions for your objecttype based on launch point or other criteria you can add a suffix further qualifying the action as shown below. For example: editFrom<launch page or table> edit<name for a subset of attributes being edited> Ex: editFromAttributesTable Ex: editAnnotations

Creating Actions and/or Service Property Entries for Your Wizard Steps

You may be able to use out-of-the-box action definitions for wizard steps that are common to multiple wizards. The following wizard step actions are defined outof-the-box.

Step Set Attributes

Objecttype object

Action definition/ File Location/ Associated JSP Page <action name="editAttributesWizStep" id="editAttributesWizStep" preloadWizardPage="false" required="true" afterVK="editAttributes" resourceBundle="com.ptc.core.ui.componentRB"> <command windowType="wizard_step" url="servlet/TypeBasedIncludeServlet?contextAction=editAttributesWiz Step"/> </action> Action file: <WT_HOME>/codebase/actions.xml Associated jsp page: None

Constructing Wizards

14-97

Step Set Classification Attributes

Objecttype part

Action definition/ File Location/ Associated JSP Page <action name="setClassificationAttributesWizStep" id="setClassificationAttributesWizStep" hidden="true" required="true" preloadWizardPage="false" afterVK=editAttributes> <command windowType="wizard_step"/> </action> Action file: <WT_HOME>/codebase/ config/actions/PartManagementactions.xml. Associated jsp page: <WT_HOME>/codebase/netmarkets/jsp/part/setClassificationAttributes WizStep.jsp Note: This is the same action used for this step in part create wizards

attachments_s tep

attachments (ContentHolde r)

<action name="attachments_step" uicomponent="ATTACHMENTS" ajax="row" postloadJS="preAttachmentsStep" preloadWizardPage="false"> <command class="com.ptc.windchill.enterprise.attachments.forms.SecondaryAttach mentsSubFormProcessor" windowType="wizard_step"/> <includeFilter name="hideFromDTI" /> <includeFilter name="EDACompareFilter" /> </action> Action file: <WT_HOME>/codebase/config/actions/Attachments_actions.xml Associated jsp page: <WT_HOME>/codebase/netmarkets/jsp/attachments/attachments_step.js p

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. Also note that the Set Classification Attributes step is marked as hidden. It is dynamically inserted into the wizard if the part is classified when the wizard launches. It is dynamically removed if the user clicks the Do Not Classify radio button in the "Set Attributes Step" to unclassify the part. If these action definitions meet your requirements you do not need to define your own actions for your wizard. However, you will need to define your own action for a wizard step if either of the following is true: You need to define additional or different tag attributes for the step action Your step is unique to your wizard.

14-98

Windchill Customizers Guide

Note that you can use your own JSP for the Set Attributes step without defining your own step action by use of the TypeBasedIncludeServlet described below. See the Creating Actions and/or Service Property Entries for Your Wizard Steps of the Building Wizards to Create a Single Object section on page 14-97 for more information on creating step actions.
Creating service.properties Entries for the Set Attributes Step

The Creating service.properties Entries for the Set Attributes Step of the Building Wizards to Create a Single Object section on page 14-99 describes how the TypeBasedIncludeServlet is used to look up the jsp that should be used for some wizard steps or portions of wizard steps. For edit wizards, the servlet is used to look up the jsp that should be used for the Set Attributes step. This allows you to use the common action definition for this step but still create and use your own step jsp. If you have multiple wizards that differ only by the content of this step, it also means you can use the same main wizard JSP and wizard action definition for all of them. This is often the case when creating wizards for different subtypes of the same base type. To specify which jsp should be used for this step for a specific object type you would include an entry like the following in a type-based service.properties file: Xconf file:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor=" <object type to be edited> >" resource=" <jsp file path relative to WT_HOME/codebase>.jsp" selector="editAttributesWizStep"/> </Resource>

Corresponding property file entry generated by the xconfmanager:


wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto ry/editAttributesWizStep/ <object type to be edited>/0=<jsp file path relative to WT_HOME/codebase>.jsp

Note that the selector string matches the contextAction parameter on the URL in the step action. For example, to use the jsp page <WT_HOME>/codebase/netmarkets/jsp/ext/part/myPart/setAttributesWizStep.js p for the Set Attributes step when editing objects of type ext.part.MyPart you would add the following entry to a type-based service.properties xconf file:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="ext.part.MyPart" resource= /netmarkets/jsp/ext/myPart/setAttributesWizStep.jsp selector="editAttributesWizStep"/> </Resource>

Constructing Wizards

14-99

Creating Your Step JSP Pages


See the Creating Your Step JSP Pages of the Building Wizards to Create a Single Object section on page 14-63 for information on how to create your step jsps. Differences between create and edit wizards are noted below.
Attribute Input Tables and Panels

The describePropertyPanel and describeAttributesTable tags for input fields should have a mode parameter of EDIT. The componentType parameter is WIZARD_ATTRIBUTES_TABLE, just as for create. Using EDIT mode will cause input fields to be generated for each attribute in the table or panel by default. If you want a specific attribute to be displayed in readonly mode you can override the default mode by specifying a mode parameter on the describeProperty tag as shown in the example below:
<jca:describeAttributesTable var="attributesTableDescriptor" scope="request" id="create.setAttributes" mode="EDIT" componentType="WIZARD_ATTRIBUTES_TABLE" type="wt.part.WTPart" label="${attributesTableHeader}"> <jca:describeProperty id="name" mode="VIEW"/>

Developing Your Set Attributes Step JSP

Because the attributes on this step vary by object type, you will need to create your own main jsp for this step. However, once you describe the contents of the page there are jsp components available to help you acquire the data models for and render the elements. These are the same components that are used for create wizards. The suggested name for this step jsp is: editAttributesWizStep.jsp or editAttributesWizStepFor<object type>.jsp (if there is more than one of these step jsps in the directory) This step is very similar to the Set Attributes wizard step for create wizards. Typically, it will include the following: 1. A describePropertyPanel tag for the read-only attributes panel at the top of the step. This tag should have a mode parameter of VIEW. Also set the following tag attributes if you are including setAttributesWizStep.jspf file to obtain the data for and to render your panel:
Attribute Value

var

attributesStepReadOnlyPanel

14-100

Windchill Customizers Guide

Attribute

Value

id scope

attributesStepReadOnlyPanel (recommended, not required) request

2. A describeAttributesTable tag for editing hard and soft attributes. The mode of this tag should be set to EDIT. (See the section Attribute Input Tables and Panels above for how to make individual attributes view-only.) You should also set the following tag attributes if you want to use the out-of-thebox jspf file described in the next step for getting the table model and rendering the table.
Attribute Value

var id scope

attributesTableDescriptor attributesTableDescriptor (recommended, not required) request

If your object is a subtype of WTPart and you want to include a classification picker in your table, you would add the following property to your table:
<jca:describeProperty id="classification.id" label="${classificationLabel}"/>

and you must include the following hidden fields in the page:
<input id="selectedClfNodes" type="hidden" name="selectedClfNodes" > <input id="selectedClfNodesDisplayName" type="hidden" name="selectedClfNodesDisplayName" >

3. If your object is a FormatContentHolder and you want to allow users to edit the primary content input on this step, include the file /netmarkets/jsp/document/setAttributesWizStepWithContent.jspf. This contains the tag primaryAttachmentWithMSOI, which will render a section for editing of primary content. See the Attachments section of the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for information on this tag. It also acquires the data for and renders the read-only property panel and the attributes input table, providing you have followed the naming conventions described in this section. If your object is not a FormatContentHolder, include the file /netmarkets/jsp/components/setAttributesWizStep.jspf. This does the same things as setAttributesWizStepWithContent.jspf except that it does not include a primaryAttachment tag.

Constructing Wizards

14-101

Note that these JSPFs are also used for create wizards. See the Sample Code section on page 14-107 for an example page.
Adding Set Classification Attributes and Attachments Steps

JSPs for these steps are available out-of-the-box. You need only include the step action in your main wizard JSP page. Customization of these steps is not recommended.

Creating Data Validators For Your Steps


A default server-side validator is available for the Set Attributes step. The selector key and validator class path are specified in the following entry in components.service.properties.xconf:
<Option requestor="null" serviceClass="com.ptc.core.components.validators.EditAttributes StepValidator" selector="editAttributes" />

This validator works exactly like the SetAttributesStepValidator for create wizards --- it also calls the preprocess() method of the wizard form processor to validate the data against all constraints that were defined for the attributes in the Rose model or Type Manager. If the out-of-the-box validator class meets your needs you can use it by specifying the selector string shown in the entry above as the value of the afterVK attribute of your wizard step action. If you need to do additional validation, you can write your own validator, typically subclassing the default validator. The Set Classification Attributes step uses the same validator as the Set Attributes step. No validator is provided or needed for the attachments step.
Creating Your Main Wizard JSP Page

This should look much the same as that for a create wizard, with the differences noted below. See the Sample Code section on page 14-107 for example JSPs.
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/>

14-102

Windchill Customizers Guide

This tag will check out the object to the current user before opening the wizard. See the Solution Elements section on page 14-93 for more information.
InitializeItemTag

Like create wizards, edit wizards require 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.
Wizard Tag

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 <WT_HOME>/codebase/config/actions/actionmodels.xml. To include a Set Attributes step in your wizard you should provide a wizardStep tag with the action name editAttributesWizStep (if you are using the common step action shown in the Creating Actions and/or Service Property Entries for Your Wizard Steps section on page 14-97) or the action name you specified on your custom action. To include Set Classification Attributes and/or Attachments steps, use the action names shown for these steps in Creating Actions and/or Service Property Entries for Your Wizard Steps section on page 14-97).
Classification Step Requirements

If your wizard includes a Set Classification Attributes step you will need to dynamically load that step if the part being edited is classified. The js function loadClassificationStep() in <WT_HOME>/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> .

Constructing Wizards

14-103

. . <script language="Javascript"> Event.observe(window, 'load', 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. If the Set Attributes step is not the first step in your wizard and it is not preloaded, you will also need to include the following in your Set Attributes step jsp:
<script language="JavaScript" src="netmarkets/javascript/part/PartHelper.js"></script> . . . <script language="Javascript"> Event.observe(window, 'load', loadClassificationStep); </script>

Attachment Step Requirements

See the Attachments section of the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-16 for information on the elements that must be included to incorporate this step.

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

14-104

Windchill Customizers Guide

These classes may be extended as necessary to meet your purposes.

Both of these processors do the following: 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 varies as follows: DefaultEditFormProcessor.setResultNextAction() (called by the DefaultFormProcessorController)

Constructing Wizards

14-105

If the status of the FormResult is SUCCESS or NON_FATAL_ERROR, sets the next action to FormResultAction.REFRESH_OPENER; it also sets the refreshInfo attribute of the FormResult as follows: action = NmCommandBean.DYNAMIC_UPDATE oid = object that was edited location = object that was edited

As a result, if the edited object is displayed in a table row of the launch page and the ajax action on the wizard action was set to row, only the table row will be refreshed. If the ajax action was set to page or was not specified, the entire launch page will be refreshed. If the ajax action was set to component and the wizard was launched from a table toolbar, only that table will be refreshed. If the status set on the FormResult is FAILURE, sets the nextAction to FormResultAction.NONE. This will return the user to the wizard page on which OK was clicked.

EditWorkableFormProcessor.setResultNextAction() (called by the DefaultFormProcessorController) If the status of the FormResult is SUCCESS or NON_FATAL_ERROR and the Check In button was clicked

Sets the next action to FormResultAction.JAVASCRIPT and adds javascript to launch the check in action. If the edit action was launched from a table row, the table row will be refreshed when the checkin completes. If the edit action was launched from an info page, the info page of the new iteration will be displayed when the check in completes.

and the Save button was clicked

If the wizard was launched from the folder browser, sets the next action to FormResultAction.REFRESH_OPENER and adds dynamic refresh attributes to refresh the table row of the edited object If not launched from the folder browser, sets the next action to FormResultAction.LOAD_OPENER_URL and loads the url for the info page of the working copy

If the status of the FormResult is FAILURE sets the next action to FormResultAction.NONE

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

14-106

Windchill Customizers Guide

the table below. Consult the javadoc for these classes for more information on their behavior.
If your class extents Use processor class

WTChangeIssue WTChangeRequest2 WTChangeOrder2 WTChangeActivity2 WTVariance

com.ptc.windchill.enterprise.change2.forms.process ors.EditProblemReportFormProcessor com.ptc.windchill.enterprise.change2.forms.process ors.EditChangeRequestFormProcessor com.ptc.windchill.enterprise.change2.forms.process ors.EditChangeNoticeFormProcessor com.ptc.windchill.enterprise.change2.forms.process ors.EditChangeTaskFormProcessor com.ptc.windchill.enterprise.change2.forms.process ors.EditVarianceFormProcessor

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 the Creating Your Form Processor and Form Processor Delegates section on page 14-75 for examples of cases where you may need to implement your own processor.netmarkets/jsp/components/beginWizard.jspf 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 JSP for the Set Attributes Step of the Edit Part Wizard
Filename: <WT_HOME>/codebase/netmarkets/jsp/part/editPartAttributesWizStep.jsp
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%> <%@ page import="com.ptc.windchill.enterprise.part.partResource" %> <%@ page import="com.ptc.windchill.enterprise.part.PartConstants" %> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%>

Constructing Wizards

14-107

<fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/> <fmt:message var="classificationLabel" key="<%= partResource.CLASSIFICATION_LABEL %>" /> <fmt:message var="locationLabel" key="<%= partResource.LOCATION_LABEL %>" /> <fmt:message var="typeNameLabel" key="<%= partResource.TYPE_NAME_LABEL %>" /> <fmt:message var="minimumRequiredLabel" key="<%= partResource.MINIMUM_REQUIRED_LABEL %>" /> <fmt:message var="maximumAllowedLabel" key="<%= partResource.MAXIMUM_ALLOWED_LABEL %>" /> <%--> Read-only context panel <--%> <jca:describePropertyPanel var="attributesStepReadOnlyPanel" id="attributesStepReadOnlyPanel" scope="request" mode="VIEW" type="wt.part.WTPart"> <jca:describeProperty id="containerName" label="${createBean.containerLabel}"/> <jca:describeProperty id="partTypeName" label="${typeNameLabel}"/> <jca:describeProperty id="orgid" need="organization.id"/> </jca:describePropertyPanel> <%--> Attributes input table <--%> <jca:describeAttributesTable var="attributesTableDescriptor" scope="request" id="create.setAttributes" mode="EDIT" componentType="WIZARD_ATTRIBUTES_TABLE" type="wt.part.WTPart" label="${attributesTableHeader}"> <jca:describeProperty id="number" mode="VIEW" isInfoPageLink="false"/> <jca:describeProperty id="name" mode="VIEW"/> <jca:describeProperty id="version" mode="VIEW"/> <jca:describeProperty id="partType"/> <%--> Source uses a special data utility to hide the other options except 'Buy' if SUMA is installed and the part type is manufacturing or vendor <--%> <jca:describeProperty id="source"/> <%--> The following 3 are WADM specific attributes. They are hidden by the PartSolutionGroup logic if WADM is not installed. <--%> <jca:describeProperty id="<%=PartConstants.ColumnIdentifiers.WADM_CONTRACT_NUMBER%>"/ >

14-108

Windchill Customizers Guide

<jca:describeProperty id="<%=PartConstants.ColumnIdentifiers.WADM_JOB_AUTH_NUMBER%>"/ > <jca:describeProperty id="<%=PartConstants.ColumnIdentifiers.WADM_PHASE%>"/> <jca:describeProperty id="classification.id" label="${classificationLabel}"/> <jca:describeProperty id="minimumRequired" label="${minimumRequiredLabel}"/> <jca:describeProperty id="maximumAllowed" label="${maximumAllowedLabel}"/> <jca:describeProperty id="ALL_CUSTOM_HARD_ATTRIBUTES_FOR_INPUT_TYPE"/> <jca:describeProperty id="ALL_SOFT_NON_CLASSIFICATION_SCHEMA_ATTRIBUTES"/> </jca:describeAttributesTable> <%--> The following fields are necessary for the classification picker in the table above <--%> <input id="selectedClfNodes" type="hidden" name="selectedClfNodes" > <input id="selectedClfNodesDisplayName" type="hidden" name="selectedClfNodesDisplayName" > <%@ include file="/netmarkets/jsp/components/setAttributesWizStep.jspf"%> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Main JSP for the Edit Product Wizard


Filename: <WT_HOME>/codebase/netmarkets/jsp/product/editProductWizard.jsp Notes: This is a one-step wizard
<%@ page import="com.ptc.windchill.enterprise.product.productResourceClient " %> <%@ 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.productResourceClie nt" />

Constructing Wizards

14-109

<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>

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

Main JSP for the Edit Part Wizard


Filename: <WT_HOME>/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 <--%>

14-110

Windchill Customizers Guide

<script language="JavaScript" src="netmarkets/javascript/part/PartHelper.js"></script> <% if(InstalledProperties.isInstalled(InstalledProperties.SCMI)) { %> <attachments:fileSelectionAndUploadApplet forceApplet='${param.addAttachments != null }'/>

<% } %>

<%--> 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/> <% } %>

<% if ((request.getParameter("newInWorkspace") != null) || (request.getParameter("checkedOutInWorkspace") != null)) { %> <script language="Javascript">newOrCheckedOutInWorkspace=true</script> <% } %>

Constructing Wizards

14-111

<%--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. JSP file for the step is, however, part specific and hooked up using PartManagement-typedservicesproperties.xconf <--%> <jca:wizardStep action="editAttributesWizStep" label="${editAttributesWizStepLabel}" type="object"/> The

<jca:wizardStep action="setClassificationAttributesWizStep" type="part"/> <%--> The attachments step will get enabled or disabled based on the AttachmentsStepActionValidator hooked up to it <--%> <jca:wizardStep action="attachments_step" label="${attachmentsWizStepLabel}" type="attachments" />

</jca:wizard>

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

14-112

Windchill Customizers Guide

Additional Resources Related Package/Class Javadoc


com.ptc.core.components.forms.DefaultEditFormProcessor com.ptc.core.components.forms.EditWorkableFormProcessor Also see the Related Package/Class Javadoc of the Building Wizards to Create a Single Object section on page 14-89.

Constructing Wizards

14-113

14-114

Windchill Customizers Guide

15
Information Pages
This chapter describes how to customize information pages. Topic Page

Information Pages..............................................................................................15-2

15-1

Information Pages
Objective
You want to create an object information page specific to a given business object.

Solution
Use the Info Page Common Component with an info.jsp file associated to that object type.

Design Overview
There are many types of business objects in Windchill, plus potentially many soft types or modeled object types introduced by customers. Each type of object can potentially have its own associated information page, a page that displays information around a selected instance of that type. While the information associated with different object types can vary widely, it is important to maintain a common look and feel among the multitude of information pages. The info page component was developed to give the Windchill products consistency for displaying an object details page. The component is also intended to make developing an info page much easier. Using the component, a developer only needs to configure certain parts of the page (list of actions, which attributes to show, etc.) while the main layout of the page is provided by the component.

Applicability
This design pattern should be used for configuring the info page for some business object in one of the Windchill products.

15-2

Windchill Customizers Guide

Structure

Design Elements
The info page component Page title area Top attributes panel Visualization area Navigation menu Filter area Content area Global navigation Type-specific data

Information Pages

15-3

Actions list Recently visited list Auditing service Object attributes Status glyphs

Collaborations
The info page component controls the layout of the various other components on the page; page title area, top attributes panel, visualization area, navigation menu, filter area, and content area, as well as including the global navigation. The info page component supports type based lookups (including soft types) for the type specific data, attributes, 3rd level navigation menu. The info page component hooks up to the global navigation as appropriate (e.g.: tab highlighting) The info page component displays the correct action list based on object type The info page component registers the object in the recently visited list The info page component registers the user and the object in the auditing service for the view event The info page component does role based checking on attributes The info page component allows Status Glyph Indicators

Consequences
By following this design pattern the configuration of all objects info pages should be done in a consistent manner. This will make maintaining these info pages a much easier and more manageable task and have a consistent user model.

Implementation Overview
The info page component was developed using the Windchill client architecture. This component provides a common layout for an objects information page as it is displayed in any of the Windchill products. Using the info page component will provide consistency between all objects and Windchill products. The specific content that is displayed for any given object type will be configured by overriding certain elements in the context of the specific object types. Configurable portions of the page include things like which action list is used and which attributes are shown in the top attribute panel.

15-4

Windchill Customizers Guide

What is the component


it is a combination of a jsp, bean, taglib, renderers and service call(s). it follows user interface standards it is Section 508 compliant per requirements it supports customization requirements it supports Soft type/attribute it follows a standard format for the Item Identification release specific recommendationIdentifying the object it supports the Object Icon including support for soft types and part flavors like Generic it supports third level Navigation stickiness and remembers the last third level navigation table that the user was viewing. per navigation specification

The default info page implementation will only contain the object icon, the name of the object, and possibly a link to the action list if one has already been configured

To display more than the default provides, you can create a new jsp that is configured for your type. All the details links (e.g. , ) will lead to the same servlet. As shown below, the TypeBasedInclude servlet receives the request for an info page and determines which navigator delegate to use. The navigator delegate determines which jsp to redirect to based on the object type and the state of the object. A jsp using the info page common component would include netmarkets/jsp/components/infoPage.jspf.

Using the component


In the default information page, only the name of the object, the object icon and possibly a link to the action list would appear. Most likely, for your object type, you will want to override the default set of information that is displayed. The configurable portions of the page are: Action list displayed in the top attributes panel Visualization area

Information Pages

15-5

Status glyphs Help context Attributes displayed in the top attributes panel Third level navigation menus Actions contained in each third level navigation menu Default third level content table and table view

Create a jsp for your object type Create a jsp


Your info page jsp will have a describeInfoPage tag, a describePropertyPanel tag, and an include of the info page component, infoPage.jspf. Based on the configuration in the describeInfoPage and describePropertyPanel tags, the infoPage.jspf component will render the object icon, object identification, status glyphs, help link, action list, attributes panel (property panel), visualization component, 3rd level navigation and 3rd level navigation content. Before the include of infoPage.jspf, your jsp can set up what information is displayed on the page. (e.g. what attributes to show, whether or not visualization applies, what action model to use for 3rd level nav etc.) See section 9.4 for the properties that can be configured in your info page jsp: For example:
<jca:describePropertyPanel var="propertyPanelDescriptor"> <jca:describeProperty id="name" /> <jca:describeProperty id="number" /> </jca:describePropertyPanel> <jca:describeInfoPage showVisualization="true" helpContext="part_details_help" navBarName="third_level_nav_part" propertyPanel="${propertyPanelDescriptor}"> <jca:describeStatusGlyph id="statusFamily_Share" /> <jca:describeStatusGlyph id="statusFamily_General" /> <jca:describeStatusGlyph id="statusFamily_Change" /> </jca:describeInfoPage>

Register 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.FragmentFa ctory/InfoPage/java.lang.Object/0=/netmarkets/jsp/object/info.j sp

15-6

Windchill Customizers Guide

wt.services/rsc/default/com.ptc.netmarkets.util.misc.FragmentFa ctory/InfoPage/<fully qualified class path>/0=<jsp path relative to codebase>.jsp Here is an example of the xconf format: <Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="<fully qualified class path>" resource="<jsp path relative to codebase>" selector="InfoPage"/> </Resource>

See the About the xconfmanager Utility section in the Windchill Utilities chapter on page 6-2 for more information.

Specify Status Glyphs to show in the Title Bar


<jca:describeInfoPage > <jca:describeStatusGlyph id="<Status Glyph Family Id>" /> </comp:describeInfoPage>

Specify the Attributes to include


<jca:describePropertyPanel var="propertyPanelDescriptor"> <jca:describeProperty id="<attribute name | data utility id | logical form>" /> <jca:describeProperty id="<attribute name | data utility id | logical form>" /> </comp:describePropertyPanel> <jca:describeInfoPage propertyPanel="${propertyPanelDescriptor}"> </comp:describeInfoPage>

To determine the set of available properties that can be displayed for an object type, you can use the property report.

Information Pages

15-7

Configure Action List Actions


The Actions that apply for a particular object type are configured in actionmodels.xml.

To specify which actionmodel to use as the actions list for a specific class or softtype, use the attribute menufor as specified in the following example:
<!-- Part information page Actions list --> <model name="more parts actions" menufor="wt.part.WTPart"> <action name="view" type="object"/> <action name="viewDefaultRepresentationPV" type="wvs"/> <action name="viewDefaultRepresentationPVLite" type="wvs"/> <action name="launchPSE" type="explorer" /> <action name="launchABE" type="explorer" /> <action name="separator" type="separator"/> <action name="checkin" type="wip"/> <action name="checkout" type="wip"/> <action name="undocheckout" type="object"/> ..

For example:
<!-- your comment here --> <model name="<your_action_model_name>" menufor="<fully qualified classpath>"> <action name="view" type="object"/> </model>

Or, if you want to have multiple classes or soft types you can comma separate the list:

15-8

Windchill Customizers Guide

<model name="more meeting actions" menufor="wt.meeting.TraditionalMeeting,wt.meeting.MeetingCenterMee ting"> <action name="host" type="meeting"/> <action name="join" type="meeting"/> <action name="add_minutes" type="meeting"/> </model>

The info page uses what is registered in actionmodels.xml with menufor as the action list. You can override what is registered in actionmodels.xml by configuring the describeInfoPage with a different actionListName to use:
<jca:describeInfoPage actionListName="<action model name>" > </jca:describeInfoPage>

If no actions list should be displayed you can specify that also:


<jca:describeInfoPage actionListName="" > </jca:describeInfoPage>

Indicate if Visualization applies


By default visualization is hidden. You can configure your info page to show visualization by setting showVisualization to true.
<jca:describeInfoPage showVisualization="<true/false>" > </jca:describeInfoPage>

Specify the help context to use


To specify a help topic for the info page a service.properties.xconf entry is needed and the help selector key from that entry can be added to the describeInfoPage tag.
<Resource context="default" name="wt.help.HelpTemplate"> <Option requestor="<context class>" resource="<help file path>" selector="<help selector key"/> </Resource>

For example:
<Resource context="default" name="wt.help.HelpTemplate">

Information Pages

15-9

<Option requestor="java.lang.Object" resource="online.pdm_prodmgmt.PMPartStructureEdit" selector="PMPartStructureEdit_help"/> </Resource>

Selector is a help selector key that will be set on the describeInfoPage tag. In the above example it is PMPartStructureEdit_help. Resource is the help file location and is assumed to be an html file. The help file gets a base of $WT_HOME/codebase/wt/helpfiles/help_<locale> Hence in the above example where resource="online.pdm_prodmgmt.PMPartStructureEdit" the english help file will be:
$WT_HOME/codebase/wt/helpfiles/help_en/online/pdm_prodmgmt/PMPartS tructureEdit.html

Requestor is the class of the container context that the object is in. For example, parts could be created in either Products or Projects. If the help topic for parts in Projects had to be different from the help topic for parts in Products, an entry could be added with requestor="wt.projmgmt.admin.Project2". Once the above xconf entry is created, the help topic can be set on the info page by adding the selector on the describeInfoPage tag:
<jca:describeInfoPage helpContext="<help selector key>" > </jca:describeInfoPage>

Specify the Third Level Navigation Menubar to use

<jca:describeInfoPage navBarName="<action model name>" > </jca:describeInfoPage>

Configure the Third Level Navigation Menus for your object type
The following is an example configuration of a third level navigation menu for the part info page:
<!-- Part information page 3rd level nav menu bar --> <model name="third_level_nav_part"> <action name="productStructure" type="object"/> <submodel name="general"/>

<!-- Structure --> <!-- General -->

15-10

Windchill Customizers Guide

<submodel name="relatedItems"/> <submodel name="history"/> <submodel name="collaboration"/> </model>

<!-- Related Objects --> <!-- History --> <!-- Collaboration -->

As you can see it is a combination of an action and submodels. An action in the 3rd level nav bar will be displayed as just a link. (e.g. Product Structure browser) A submodel in the 3rd level nav bar will be displayed as a drop down menu (e.g. Related Items menu) The General, Related Items, History and Collaboration menus are meant to be reused for all object types. Actions that do not apply for certain object types will be removed via action validation. So your action model would probably look something like this:
<!-- your comment here --> <model name="<your_action_model_name>"> <submodel name="general"/> <submodel name="relatedItems"/> <submodel name="history"/> <submodel name="collaboration"/>
</model>

<!-- General --> <!-- Related Objects --> <!-- History --> <!-- Collaboration -->

Create a new 3rd level nav action


To create a new 3rd level nav action. See the Adding Actions and Hooking Them Up in the UI chapter on page 11-1 for more information on actions. Register the action. Add the action to the action model. Create the jsp for the action. The jsp just has to have the 3rd level nav content between begin.jspf and end.jspf. For example, if a jsp had this content:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <b>Related Parts table goes here...</b> <table border=1> <tr><td>A</td><td>B</td></tr> <tr><td>C</td><td>D</td></tr> </table> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Then the image below would be the resulting 3rd level nav content (the action that led to the above jsp was added to the relatedItems submodel so that is why Related Objects is highlighted)

Information Pages

15-11

Setup

Parameter Attribute

Default Value None

Possible Values See section Specify the Attributes to include TBD Specify Status Glyphs to show in the Title Bar User defined. Specify the help context to use User defined in actionmodels. xml. User defined in actionmodels. xml. Set only if you want to override menufor setting in actionmodels. xml.

Req? No

Description describeProperty tag nested in describePropertyPanel tag

statusGlyph

None

No

describeStatusGlyph tag nested in describeInfoPage tag

helpContext

None

No

As attribute on the describeInfoPage tag

navBarName

None

No

As attribute on the describeInfoPage tag

actionListName

The action model specified in actionmodels.x ml based on classname that is in the oid.

No

As attribute on the describeInfoPage tag

Sample Code Example implementation for the InfoPageComponent


This is an example of how the info page could be configured for some object type. Assume you are configuring the info page for wt.part.CoolPart. These steps reference codebase locations only. These steps do not include instructions for source placement or best practices for usage of xconf files. 1. Create a jsp file called info.jsp and place it in the following location in your codebase
codebase/netmarkets/jsp/coolpart

15-12

Windchill Customizers Guide

For now, just add the following content to the page:


<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <H2>This will be the cool part details page</H2> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

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/InfoPage/wt.part.CoolPart/0=/netmarkets/jsp/coolpart/info .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/TypeBasedIncludeSer vlet?oid=OR:wt.part.CoolPart:62028

The servlet will look up which jsp to forward to in typedservices.properties. You should see the text that you typed into your jsp in step 1. 4. Now, lets add some content to your page. First, youll need the jca components taglib:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

5. Then, youll need to describe a property panel that contains the attributes that apply for your object type. Using the property report on your build (see Property Report on page 14-64), find the attribute names you want to use:
<jca:describePropertyPanel var="propertyPanelDescriptor"> <jca:describeProperty id="name" /> <jca:describeProperty id="number" /> </jca:describePropertyPanel>

6. Next, describe the info page. Specify the third level nav, the help file, whether visualization applies, which property panel to use, and the status glyph families to be shown:
<jca:describeInfoPage showVisualization="true" helpContext="<cool_part_info_help>" navBarName="<third_level_nav_for_cool_part>" propertyPanel="${propertyPanelDescriptor}"> <jca:describeStatusGlyph id="statusFamily_Share" /> <jca:describeStatusGlyph id="statusFamily_General" /> </jca:describeInfoPage>

7. After setting up the describePropertyPanel and describeInfoPage tags include the infoPage.jspf. The component will acquire the necessary data (attributes, icon images, action models, etc.) and display the info page (attribute panel, title bar, 3rd level nav, etc.)
<%@ include file="/netmarkets/jsp/components/infoPage.jspf"%>

Information Pages

15-13

Here is the example info.jsp:


<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ include file="/netmarkets/jsp/util/begin.jspf"%> <jca:describePropertyPanel var="propertyPanelDescriptor"> <jca:describeProperty id="name" /> <jca:describeProperty id="number" /> </jca:describePropertyPanel> <jca:describeInfoPage showVisualization="true" helpContext="<cool_part_info_help>" navBarName="<third_level_nav_for_cool_part>" propertyPanel="${propertyPanelDescriptor}"> <jca:describeStatusGlyph id="statusFamily_Share" /> <jca:describeStatusGlyph id="statusFamily_General" /> </jca:describeInfoPage> <%@ include file="/netmarkets/jsp/components/infoPage.jspf"%> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Implementation of Info Page with No 3rd Level Navigation


Some info page instances do not require a third level navigation menu. For instance when there are few enough tables that all the tables should just display on the screen by default. For these cases, simply omit the navBarName attribute:
<jca:describeInfoPage navBarName="<action model name>" > </jca:describeInfoPage>

Or include the line, but with the navBarName value as an empty string:
<jca:describeInfoPage navBarName="" > </jca:describeInfoPage>

Known Uses
Many out-of-the-box business objects in Windchill have info pages that are built using the Info Page component. Here are a couple examples: WTPart codebase/netmarkets/jsp/part/info.jsp WTDocument codebase/netmarkets/jsp/document/info.jsp

15-14

Windchill Customizers Guide

16
Incorporating Pickers in JSP Clients

This chapter describes how to customize and configure pickers. Topic Page

Picker Interaction ............................................................................................. 16-2 Common Picker Configuration Options......................................................... 16-14 Configuring a Context Picker......................................................................... 16-18 Configuring an Item Picker ............................................................................ 16-24 Configuring an Organization Picker............................................................... 16-31 Configuring a Type Picker ............................................................................. 16-37 Configuring a User Picker.............................................................................. 16-50 Configuring a Participant Picker .................................................................... 16-57

16-1

Picker Interaction
Objective
You want to configure a property picker in some wizard step and manage interaction between that page and the picker.

Background
There are many types of business objects in Windchill, plus potentially many soft types or modeled object types introduced by the user. These types would predominantly would have some relationship with the other types. There are numerous instances when user creates or updates objects of such types using an user interface, he would need to specify the property value(s) derived from the other available objects of the same or different type. e.g. The business object like Part or Document are owned by a specific organization and hence at the time of their creation user needs to be able to specify an owning organization. This sort of user interaction is achieved through the use of property picker. The property picker simply aids in picking up a property from an existing business object. The user would pick an object by launching the picker and have its pro properties used to update visible and/or non-visible properties on the page. The following sketch illustrates this sort of interaction pictorially.

Scope/Applicability/Assumptions
Assume you have a customized type <myObjectType> object needing to be created. On the first step of the create wizard, you need to define a relation ship with an object of type <someObjectType>. This spawns a need to let user select the object he desires from a picker and have the attributes of these objects used to populate some content on the first step of the create wizard.

16-2

Windchill Customizers Guide

Intended Outcome
By following this design concept, the property picker user model would be consistent with the one that exists across the product at multiple places.

Solution
Follow the design concept as described to facilitate the picker interaction.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving HTML forms, JSP, JavaScript based DOM manipulations, AJAX The actions framework in the Windchill client architecture The table component to list the objects. The wizard component in the Windchill client architecture

Incorporating Pickers in JSP Clients

16-3

Solution Elements
Element Type Description

picker.tld

tld

Tag Library Descriptor (TLD) file, which contains Picker related Tag definitions. The propertyPicker,populate and pickerParam are the ones needed to be used to implement this design concept. Run time Location:
<Windchill>\codebase\WEB-INF\tlds\

create_step_<step no>.jsp

JSP

This JSP page provides the content for the specified step of the Create Wizard . This step would include the controls to launch a picker and populate values from the picked object. This JSP could as well render a javascript picker callback function to be executed once the picker OK action is executed. Run time Location:
<Windchill>\codebase\netmarkets\ <myObjectType>\create_step_<stepno>.jsp

<someObjectType>_picker.jsp

JSP

This JSP page defines a single step wizard with OK and Cancel actions for the wizard. The wizard step would render a content that presents a list of <someObject> in table or tree component. The user would select the object of interest by ticking the check boxes to select row(s) in the table. Run time Location:
<Windchill>\codebase\netmarkets\< someObjectType >\ <someObjectType>_picker.jsp

<someObjectType>_picker_st ep.jsp

JSP

This JSP page defines the content for the picker wizard step. This step can contain a table listing the objects of <someObjectType> or search criteria along with Run time Location:
<Windchill>\ codebase\netmarkets\< someObjectType >\ <someObjectType>_picker_step.jsp

16-4

Windchill Customizers Guide

Element

Type

Description

Actions.xml

XML

The file has definitions of all the actions. The action that launches picker need to get defined for the type <myObjectType>. The picker wizard step actions as well get defined in this file. JSP fragment to be always included by the picker implementation i.e. in <someObjectType>_picker_step.jsp Run time location:
<Windchill>\codebase\netmarkets\components\ picker.jspf

picker.jspf

JSPF

defaultPickedDataFetcher.jsp

JSP

Default Picker Data Fetcher available in the product. It uses the oids passed to get the specified attributes. The oid and attribute information is compiled into a string as JSON representation to be sent back as http response. Run time location:
<Windchill>\codebase\netmarkets\components\ defaultPickedDataFetcher.jsp

Procedure Creating a Picker Interaction


This section defines the exact steps to implement a picker.
Implement a Picker as a single step wizard

Author a JSP page named as <someObjectType>_picker.jsp. This JSP page must include a single step wizard using the wizard component of the Windchill Client Infrastructure. The jsp would look like this:
<%@ page errorPage="/netmarkets/jsp/util/error.jsp"%> <%@ page import=" . %> <jsp:useBean scope="request" > <!As the wizard step content might have a flexibility in presenting itself and can be controlled by the picker parameters, these parameters could be passed to the step using a bean with request scope <%@ include file="/netmarkets/util/beginPopup.jspf"%> <%@include file=/netmarkets/components/picker.jspf%> . .. .. <script language="JavaScript1.2"> <!sets a callback to javascript function on hitting ok action setUserSubmitFunction(onOK); </script> <%--> Wizard Step. <--%> <jca:wizard buttonList="OkCancelWizardButtons">

Incorporating Pickers in JSP Clients

16-5

<jca:wizardStep action="<someObjectType>_picker_step " type="<someObjectType>"/> </jca:wizard> <!Javascript callback function for wizard OK action goes here <!- OK callback definition start .. <!OK callback definition end <%@ include file="/netmarkets/jsp/util/end.jspf"%>

The picker.jspf is needed to be included in the picker page always. It defines the following javascript window variables to track the pickerCallback and jcaPickerCallback functions. These windows variables are needed to be used in the OK action javascript user submit function . The setUserSubmitFunction is needed to be invoked to configure wizard OK action to invoke a javascript function. The javascript callback definition would be as well included in this page, the definition of this callback and any other definitions of functions the callback calls need to be placed preferably before the end.jspf is included.
Implement a Picker step

The picker step content would get defined by the codebase\netmarkets\< someObjectType >\<someObjectType>_picke_stepr.jsp. This step would render a search client or just a listing table to allow the user select the objects from. The details on how this could be done can be found out in the design pattern for Search Picker OR table component.
Provide definition of the javascript function to be invoked on OK action

The javascript callback definition would be as well included in this page, the definition of this callback and any other definitions of functions the callback calls need to be placed preferably before the end.jspf is included. This java script function has to fulfill the following responsibilities It would not have any arguments to it. It scans the page and sifts through the table or tree data to identify what objects have been selected, if any are selected builds an array of these objects. Invokes a pickedDataFetcher uri using AJAX and the array of objects selected passed over query string parameters as oid=<oid_value> parameters that the pickedDataFetcher URI can understand. The AJAX request returns the response

Use a picker

To use the existing picker, the user would have to perform the following procedures. Define the action to launch a picker

16-6

Windchill Customizers Guide

The action needs to be defined in codebase\actions.xml as follow.


<objecttype name="< myObjectType> " class=">"> <action name="launch<SomeObjectType>Picker"> <command windowType="popup"/> </action> </objecttype>

Create the HTML form elements to be updated using the picker

Create the visible input fields that need to be updated as a part of the picker interaction using the AbstractGuiComponent to the client page i.e. create_step_<step no>.jsp. See the Presenting Information in the UI chapter on page 13-1 for more information on how to use GUI components. The following describes how to add a textfield.
<% TextBox<SomeObjectType> name = new TextBox(); tab_tbox.setId("<SomeObjectType>Name_tbox_id"); tab_tbox.setName("<SomeObjectType>Name_tbox_id"); RenderingContext tab_rcontext = new RenderingContext(); %> <c-rt:set var="tbox" value="<%=<SomeObjectType> name %>"/> <c-rt:set var="tboxId" value="<%=<SomeObjectType> name .getId()%>"/>

Create the non-visible input fields that would be as well updated as a part of the picker interaction in the client page mentioned above.
<input id="<SomeObjectType>Reference" type="hidden" value=" " />

Use the tags

Use the PropertyPickerTag in client page, i.e. create_step_<step no>.jsp, utilizing the information from the Create HTML form elements to be updated using the picker section as follows
<p:propertyPicker propertyLabel="<SomeObject>" propertyField="${ tbox }" action=" launch<SomeObjectType>Picker " type="< myObjectType>"> <p:populate from="name" to="${ tboxId }" /> <p:populate from="oid" to="<SomeObjectType>Reference 2" /> <p:pickerParam name="pickerId" value="userPicker1" /> <p:pickerParam name="objectType" value="wt.org.WTUser" />

Incorporating Pickers in JSP Clients

16-7

<p:pickerParam name="componentId" value="pickerSearch" /> </p:propertyPicker>

The above usage supposes that user would be interested in using the name and oid attributes from the information extracted for the pickedObject.

Default Data Fetcher


The default data fetcher is implemented in the form of a jsp page invoked using the AJAX asynchronous request. This page looks for the pickedOids and attributes query string parameters in the request. The page then invokes an Info*Engine webject to extract the attribute values for the specified Oid. The Oid could be in the form of Object Reference or Version Reference or UFID. The page returns the extracted information as a single string from which one can easily construct the javascript object. Such a string would look like
{"pickedObject": [{"oid":"uid=wcadmin,ou=people,cn=koakx1044,dc=ptcnet,dc=ptc,d c=com","class":"wt.org.WTUser","name":"Administrator"},{"oid":"uid =demo,ou=peopl e,cn=koakx1044,dc=ptcnet,dc=ptc,dc=com","class":"wt.org.WTUser","name":"demo"} ] }

Default Callback function


The default callback function is authored using the populate tag information, it does the task of updating the html form input text fields specified by the id using the attribute information for the object picked which is made available in the form of a javascript object. The default callback function would be of the following form and would be unique for each of the picker occurrence.
function jcaPickerCallBack0(objects) { document.getElementById("b1").setAttribute("value",objects.pickedO bject[0].name); document.getElementById("b2").setAttribute("value",objects.pickedO bject[0].oid); } function jcaPickerCallBack1(objects) { document.getElementById("c1").setAttribute("value",objects.pickedO bject[0].name); document.getElementById("c2").setAttribute("value",objects.pickedO bject[0].oid); }

16-8

Windchill Customizers Guide

Customization Points propertyPicker tag attributes


This tag configures a property picker.
Parameter label Default value Possible values Any String Value Required? Yes Description The localized display label of the property the value of which is to be populated using a picker.

field

AbstractGuiComp onent

Yes

The AbstarctGuiComponent object like TextBox that would be used to render the form field that would be populated from picker object. The name of the action as it exists in actions.xml The type of the action for which the definition exists in actions.xml that would launch the picker. Rendering context to be used for the AbstractGuiComponent specified through a field attribute

name type

Any String value Any String value

Yes Yes

renderingCont ext

RenderingContext

Yes

populate tag attributes


This tag configures source attribute of the picked object to be used to populate a target property on the client page. The tag would be always encapsulated in the propertyPicker tag.
Parameter from Default values Possible values Any String Value Required? Yes Description Specifies the name of the property (attribute) of the picked object

Incorporating Pickers in JSP Clients

16-9

Parameter to

Default values

Possible values Any String value but adhering to HTML id attribute specification criteria

Required? Yes

Description HTML 'id' of the form input element to update on the parent page.

pickerParam tag attributes


This tag configures the name=value URL query string parameters to drive the actual picker content. The tag would be always encapsulated in the propertyPicker tag.
Parameter name Default values Possible values Any String Value Required? Yes Description Name of the query string parameter to be passed to the popup picker Value of the URL query string parameter to be passed to the popup picker.

value

Any String Value

Yes

Sample Code
User can refer to the following code which is available in the product, it is a type picker. codebase\WEB-INF\tags\organizationPicker.tag - Defines the organizationPicker tag definition that uses internally the propertyPicker tag. Just a way to encapsulate abstract design concept. Following snippet of java scriptlet code, creates the visible and invisible form fields to be updated using the information from the picked objects
<%. String displayFieldId = id+SearchWebConstants.DISPLAY_FIELD_LABEL; RenderingContext rc = new RenderingContext(); TextBox tb = new TextBox(); tb.setId(displayFieldId); tb.setName(displayFieldId); tb.setValue(defaultValue);

16-10

Windchill Customizers Guide

if("true".equals(readOnlyPickerTextBox)) { tb.addJsAction("readonly","readonly"); } tb.setWidth(Integer.parseInt(pickerTextBoxLength)); tb.setMaxLength(Integer.parseInt(pickerTextBoxLength)); %> <input id="<%=id%>" name="<%=id%>" value="<%=defaultHiddenValue%>" type="hidden"/>

The following snippet of code propagates selectively the parameters passed to the organizationPicker tag to the propertyPicker tag
<p:propertyPicker label="${label}" field="${textbox}" action="callSearchPicker" type="search"> <p:populate from="${displayAttribute}" to="${displayFieldId}" /> <p:populate from="oid" to="${id}" /> <p:pickerParam name="pickerId" value="${id}" /> . </p:propertyPicker>

codebase\netmarkets\jsp\search\callSearchPicker.jsp - Defines the Picker Wizard codebase\netmarket\jsp\search\searchPicker.jsp - Defines the content for the Wizard step Following includes all the javascript code needed to manage the picker interaction.
<script language="javascript" src="<%=wncurl%>netmarkets/jsp/search/pickerSearch.js"> </script>

Following ensures specified JSP fragment is added by the picker implementation.


<%@ include file="/netmarkets/jsp/components/picker.jspf"%>

Following ensures that the search criteria and search results table are as well added to the step content.
<TABLE> <%@ include file="/netmarkets/jsp/search/pickerAttributes.jsp"%> .. <%@ include file="/netmarkets/jsp/search/searchResults.jsp"%> .

Incorporating Pickers in JSP Clients

16-11

codebase\netmarkets\jsp\search\pickerSearch.js Defines the javascript functions needed to be used to manager this picker interaction Following javascript function defines the callback function being used on the Wizard OK action, it collects the selected objects using their oids and invokes the data fetcher URI using AJAX.
function getSelectedValue() { }

The AJAX callback function is defined below which is actually responsible to use the AJAX response as JSON object and populate information on the client page using the picker callback function
function updateParent() { . }

codebase\netmarkets\components\picker.jspf Defines picker interaction specific must include code, to be included in picker implementation. The following javascript snippet inserted in the jsp fragment ensures that certain javascript variables are always populated and available to be used in the Wizard OK action callback function.
<script type="text/javascript" > window.pickerCallback = "<%=request.getParameter("pickerCallback")%>"; window.pickedAttributes = "<%=request.getParameter("pickedAttributes")%>"; window.pickedDataFetcher = "<%=request.getParameter("pickedDataFetcher")%>"; </script> ..

Note: The user of the picker can as well specify his own set of callback function or data fetcher using the pickerParam tag <p:pickerParam name= pickerCallback value=myPickerCallback /> <p:pickerParam name= pickedDataFetcher value= jsp/components/myPickedDataFetcher.jsp />

16-12

Windchill Customizers Guide

Parameter

Default values

Possible values

Req?

Description

pickerCallback

jcaPickerCallBac k

Name of the javascript function.

no

The javascript callback function to be invoked by the picker page after the user has picked object(s) and activated ok action. This callback is defined in the client page and would accept a single argument only. If the client chooses for default acquisition for the data of the picked objects, then this argument would be an object with a property named pickedObject of type Array, each object of the Array being an object containing the properties of interest of the picked object. The array would have as many objects as the objects that the user has picked. The URI of the jsp page that would be delegated with a task of extracting the data for the picked objects and return the information in the form of a literal string using which the javascript object as understood by the callback function could be created.

pickedDataFetcher

jsp/components/d efaultPickedData Fetcher.jsp

URI

no

Following snippet ensures that all AJAX related javascript artifacts are available for re-use.
<script type="text/javascript" src="netmarkets/javascript/util/prototype.js"></script> <script type="text/javascript" src="netmarkets/javascript/components/wizard.js"></script> codebase\netmarkets\components\picker.jspf

Examples of Usage in Windchill Code


All the search based pickers e.g. Item Picker, User Picker, Org Picker are all implemented using this core capability. These picker implementations are made available in the form of tag. These tag definitions internally use the core capability devised for the property picker.

Incorporating Pickers in JSP Clients

16-13

Common Picker Configuration Options


Objective
To configure a picker to accept seeded criteria for containers, customize it to user specified criteria options and results.

Background
Configure a picker to only display a specific soft-type of parts (Product Areas). Allow user to enter criteria that includes name (not number) and library. Include criteria (that the user cannot see/edit) to retrieve libraries that are NOT in an state of obsolete AND that include certain specific words in the library description. The picker should show the product area name, not show its number, and also include the library that contains the part.

Scope/Applicability/Assumptions
Lets assume we need to launch a customized part picker from a JSP client which would have the capability to define the soft type as a seed for searching and also would respect seeded containers to search in. We would be using our OOTB item picker tag to launch it from a JSP page.

Intended Outcome
We should be able to launch an Item Picker which would be configured to search in for a soft type of part. This would have a name field as criteria for the picker where the user can filter results based on name of the part. The results table would contain customized view for this picker where the container and the name of the part would be shown. It would also respect seeded criteria which would filter the query based on criteria such that the part belongs to library which has certain words in the description and are not obsolete.

Solution
A custom JSP page would be written to launch this picker with appropriate seeded criteria. We would be using the Item Picker tag to launch the picker.

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

16-14

Windchill Customizers Guide

Solution Elements
Element Type Description

PickerAttributes.xml

XML

Runtime location - \codebase\pickerAttributes.xml Clear case location - \Windchill\DevModules\Search\ src_web\pickerAttributes.xml This file is used to customize the search criteria at picker page.

SearchResultsTable.pro perties.xconf

Xconf

Runtime location - \codebase\com\ptc\netmarkets\search\ SearchResultsTable.properties.xconf This file can be used to configure table view definition.

Procedure Customizing picker to have user defined criteria and result view
Customizing the picker search criteria

The search criteria for a picker can be customized by defining the attributes in PickerAttributes.xml file. This can be done by creating a new component id and then defining the search criteria as 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>

Here we have defined a new component id as customizedItemPickerForSoftPart. We have defined a single attribute to be searchable i.e. the name of the soft type.
Launching the picker with custom component id and user defined object type

The picker can be launched by passing the above component id to customize the search criteria as defined above.
<wctags:itemPicker id="customized_item_picker" objectType="WCTYPE| wt.part.WTPart|org.r_and_d.mypart" componentId=" customizedItemPickerForSoftPart "/>

Seeding the picker with container criteria

We need to find objects within container based on some filter onto these containerss itself. Containers may be passed to the picker tag and objects would be queried within those containers only. The picker tag accepts a parameter named containerRef which can be a comma separated list of containers within

Incorporating Pickers in JSP Clients

16-15

which we want to search. The container references can be passed as below. The comma separate list of the containers can be fetched by querying for containers in which the user wants to search.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE| wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using generic" containerRef="<container ref here>" componentId=" customizedItemPickerForSoftPart " showVersion="false"/>

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. Please refer [Crating Table View] for details regarding creating and configuring a new view. Then we can pass the view as below to the picker tab and search results table would be rendered with this view.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE| wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using generic" containerRef="<%=containerRefs.toString()%>" componentId="scenarioOnePicker" searchResultsViewId="wt.part.WTPart.customizedSearchView" showVersion="false"/>

The view id wt.part.WTPart.customizedSearchView should be configured to lookup the java class associated with this id which would define the table view. Please refer to configuring table views document. An example to configure this in SearchResultTable.properties.xconf file could be
<Service context="default" name="com.ptc.core.htmlcomp.tableview.ConfigurableTable"> <Option serviceClass="com.ptc.netmarkets.search.views.CustomizedPartVie w" requestor="java.lang.Object" selector=" wt.part.WTPart.customizedSearchView "/> </Service>

A new java class com.ptc.netmarkets.search.views.CustomizedPartView should be created which would define the view columns for this picker customization.

Sample Code
Launching the picker in <pickerlauncher>.jsp
<html> <body> <table> <tr> This is a customization where a hidden seed for container refs is feeded to the picker. </tr> <tr> <%-launching Item Masterpicker--%>

16-16

Windchill Customizers Guide

<wctags:itemPicker id="customPartPicker" objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart" label="Custom Part Picker" containerRef="<%=containerRefs.toString()%>" componentId="scenarioOnePicker" searchResultsViewId="wt.part.WTPart.customizedSearchView" showVersion="false"/> </tr> </table> </body> </html>

The containerRefs passed above can be a list of comma separate containers from which we want to fetch the results. This parameter is optional and if not provided would launch picker to search in all containers.

Incorporating Pickers in JSP Clients

16-17

Configuring a Context Picker


Objective
You want to pick context(s) to be used in your application.

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 Find Button along with the specified label after using the tags for context picker. After clicking Find button, context picker will be launched.

16-18

Windchill Customizers Guide

On clicking Find button you should Context Picker for Project as:

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 RBINFO file customizations. Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients

16-19

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: <WT_HOME>\codebase\ pickerAttributes.xml

searchClientResource.rbInfo

RBINFO file

You should use this file to localize the contents of the pickers. Runtime location: <WT_HOME>\src\com\ ptc\windchill\enterprise\search\client\ searchClientResource.rbInfo

contextPicker.tag

Custom JSP tag file

This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\ WEB-INF\tags\itemPicker.tag

SearchableTypes.properties. xconf

xconf Properties file

You should specify component Id and corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\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: <WT_HOME>\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


Configure basic context picker:
<tr> <wctags:contextPicker id="contextPickerId" /> </tr>

16-20

Windchill Customizers Guide

Customization Points
Parameter id Default Value Possible Values Anything thats unique in a page Req? Yes Description An ID is associated with every picker in 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 determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the context picker Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. The title of picker.

componentId

pickerSearch

Any valid component id specified in pickerAttributes.x ml Name of the callback function

No

pickerCallback

Generated at the runtime if user has not specified this parameter (blank) (blank) <WebApp>/net markets/jsp/sear ch/pickedData.js p. Context Picker name

No

defaultValue defaultHiddenV alue pickedDataFetc her

Any values Any values URL location of the fetcher file

No No No

label displayAttribute

Any value Any attribute

No No

containerRef baseWhereClaus e

(blank) (blank)

Any container Any valid I*E where clause query

No No

pickerTitle

Contexts

Any value

No

Incorporating Pickers in JSP Clients

16-21

Parameter editable

Default Value true

Possible Values true/false

Req? No

Description This attribute defines whether you want to have Findbutton along with the textbox or not. This attribute defines whether the picker text box should be editable or not. This parameter is passed to define set of types that can be shown in Type Picker

readOnlyPicker TextBox typeComponentI d

false

true/false

No

Foundation.cont extPicker

Any valid componentId specified in SearchableTypes.p roperties file true/false

No

inline

false

No

You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a commaseparated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. This parameter should be used to enable type picker in the picker. 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. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccessController you can pass on comma (,) separated list of the class names.

pickedAttributes

name

Any comma separated list of valid attributes true/false search/picker

No

showTypePicker pickerType

true search

No No

pickerTextBoxL ength searchResultsVi ewId customAccessC ontroller

25 (blank)

Any numeric value Any valid view id

No No

(blank)

Any valid name

No

16-22

Windchill Customizers Guide

Parameter excludeSubType s

Default Value (blank)

Possible Values Any valid subtypes

Req? No

Description This parameter is used to exclude sub types from the search.

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*)" />

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; } }

Incorporating Pickers in JSP Clients

16-23

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 Find button, item picker will be launched.

16-24

Windchill Customizers Guide

On clicking Find button you should 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 RBINFO file customizations. Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients

16-25

Solution Elements

Element pickerAttributes.xml

Type XML file

Description You should use this file to customize the search criteria attributes for an object type for your picker. Runtime location: <WT_HOME>\codebase\ pickerAttributes.xml

searchClientResource.rb Info

RBINFO file

You should use this file to localize the contents of the pickers. Runtime location: <WT_HOME>\src\com\ptc\ windchill\enterprise\search\client\ searchClientResource.rbInfo

itemPicker.tag

Custom JSP tag file

This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\WEBINF\tags\itemPicker.tag

SearchableTypes.proper ties.xconf

xconf Properties file

You should specify component Id and corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\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: <WT_HOME>\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>

16-26

Windchill Customizers Guide

Customization Points

Parameter id

Default Value

Possible Values Anything thats unique in a page

Req? Yes

Description An ID is associated with every picker in 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 determines the attributes that should appear in search criteria panel of the given picker.

componentId

pickerSearch

Any valid component id specified in pickerAttributes.x ml Name of the callback function

No

pickerCallba ck

Generated at the runtime if user has not specified this parameter (blank) (blank) <WebApp>/net markets/jsp/sear ch/pickedData.js p. Item Picker name

No

Name of the customized callback function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the item picker Value of the containerRef in which a user wants to restrict the search.

defaultValue defaultHidde nValue pickedDataF etcher

Any values Any values URL location of the fetcher file

No No No

label displayAttrib ute containerRef

Any value Any attribute

No No

(blank)

Any container

No

Incorporating Pickers in JSP Clients

16-27

Parameter baseWhereC lause

Default Value (blank)

Possible Values Any valid I*E where clause query

Req? No

Description Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. If you want to specify different baseWhereClause for say, Part and Document, then you can do so using following syntax: wt.part.WTPart$SEP$<where clause that will get ANDed with internal whereClause>$OBJ$wt.doc.WTDocum ent$SEP$<where clause that will get ANDed with internal whereClause>. If you dont specify the object type then the one supplied will be used for all the object type. The title of picker. This attribute defines whether you want to have Findbutton along with the textbox or not. This attribute defines whether the picker text box should be editable or not. This parameter is passed to define set of types that can be shown in Type Picker

pickerTitle editable

Item true

Any value true/false

No No

readOnlyPic kerTextBox typeCompon entId

false Foundation.chan geablePicker

true/false Any valid componentId specified in SearchableTypes. properties file true/false

No No

inline

false

No

You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a commaseparated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. This parameter determines whether to display version/iteration attributes in search criteria or not. This attribute determines the default object type in the item picker. This parameter should be used to enable type picker in the picker.

pickedAttrib utes

name

Any comma separated list of valid attributes true/false

No

showVersion

true

No

objectType showTypePi cker

wt.fc.Persistable true

Any Windchill object type true/false

No No

16-28

Windchill Customizers Guide

Parameter pickerType

Default Value search

Possible Values search/picker

Req? No

Description 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. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccessController you can pass on comma (,) separated list of the class names. This parameter is used to exclude sub types from the search.

pickerTextB oxLength searchResult sViewId customAcces sController

25 (blank)

Any numeric value Any valid view id

No No

(blank)

Any valid name

No

excludeSubT ypes

(blank)

Any valid subtypes

No

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" />

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*)" />

Incorporating Pickers in JSP Clients

16-29

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; } }

16-30

Windchill Customizers Guide

Configuring an Organization Picker


Objective
You want to pick organization(s) based on certain search criteria.

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 Find Button along with the specified label after using the tags for organization picker. After clicking Find button, user picker will be launched.

Incorporating Pickers in JSP Clients

16-31

On clicking Find button you should organization picker as:

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 RBINFO file customizations. Windchill xconfmanager concepts.

16-32

Windchill Customizers Guide

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: <WT_HOME>\codebase\ pickerAttributes.xml

searchClientResource.rbInfo

RBINFO file

You should use this file to localize the contents of the pickers. Runtime location: <WT_HOME>\src\com\ptc\ windchill\enterprise\search\ client\ searchClientResource.rbInfo

organizationPicker.tag

Custom JSP tag file

This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\ WEB-INF\tags\userPicker.tag

custom.js

JavaScript file

You should specify custom pickerCallback function for picker in this file. Runtime location:
<WT_HOME>\codebase\ netmarkets\jsp\search\ custom.js

Procedure Including a Organization Picker in a jsp page


Configure basic organization picker:
<tr> <wctags:organizationPicker id="organizationPickerId" /> </tr>

Incorporating Pickers in JSP Clients

16-33

Customization Points

Parameter id

Default Value

Possible Values Anything thats unique in a page

Req? Yes

Description An ID is associated with every picker in 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 determines the attributes that should appear in search criteria panel of the given picker.

componentId

pickerSear ch

Any valid component id specified in pickerAttributes. xml Name of the callback function

No

pickerCallback

Generated at the runtime if user has not specified this parameter (blank) (blank) <WebApp >/netmark ets/jsp/sear ch/picked Data.jsp. Organizati on Picker Name

No

Name of the customized callback function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file

defaultValue defaultHiddenValu e pickedDataFetcher

Any values Any values URL location of the fetcher file

No No No

Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results.

label displayAttribute

Any value Any attribute

No No

Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the organization picker Value of the containerRef in which a user wants to restrict the search.

containerRef

(blank)

Any container

No

16-34

Windchill Customizers Guide

Parameter baseWhereClause

Default Value (blank)

Possible Values Any valid I*E where clause query

Req? No

Description Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. The title of picker. This attribute defines whether you want to have Findbutton along with the textbox or not. This attribute defines whether the picker text box should be editable or not. You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a commaseparated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. 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. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccessController you can pass on comma (,) separated list of the class names.

pickerTitle editable

Organizati on true

Any value true/false

No No

readOnlyPickerTe xtBox inline

false false

true/false true/false

No No

pickedAttributes

yesname

Any comma separated list of valid attributes search/picker

No

pickerType

search

No

pickerTextBoxLen gth searchResultsView Id customAccessCont roller

25 (blank)

Any numeric value Any valid view id

No No

(blank)

Any valid name

No

Incorporating Pickers in JSP Clients

16-35

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; updateDisplayField.value=displayAttr; } }

16-36

Windchill Customizers Guide

Configuring a Type Picker


The Type Picker common component is used for the display or assignment of the item type upon creation, copying (save-as), registration, revision, searching, or viewing information of type-able items. The component is available in three formats i.e. as a drop down, as a table and as a tree, either of which can be used depending on the need of application.It can be used in both single-item and multiitem user interface designs. The display or assignment of the type adheres to the defined hard-type items the soft-type items the application context and the access control policies of the system

The application developer can control following features of the picker Picker Default values population Picker Action Definition Selected elements population on Target element

How to Use Type Picker


Type Picker can be created by using the custom tag provided for the component. The parameters that drive the behavior and content of the picker can be passed either via attributes or by use of necessary sub-tags. It consists of Picker Label, Picker Action and the Target element.

Drop Down Format


In the drop down format of type picker the picker label and the target element are displayed. The Go button is optional. If you want the Go button you have to configure it and define its behavior as per your application needs. You can select one or more values as per the select parameter value configured for the picker. Following example creates a type picker component by using the type picker tag.

Incorporating Pickers in JSP Clients

16-37

Example:

<p:typePicker id="document_type_picker" label="Type : " mode="SEARCH"> <p:pickerParam name="select" value="single" /> <p:pickerParam name="format" value="dropdown" /> <p:pickerParam name="defaultType" value="All Types" /> <p:pickerParam name="type" value="BOTH" /> <p:pickerParam name="displayHierarchy" value="false" /> <p:pickerParam name="showRoot" value="true" /> </p:typePicker>

In the above example a simple drop down type picker is defined with. Attributes: Id - This is required attribute used to distinguish between multiple TypePickers Label - Picker Label Mode Defines the mode in which the picker can be used. Default is SEARCH.

There are other optional attributes for this picker which are listed at the end of this section. Parameters: Select It has two possible values single and multi. Default is single.

16-38

Windchill Customizers Guide

defaultType Specifies the default value to be displayed. It accepts valid logical or external representation of Windchill Type Identifiers. It supports multiple values for multi select pickers and a single value for single select pickers. Type Possible values are ROOT_TYPES - only seeded types SOFT_TYPES - only soft types BOTH - Modeled and soft types (default value)

displayHierarchy It displays the picker elements in hierarchy. It is valid only for drop down format. It is false by default. showRoot - Accepts String representation of Boolean value. Shows the seedTypes as I level elements.</font></font>

There are other optional parameters for this picker which are listed at the end of this section.

Tree Format
In the tree format implementation the Picker Label, the Target element and find button are displayed. On the find button click event a popup window pops up with Windchill Type Identifiers displayed in tree format. If one or more types are selected and ok button is hit the selected value(s) are populated in to target element. If any type identifiers are present in the target element and user hits the find button then the type identifiers in the target element appear as pre-selected values in the tree, provided that the types are valid logical or external representation of Windchill Type Identifiers. If cancel button is hit in the popup

Incorporating Pickers in JSP Clients

16-39

window no selection is done from the popup window and the target element contents remain unchanged.

Example:
<p:typePicker id="document_typePicker" label="Type : "> <p:pickerParam name="format" value="tree" /> <p:pickerParam name="defaultType" value="wt.doc.WTDocument| com.ptc.www.Agenda" /> <p:pickerParam name="defaultType" value="wt.doc.WTDocument| com.ptc.www.Plan" /> <p:pickerParam name="defaultType" value="WCTYPE| wt.pdmlink.PDMLinkProduct|Sub Product3" /> <p:pickerParam name="seedType" value="wt.doc.WTDocument" /> <p:pickerParam name="type" value="BOTH" /> <p:pickerParam name="showRoot" value="true" /> <p:pickerParam name="appOption" value="Mera Type$WCTYPE| wt.pdmlink.PDMLinkProduct|Sub Product3" /> </p:typePicker>

16-40

Windchill Customizers Guide

Table Format
In the table format of type picker the type identifiers are displayed in tabular format. The working of the Picker Label, the Target element and find button is same as in the case of Tree format except that, on the find button click event a popup window pops up with Windchill Type Identifiers displayed in tabular format. User can select one or more values and hit OK / Cancel button. Example:<p:typePicker id=" document_typePicker" label="Type : " > <p:pickerParam name="defaultType" value="wt.doc.WTDocument" /> <p:pickerParam name="seedType" value="wt.doc.WTDocument" /> <p:pickerParam name="format" value="table" /> <p:pickerParam name="type" value="BOTH" /> <p:pickerParam name="showRoot" value="true" /> </p:typePicker>

Overview

The TypePicker is defined with the help of TypePicker Tag. The attribute and parameter values supplied are used to populate an object of type TypeBean. This bean is used to carry the user-supplied information across. The different phases involved in a TypePicker component are as follows.

Incorporating Pickers in JSP Clients

16-41

Processing the TypePicker Tag


Draw the Label if supplied Create the Target Element if not provided Populate the Target Element and Draws it If the format is table/tree: Creates the Picker Action and draws If pickerCallBack is not provided, puts the default function.

Picker Action button hit


Pops up the TypePicker.jsp that contains Wizard having Ok/Cancel buttons Wizards first step is typePicker_step.jsp Depending on whether its a tree or table, it includes either typePicker_tree.jspf or typePicker_table.jspf The jspf has got appropriate component defined in it to draw the picker as configured.

Ok Wizard action
If no element is selected, a JavaScript warning is displayed and the pop-up stays.</font></font> If some element is selected then it makes an Ajax call to the jsp specified via the pickerDataFetcher. The jsp will fetch all the selected elements that need to be populated in the target element. Calls pickerCallBack available in the calling jsp Update Target Element Close the pop-up

Cancel Wizard action


Close the pop-up

16-42

Windchill Customizers Guide

Customization Points
You can customize following areas of type picker. Target element Definition Picker Default values population Picker Action Definition Selected elements population on Target element Picker Element Content population

Target Element Definition


You can provide the target element using the field attribute. The values that the target element can have are text field, drop down and list box. If you do not specify the target element it will be created by the component. You can also provide the rendering context using the renderContext attribute.

Picker Default values population


You can define the values that can be populated as pre-selected values at the time of configuring the TypePicker. Multiple values can be passed to the parameter pickerDefaultTypes. The type specified should be valid logical or external representation of Windchill Type Identifiers. For single select only one type should be provided. For multiple select multiple values can be provided.

Picker Action Definition


The picker action can be specified by using the Go / Find button. If the picker type is dropdown list then the Go/Find button is optional and user has to define the behavior if he wants. In case of table / tree format the picker action can be specified using the object Type& actionNameparameters. The picker action is specified in the object type in actions.xml. The action name is the name of the action in actions.xml. The Picker actions are not available for mode=VIEW / EDIT.

Selected elements population on Target element


Depending on the choice of select value (single/multiple) and the picker format the target element is decided.
Select Format Drop Down List Tree Table

Single Multi

No Target element Not supported

Text Box List Box

Text Box List Box

Incorporating Pickers in JSP Clients

16-43

You can provide your own pickerCallBack function with following conditions The function signature should be user_call_back_function(JSON_Object, TypePicker_Id, TargetElement_Id). The function should be available where type picker component is inserted.

You can provide your own pickerDataFetcher function with following conditions It is to be a jsp file located in the <Windchill>/codebase and relative path is to be provided. It is not applicable for drop down.

Picker Element Content population


You can specify one or more seed Types to the type picker using the parameter pickerSeedTypes. If seed types are not provided it will throw an Exception. For mode=SEARCH exception is not thrown. For search mode the root types are defined in WT_HOME\codebase\com\ptc\windchill\enterprise\search\server\ SearchableTypes.properties file. So if no seed types are specified, the types will be populated from SearchableTypes.properties file.

Attributes and Parameters supported by Type Picker


The Following table describes all the supported attributes of a Type Picker Common Component
Attribute Example Description

id label mode

id="tp" label ="Type :" mode=SEARCH

A required value. Used to distinguish between the multiple Type-Picker usages in a page Picker Label Defines in which mode the Type-Picker is going to be used. It should be one of the value defined in com.ptc.core.ui.resources.ComponentMode. Default value is SEARCH Target Element into which the picked element attribute will be populated. It should be a subclass of com.ptc.core.components.rendering.AbstractG uiComponent. Currently support TextBox and ComboBox. If not supplied the component will create a Target Element for the user

field

field ="${target_element}"

16-44

Windchill Customizers Guide

Attribute

Example

Description

renderContext

renderContext ="${rcontext}"

Object should be an instance of com.ptc.core.components.rendering.Rendering Context. If not supplied the component will create one for the user This is the objecttype in which the picker action is specified in *actions.xml (<Windchill>\ codebase\config\actions\EnterpriseUIactions.xml) This is the action name that is specified in *actions.xml for the picker action

objectType

objectType =" typepicker"

actionName

actionName =" typePicker"

The Following table describes all the supported parameters of a Type Picker Common Component.
Parameter Example Description

adminDomainRef

value ="${adref}"value =" wt.admin.AdministrativeDomain :7" value ="${container_Ref}"

String representation of the administrative domain reference (wt.admin.AdminDomainRef). Used to check access control rights. String representation of the container reference (wt.inf.container.WTContainerRef). Used to populate types specified for this container String representation of State. (wt.lifecycle.State). Used while checking access control rights Accepts valid logical or external representation of Windchill Type Identifiers Multiple values supported. Required for mode = CREATE/EDIT/VIEW 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

containerRef

lifeCycleState

value ="RELEASED"

seedType

value = wt.part.WTPart

filterType

value ="coolPart"

Incorporating Pickers in JSP Clients

16-45

Parameter

Example

Description

defaultType

value = wt.part.WTPart

For single select, it should be only one value. Accepts valid logical or external representation of Windchill Type Identifiers. Multiple values supported. It can support blank, "Select a Type" etc values also Localized Display name and value separated by a $ delimiter. Multiple values supported. It should be one of the enum constant value defined in com.ptc.windchill.enterprise.picker.type.s erver.TypePickerFormat. Possible values are dropdown, table, tree. Default value is dropdown Possible values are single and multi, the former being the default. It should be one of the enum constant value defined in com.ptc.windchill.enterprise.picker.type.s erver.TypePickerTypes. 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) Default value is BOTH Accepts String representation of Boolean value. Valid only for dropdown format. Presents picker elements in hierarchy. Default value is false Accepts String representation of Boolean value. If true - only instantiables will be displayed. If false both instantiables and non-instantiables will be displayed. Default value is false Accepts String representation of Boolean value. Shows the seedTypes as I level elements

appOption

value ="All Types$wt.fc.Persistable" value ="dropdown"

format

select type

value ="single" value ="BOTH"

displayHierarchy

value=true

showInstantiable

value=false

showRoot

value=true

16-46

Windchill Customizers Guide

Parameter

Example

Description

componentId

value=

ComponentId is defined as 'APP_ID+. +COMPONENT_NAME' . Valid APP_IDs are ProjectLink, Foundation, or PDMLink. Used for mode = "SEARCH" to find the I level types from <Windchill>\ codebase\com\ptc\windchill\enterprise\ search\server\SearchableTypes.properties. Passing null will default to Foundation.allSearch (Default)

Source code location Tag Definition


\ClientArchitecture\CommonComponents\src_web\WEB-INF\tlds\picker.tld \wcEnterprise\EnterpriseUI\src_web\com\ptc\windchill\enterprise\tags\ picker\TypePickerTag.java

Picker Action, Wizard Step Definition


\wcEnterprise\EnterpriseUI\src_web\config\actions\EnterpriseUI-actions.xml

Type Picker Service Entry


\wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\enterpriseuiservice.properties.xconf

Java & Model Files


\wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ type.cat \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ type.mData \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ typePickerResource.rbInfo \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ commands\commands.mData \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ commands\type.commands.cat \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ commands\TypePickerCommands.java

Incorporating Pickers in JSP Clients

16-47

\wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ dataUtilities\type.dataUtilities.cat \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ dataUtilities\TypePickerNmObjectUtility.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ dataUtilities\TypePickerTreeHandler.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\server.mData \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\type.server.cat \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\StandardTypePickerService.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerBean.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerData.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerFormat.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerHelper.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerServiceFwd.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerService.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerTreeModel.java \wcEnterprise\EnterpriseUI\src\com\ptc\windchill\enterprise\picker\type\ server\TypePickerTypes.java

JSP files
\wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker.jsp \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_dataFetcher.jsp \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_doer.jspf \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_includes.jspf

16-48

Windchill Customizers Guide

\wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_table.jspf \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_tree.jspf \wcEnterprise\EnterpriseUI\src_web\netmarkets\jsp\typepicker\ typePicker_step.jsp

Incorporating Pickers in JSP Clients

16-49

Configuring a User Picker


Objective
You want to pick User(s) based on certain search criteria.

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 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 Button along with the specified label after using the tags for user picker. After clicking Find button, user picker will be launched.

16-50

Windchill Customizers Guide

On clicking Find button you should use a user picker as:

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 RBINFO file customizations. Windchill xconfmanager concepts.

Incorporating Pickers in JSP Clients

16-51

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: <WT_HOME>\codebase\ pickerAttributes.xml

searchClientResource.rbInfo

RBINFO file

You should use this file to localize the contents of the pickers. Runtime location: <WT_HOME>\src\com\ptc\ windchill\enterprise\search\ client\ searchClientResource.rbInfo

userPicker.tag

Custom JSP tag file

This file is contains the information about the supported parameters for this tag. Runtime location:
<WT_HOME>\codebase\WEBINF\tags\userPicker.tag

custom.js

JavaScript file

You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\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>

16-52

Windchill Customizers Guide

Customization Points

Parameter id

Default Value

Possible values Anything thats unique in a page

Req? Yes

Description An ID is associated with every picker in 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 determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the user picker Value of the containerRef in which a user wants to restrict the search.

componentId

pickerSearch

Any valid component id specified in pickerAttribut es.xml Name of the callback function

No

pickerCallback

Generated at the runtime if user has not specified this param

No

defaultValue defaultHiddenValue

(blank) (blank)

Any values Any values

No No

pickedDataFetcher

<WebApp>/netmar kets/jsp/search/pick edData.jsp. User Picker fullName

URL location of the fetcher file Any value Any attribute

No

label displayAttribute

No No

containerRef

(blank)

Any container

No

Incorporating Pickers in JSP Clients

16-53

Parameter baseWhereClause

Default Value (blank)

Possible values Any valid I*E where clause query

Req? No

Description Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. The title of picker. This attribute defines whether you want to have Findbutton along with the textbox or not. This attribute defines whether the picker text box should be editable or not. You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a comma-separated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. 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. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table.

pickerTitle editable

User true

Any value true/false

No No

readOnlyPickerTextB ox inline

false

true/false

No

false

true/false

No

pickedAttributes

fullName

Any comma separated list of valid attributes

No

pickerType

search

search/picker

No

pickerTextBoxLength searchResultsViewId

25 (blank)

Any numeric value Any valid view id

No No

16-54

Windchill Customizers Guide

Parameter customAccessControll er

Default Value (blank)

Possible values Any valid name

Req? No

Description This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccessController you can pass on comma (,) separated list of the class names. This parameter is used to restrict the user search to active/deleted/active and deleted users only. 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.

showUserType

ActiveOnly

ActiveOnly DeletedOnly ActiveAndDel ete

No

showRoles

false

true/false

No

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" />

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 fullName is the displayAttribute requested

Incorporating Pickers in JSP Clients

16-55

var displayAttr = eval("myJSONObjects[i].fullName"); updateHiddenField.value=oid; updateDisplayField.value=displayAttr; } }

16-56

Windchill Customizers Guide

Configuring a Participant Picker


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.

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 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.

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.

Incorporating Pickers in JSP Clients

16-57

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. Name of the action method that needs to be invoked for processing the selected Participants. This can take values "single" / "multi". When this is set to "single", one can select only one Participant at a time. Default is "multi". If this attribute is not passed or set to "multi", Picker will enable to select multiple Participants. Use this to set the default to any Participant type. The class com.ptc.core.components.bean s. PrincipalBean has four string constants defined, which one can be pass to this attribute. The constants are ALL_PARTICIPANT, USER, GROUP and ORG.

actionMethod

Tag Attribute

select

Tag Attribute

participantType

Tag Attribute

16-58

Windchill Customizers Guide

Element

Type

Description

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 specified as in the attribute participantType. When set to false or left unspecified, the picker supports participant types ALL_PARTICIPANT, USER, GROUP, ORG. 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. The association you desire to be pre selected in the dropdown should be passed in this attribute. The localized string for Display Label of the association. Set this to "true" to get email Textbox rendered. You can type any comma or space separated emails that you desire to invite.

associationMap

Tag Attribute

defaultAssociation

Tag Attribute

associationLabel emailAllowed

Tag Attribute Tag Attribute

Incorporating Pickers in JSP Clients

16-59

Element

Type

Description

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. The context you desire to be pre selected in the dropdown should be passed in this 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.

defaultContext

Tag Attribute

serviceMap

Tag Attribute

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 the Sample Code section 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.

16-60

Windchill Customizers Guide

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 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".

Customization Points

Parameter select

Default Value multi

Possible Values "single" / "multi"

Req? No

Description There is a need to have the picker return only a single Principal, thus, the Apply button does not appear. Not all clients will allow an email string to be returned from the picker, some clients will only allow Principal objects to be returned.

emailAllowed

false

true/ false

No

Incorporating Pickers in JSP Clients

16-61

Parameter associationMap defaultAssociation

Default Value Empty Empty

Possible Values See Solution Elements on page 16-58

Req? No No

Description Some clients want users to be able to assign Principals to create an assignment when selecting principals (such as role assignment, task assignment, etc.) If an assignment is desired along with the principal choice, there is a need to show this list. The client must be able to specify the label name, dropdown list choices, and default value for the dropdown. Not all clients that will use the picker will need the same set of Principal types. Some clients may only except certain types to be returned from the picker In Administrative clients its necessary to be able to select a specific context and have the Principals returned from that context, and from its parent contexts (i.e. the organization and site that contain the specified container) If there is only a single Search In context, the value should be displayed as read-only text (no dropdown).

associationLabel Empty No

singleParticipantT ype

Empty

true/ false

No

contextMap defaultContext

Empty Empty

See Solution Elements on page 16-58

No No

serviceMap

Empty

See Solution Elements on page 16-58

No

A specific parameter will have to be set by the application using the picker to specify that this attribute should be shown. This attribute is used to pick a specific LDAP to find Principals in. This attribute is primarily used by/in Administrative user interfaces where the end user knows which LDAP server they are interested in searching against. Label should be Service: when this is displayed.

16-62

Windchill Customizers 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 ).
<%@ 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.NmPrincipalCommands2" actionMethod="addPrincipal" participantType="<%= PrincipalBean.GROUP %>" </jca:participantPicker>

This will render a basic participant picker as show below.

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.

Incorporating Pickers in JSP Clients

16-63

public class NmPrincipalCommands2 implements Externalizable { public static ArrayList addPrincipal( NmCommandBean cb ) throws WTException { ArrayList list = new ArrayList(); String users = cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS); if (users != null) { int start = 0; int pos = users.indexOf("#", start); while (pos != -1) { String user = users.substring(start, pos); list.add(user); start = pos+1; pos = users.indexOf("#", start); } } } }

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).

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. Keys 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.NmPrincipalCommands2"

16-64

Windchill Customizers Guide

actionMethod="addPrincipal" participantType="${participantType}" defaultAssociation="GUEST" associationMap="${associationMap}" associationLabel="Add to Role" > </jca:participantPicker>

The above code will render association dropdown as shown in the following figure.

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 NmPrincipalCommands2 implements Externalizable { public static ArrayList addPrincipal( NmCommandBean cb ) throws WTException { ArrayList list = new ArrayList(); String users = cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS); if (users != null) { int start = 0; int pos = users.indexOf("#", start); while (pos != -1) { String user = users.substring(start, pos); list.add(user); start = pos+1; pos = users.indexOf("#", start); } String role = cb.getTextParameter(PrincipalBean.PARAM_ASSOCIATION); ArrayList result = NmRoleHelper.service.addUsersToRole(cb, role, list); } return result; } }

You can extract the selected association from text parameter as highlighted in the above code.

Adding Email subscription


The tag to get email subscription the code will look like this.
<jca:participantPicker actionClass="com.ptc.netmarkets.principal.NmPrincipalCommands2"

Incorporating Pickers in JSP Clients

16-65

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.

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>

16-66

Windchill Customizers Guide

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


\Windchill\codebase\netmarkets\jsp\roleAccess\ profile_addMembers.jsp \Windchill\codebase\netmarkets\jsp\subscription\ subscrPrincipalPicker.jsp \Windchill\codebase\netmarkets\jsp\team\ addUsersToRole.jsp \Windchill\codebase\netmarkets\jsp\object\ findParticipant.jsp

Incorporating Pickers in JSP Clients

16-67

16-68

Windchill Customizers Guide

17
JSP Customization Scenarios
This chapter details various customization scenarios. Topic Page

Configuring a Picker to Offer Only Specific Soft Types Based on User-specified Criteria including Restricted Life Cycle States.................................................17-2 Building a Picker that Enables Users to Select Projects from an External Project DB .....................................................................................................................17-8 Pickers from table toolbar ...............................................................................17-13 Generating HTML Tags for ProductView Visualization Within a JSP Page .17-16

17-1

Configuring a Picker to Offer Only Specific Soft Types Based on User-specified Criteria including Restricted Life Cycle States
Objective
Configure a picker to only display a specific soft-type of parts (Datecode Release). Allow user to enter criteria which includes name, library and lifecycle state. The states shown to the user must only be ones that represent a state that the objects can have, not all LC states in the system. The user to be able to pick a value for the attribute "Release Stream" (Windchill 8.0, 9.0, etc). The picker should show the datecode name, not show its number, and also include the library that contains the part. The picker will be used in the process to create Affected Data relationships for a Change Request. Associated requirements:
Background

Invoking a picker with customized seeded criteria. Customizing the columns of a table

Problem scenario represents common customization scenario for Item Picker. Picker is common UI component used for searching for referenced objects and selecting one or more of them on calling application. You can customize criteria attributes and result table columns shown in picker. You can configure Item Picker to search for single or multiple object types. You can restrict search to only in particular container or container types.
Scope/Applicability/Assumptions

Item Picker can be launched from any JSP page using ItemPicker tag. Picker returns picked objects as a Jason object by calling JavaScript function on calling page. It is the responsibility of calling page to further act on this Jason object. Soft type of Part is Date code so its fully qualified external form would be like WCTYPE|wt.part.WTPart|org.r_and_d.DatecodeRelese

Intended Outcome

Datecode Release picker with Name, context and State as criteria attributes:

17-2

Windchill Customizers Guide

Solution
A custom JSP tag with appropriate parameters would be used to launch customized Item Picker. To choose the Library, Library Picker would be used.
Prerequisite knowledge

To achieve this objective, you need to have an understanding of the following:


Solution Elements

Using JSP tags Using xconfManager Updating XML document. Using rbInfo files

Element PickerAttributes.xml SearchableTypes.propertis .xconf

Type Xml Xconf properties file

Description Location: <Windchill>\ codebase Location: <Windchill>\ codebase\ com\ptc\windchill\ enterprise\ search\server\ SearchableTypes.properties.xc onf

JSP Customization Scenarios

17-3

Element

Type JavaScript file

Description Add your callback function in this file. Location: <Windchill>\ codebase\ WEB-INF\tags\ itemPicker.tag

itemPicker.tag

JSP tag

To choose Library, Library Picker is shown.


Procedure Launch Item Picker with custom criteria and result table to pick DateCodeRelease objects Using Item Picker Tag

To show Item Picker you can use ItemPicker tag as shown below:
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %> <tr> <%-launching Item picker--%>

<wctags:itemPicker id="myItemPicker" label="Custom Item Picker" pickerTitle="Datecode Release" showVersion="false" objectType=" WCTYPE|wt.part.WTPart|org.r_and_d.myPart " showTypePicker="false" componentId="test.Customization" typeComponentId="Foundation.customization" searchResultsViewId="wt.part.WTPart.customizedSearchView"/> </tr> .

The important parameter are described below: ObjectType Fully qualified external form name of the object. ComponentId componentId to be used for configuring criteria attributes. See section below for details TypeComponentId - used for defining set of types and container types to be searched for. In our case this parameter is used to constraint our search only within Library containers.

Defining ComponentId for configuring criteria attributes

This section describes, adding new componentId.


<wctags:itemPicker id="myItemPicker" label="Custom Item Picker" pickerTitle=" Datecode Release" showVersion="false" objectType="WCTYPE|wt.part.WTPart|org.r_and_d.myPart " showTypePicker="false" componentId="test.Customization" typeComponentId="Foundation.customization" searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

17-4

Windchill Customizers Guide

ComponentId is resolved from pickerAttributes.xml file to pick up the list of attributes to be shown in picker criteria. Update pickerAttributes.xml as below:
<PickerAttributes> <ComponentID id="test.Customization"> <ObjectType id="WCTYPE|wt.part.WTPart| org.r_and_d.myPart"> <SearchCriteriaAttributes> <Attributes> <Name>name</Name> <DisplayName>NAME_LABEL</DisplayName> <IsSearchable>true</IsSearchable> </Attributes> <Attributes> <Name>containerRef</Name> <DisplayName>CONTEXT_LABEL</DisplayName> <IsSearchable>false</IsSearchable> </Attributes> <Attributes> <Name>state.state</Name> <DisplayName>STATE_LABEL</DisplayName> <IsSearchable>true</IsSearchable> </Attributes> </SearchCriteriaAttributes> </ObjectType> </ComponentID> </PickerAttributes>

Here we have defined search criteria attributes as name, context and state. DisplayName is resolved from rbInfo file : com\ptc\windchill\enterprise\search\ client\searchClientResource.rbInfo
Defining typeComponentId for constraining search to given container types

As per problem statement, we need to search only with in Library containers. This is achieved by passing typeComponentId. To configure typeComponentId add below property to <Windchill>\codebase\com\ptc\windchill\enterprise\search\ server\SearchableTypes.properties.xconf

JSP Customization Scenarios

17-5

<Property name="Foundation.customization.containerType.0" default="wt.inf.library.WTLibrary"/>

And run xconfManager to propagate.


Customizing the search result table view

Search result tables use the Windchill R9.0 table common component and hence the column display can be configured by creating a new table view. Please refer [Crating Table View] for details regarding creating and configuring a new view. Then we can pass the view as below to the picker tab and search results table would be rendered with this view.
<wctags:itemPicker id="genericPicker" objectType="WCTYPE| wt.part.WTPart|org.r_and_d.mypart" label="Part Picker using generic" containerRef="<%=containerRefs.toString()%>" componentId="scenarioOnePicker" searchResultsViewId="wt.part.WTPart.customizedSearchView" showVersion="false"/>

The view id wt.part.WTPart.customizedSearchView should be configured to lookup the java class associated with this id which would define the table view. Please refer to configuring table views document. An example to configure this in SearchResultTable.properties.xconf file could be
<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>

A new java class com.ptc.netmarkets.search.views.CustomizedPartView should be created which would define the view columns for this picker customization.
Customization Points

Please refer [Item Picker Best Practice] for further customizing Item Picker.
Limitations

As per current implementation, Lifecycle State is not limited only to states that the object can have.
Sample Code
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %> <HTML> <BODY><TABLE> <tr> <%-launching Item picker--%>

17-6

Windchill Customizers Guide

<wctags:itemPicker id="myItemPicker" label="Custom Item Picker" pickerTitle=" Datecode Release" showVersion="false" objectType=" WCTYPE|wt.part.WTPart|org.r_and_d.myPart " showTypePicker="false" componentId="test.Customization" typeComponentId="Foundation.customization" searchResultsViewId="wt.part.WTPart.customizedSearchView"/> </tr> </BODY></TABLE> </HTML>

JSP Customization Scenarios

17-7

Building a Picker that Enables Users to Select Projects from an External Project DB
To configure a picker to fetch ProjDB data, by accepting criteria for name / id. Background

Configure a picker to talk to a non-Windchill database to fetch and display data. A user should be able to search the ProjDB database from Windchill to search for projects. Its only expected to get back the Project Id, Name and Title OR Short Description
Scope/Applicability/Assumptions

Since we are dealing with non-Windchill objects here, there are a number of points that we need to take care of while implementation. First thing is an assumption that user will be able to write a task or a webject which will fetch data from a non-Windchill database and yet return an IE Group. The framework requires an IE Group to render results. Since the records returned are not Windchill objects, the user will have to build a few attributes which are not exactly related to the data like NmOid. A user would have a JSP client from which to launch this picker


Intended Outcome

You should see a text box and Find Button along with the specified label after using the tags for user picker.

Since we need an object type for launching a generic picker as a required attribute we would be using wt.fc.Persistable. However this doesnt interfere with the working of the picker. Its just given to launch a generic picker.

17-8

Windchill Customizers Guide

a) On Click of the Find button the picker will get launched in a new window as shown in the screen shot below.

Solution
Use the ProjDb Picker Common Component in your JSP file to include ProjDB Picker in your application.
Prerequisite knowledge

To achieve this objective, you need to have a thorough understanding of the following: Basic development involving HTML forms, JSP, XML. Knowledge of writing a task and a webject to get data from a non-Windchill database Picker common components Table common component View creation Knowledge of Customizing the view to display and use data correctly from non-Windchill objects Knowledge of writing a data utility to fetch NmOid object

JSP Customization Scenarios

17-9

Solution Elements Element PickerAttributes.xml Type XML Description Runtime location - \codebase\ pickerAttributes.xml This file is used to customize the search criteria at picker page. SearchResultsTable.properties.xc onf Xconf Runtime location - \codebase\com\ ptc\netmarkets\search\ SearchResultsTable.properties.xconf This file can be used to configure table view definition. Procedure Launching and configuring a Generic Picker for searching non-Windchill data like ProjDB Projects Launching a picker with a single search criteria

A generic picker can be launched from any JSP page using the following tag. Here we are launching a picker for ProjDB data
<wctags:genericPicker id="projDBPicker" objectType="wt.fc.Persistable" componentId="projDBPickerId" pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche r.jsp" displayAttribute="projId" label="ProjDB Picker using generic" pickerTitle="ProjDB" searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/>

These attributes to the tag contain configuration information like, which view is configured for this picker search result table, what is the data fetcher jsp to be called etc.
Customizing the picker search criteria

The search criteria for a picker can be customized by defining the attributes in PickerAttributes.xml file. This can be done by creating a new component id and then defining the search criteria as below. For our ProjDb Picker, we can configure the ProjectId or Name here, as search criteria
<ComponentID id="projDBPickerId"> <ObjectType id="wt.fc.Persistable"> <SearchCriteriaAttributes> <Attributes> <Name>projId</Name> <DisplayName>Project ID</DisplayName> <IsSearchable>true</IsSearchable> </Attributes>

17-10

Windchill Customizers Guide

</SearchCriteriaAttributes> </ObjectType> </ComponentID>

Configuring the customized view for results table

Search result tables use the Windchill R9.0 table common component and hence the column display can be configured by creating a new table view. Please refer Creating Table View Documentation for details of how to create and configure a new view. You can then pass the view as shown here to the picker tab to render search results table with this view.
<wctags:genericPicker id="projDBPicker" objectType="wt.fc.Persistable" componentId="projDBPickerId" pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche r.jsp" displayAttribute="projId" label="ProjDB Picker using generic" pickerTitle="ProjDB" searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/>

The view id wt.fc.Persistable.defaultPickerSearchView should be configured in SearchResultTable.properties.xconf file to lookup the java class associated with this ID. Example:
<Service context="default" name="com.ptc.core.htmlcomp.tableview.ConfigurableTable"> <Option serviceClass="com.ptc.netmarkets.search.views.ProjDbPickerResultTa bleView" requestor="java.lang.Object" selector="wt.fc.Persistable.defaultPickerSearchView"/> </Service>

A new java class com.ptc.netmarkets.search.views.ProjDbPickerResultTableView should be created which would define the view columns for this picker customization
Writing a data utility to get NmOid column in the results table to display a check box for selection

Since we are dealing with non-Windchill objects here, we need to populate this NmOid column by writing a special data utility. This data utility will have to be configured in the components.datautilities.properties file, for the specified searchResultsViewId as follows
<!ProjDB Picker Results Table --> <Option serviceClass=" com.ptc.netmarkets.search.utils.ProjDbPickerNmObjectDataUtility " requestor="java.lang.Object" selector=" wt.fc.Persistable.defaultPickerSearchView" //This value corresponds to the searchResultsTableViewId in the picker tag. cardinality=" duplicate "/>

JSP Customization Scenarios

17-11

Writing a data fetcher for displaying the selected value in the calling text box

You can configure a specific picked data fetcher for getting more information about the data displayed. In this file, from the selected OID, one needs to construct a string to be passed to the Json Object, used in Picker Callback function. A user gets a comma separated string from the request parameter attributes as follows projId,oid. Here the projId, is the display attribute configured in the picker tag. A user can passed multiple attribute names, and Click of OK button on the picker would return these in the request object, in the dataFetcher.jsp. The picker will also return the selected Oids, as a comma separated string, if multiselect is true, or as a single oid value if the picker is single select. The final string that needs to be constructed for the JSON object is as follows {"pickedObject": [{"oid":"MyTestOidFOrProjDB","<displayAttributeName>":"<selctedoid>"}]}

Sample Code
Launching Picker from any JSP
<html> <body> <table> <tr> This is a ProjDB picker. </tr> <tr> <%-launching Proj DB Picker --%> <wctags:genericPicker id="projDBPicker" objectType="wt.fc.Persistable" componentId="projDBPickerId" pickedDataFetcher="/Windchill/netmarkets/jsp/search/projDataFetche r.jsp" displayAttribute="projId" label="ProjDB Picker using generic" pickerTitle="ProjDB" searchResultsViewId="wt.fc.Persistable.defaultPickerSearchView"/> </tr> </table> </body> </html>

17-12

Windchill Customizers Guide

Pickers from table toolbar


Objective
You want to a picker from table toolbar actions.

Background
The pickers from table toolbar are used when you have a requirement to launch pickers from some table level action and accordingly populate the tables or do some processing based on the results.

Scope/Applicability/Assumptions
Say you want to launch <your picker> from your table. It is assumed that your action jsp file <MyPage>.jsp file in which you are putting picker tag includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files.

Intended Outcome
On click of the action, you should see the corresponding picker getting launched.

Solution
Use the specific picker Common Component in your JSP file to include the 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 RBINFO files customization. Windchill xconfmanager concepts.

JSP Customization Scenarios

17-13

Solution Elements
Element pickerAttributes.xml Type XML file Description You should use this file to customize the search criteria attributes for an object type for your picker. Runtime location: <WT_HOME>\codebase\ pickerAttributes.xml searchClientResource.rbInf o RBINFO file You should use this file to localize the contents of the pickers. Runtime location: <WT_HOME>\src\com\ptc\ windchill\enterprise\search\ client\ searchClientResource.rbInfo <your picker>.tag Custom JSP tag file This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\ WEBINF\tags\<your picker>.tag custom.js JavaScript file You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\codebase\ netmarkets\jsp\search\ custom.js

Procedure Including a <your picker> in a jsp page


Configure basic picker:
<tr> <wctags:<your picker name> id="myPickerId" inline=true pickedAttributes=<name of the attribute> pickerCallback=<your pickerCallback function> /> </tr>

Customization Points
Please refer to the <specific picker> Best Practice document for details regarding the parameters.

17-14

Windchill Customizers Guide

For pickers that are launched from table toolbar they should have at least following parameters in the tags.
inline=true pickedAttributes=<comma separated list of attribute names to be fetched> pickerCallback=<name of pickerCallback function> multiSelect=true

JSP Customization Scenarios

17-15

Generating HTML Tags for ProductView Visualization Within a JSP Page


To generate HTML code for the ProductView visualization components in a JSP page, use the com.ptc.wvs.common.ui.VisualizationHelper class. See this class entry in your installed Windchill Javadoc for more information. General flow of logic: The VisualizationHelper can be instantiated via the newVisualizationHelper() factory method. getCreateDialogWindow() is required to generate the Javascript fragment required by the results returned from getDefaultVisualizationData(String, Boolean, Locale). This code must be embedded somewhere in the HTML returned by the JSP page. getDefaultVisualizationData(String, Boolean, Locale) method returns an array of String values. Each value corresponds to a different component within the ProductView Visualization Service. Elements in the array can be accessed directly through the indexes returned by the following methods: getIndexOfVisLink(String, String), clipboardLinkIndex(), printLinkIndex(), viewRepsLinkIndex(). Each String is the base HTML code for the ProductView visualization component and can be embedded into the HTML returned by the JSP page. It may be an '<A HREF .. /A>' code tag or other simple unformated HTML tags. Note: The getDefaultVisualizationData(String, Boolean, Locale) method returns the basic HTML components necessary for accessing the ProductView visualization components. Most likely the results will need to be used within proper HTML tags. The responsibility of designing the user interface and properly using the values returned by these methods belongs to the implementer. Example usage:
// comp.ptc.wvs.common.ui.VisualizationHelper is assumed to be imported. VisualizationHelper visHelper = newVisualizationHelper(); if (visHelper.isWVSEnabled()) //only execute code if WVS is enabled { // Embed the create dialog JavaScript somewhere in returned HTML. // The below is just an example of calling it. Placement within // HTML is the responsibility of the implementer. out.println(visHelper.getCreateDialogWindow()); //ObjectReference object or and locale object is assumed to be obtained prior to the following line String visData[] = visHelper.getDefaultVisualizationData(or.toString(),new Boolean(false), locale); //Obtain array indices for thumbnail, clipboard link, print link, and representations link int thumbnailIndex = visHelper.getIndexOfVisLink( VisualizationHelper.THUMBNAILS_PROP_PAGE_PREF_KEY, VisualizationHelper.DEFAULT_THUMBNAILS_PROP_PAGE_PREF_VALUE);

17-16

Windchill Customizers Guide

int clipboardIndex = visHelper.clipboardLinkIndex(); int printIndex = visHelper.printLinkIndex(); int repsOrMarkupsIndex = visHelper.viewRepsLinkIndex(); /** * Print the various HTML code fragments generated for each component. * Any HTML formatting code must be wrapped around each of the following lines **/ out.println(visData[thumbnailIndex]); out.println(visData[clipboardIndex]); out.println(visData[printIndex]); out.println(visData[repsOrMarkupsIndex]); }

JSP Customization Scenarios

17-17

17-18

Windchill Customizers Guide

18
Customizing the Product Structure Explorer (PSE)

This chapter describes how to customize the Product Structure Explorer (PSE). Topic Page

Customizing PSE Menus, Toolbars and Popup Menus.....................................18-2 Customizing PSE Table Display .......................................................................18-8 Customizing PSE for Soft Types.....................................................................18-13 Customizing PSE to Handle Modeled Subclasses ..........................................18-24 Customizing PSE Structure Queries................................................................18-31 Customizing Attribute Displays within Section Headings..............................18-35 Customizing Tabs - Configure Existing Tabs with Subtabs ...........................18-43 Allow Additional Steps During New Object Creation....................................18-45 Type Picker Display Customization................................................................18-47 Disabling Actions by Object Type ..................................................................18-49 Creating a Requirements Tab ..........................................................................18-51 Configurable Link Tables................................................................................18-67

18-1

Customizing PSE Menus, Toolbars and Popup Menus


Objective
You want to change the content of a PSE menu, toolbar or popup menu.

Background
The definition of the PSE Menus, Toolbars and popup menus are interconnected. The definition of the user interface actions that appear in the toolbars and popup menus is inherited from the ActionAccess definition of the Menu Bar. The Menu Bar and Menu Items that are displayed do not change based on the mode (edit, draft or annotate) in which PSE is working, though items may become disabled if they are not relevant for the mode. The Toolbar does change based on the mode, as do the popup menus exposed in the tables. Only menu items that have an icon associated can appear in a toolbar. In the Task Tabs of PSE, a number of tables are defined, which have tool bars and popup menus. These are implemented in the exact same way as the main menu bar via ActionAccess definitions, but the menus are not displayed.

Scope/Applicability/Assumptions

Intended Outcome
You may want to change the content of the toolbar for a given mode; for example you may want to add the New Query Icon to the toolbar (before the Help icon) that is displayed in Draft Mode for the main PSE window, and also to add the actions Insert Existing and Insert New to the Uses Tab popup menu:

18-2

Windchill Customizers Guide

Solution
Change the appropriate element in
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure/PDMLinkExplorerMenus.xml

to add the New Query Action to the Toolbar, and


<Windchill>/codebase/config/logicrepository/xml/explorer/struct ureexplorer/ExplorerMenusForUsesTab.xml

to add the popup menu entries to the Uses Tab.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Management of XML file customizations

Solution Elements

Element

Type

Description

PDMLinkExplorerMenus.xml

XML file

Holds the definition of the main PSE Application Menus, toolbars and popup menus that appear in the tree displays. Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/productstructure

ExplorerMenuItems.xml

XML file

Holds Menu Item definitions, referenced from the main application menu (PDMLinkExplorerMenus.xml) and ExplorerMenus.xml Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

ExplorerMenus.xml

XML file

Holds Menu definitions for sub-menus referenced from the main application menu (PDMLinkExplorerMenus.xml) Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

Customizing the Product Structure Explorer (PSE)

18-3

Element

Type

Description

ExplorerMenusForAttributeTa ble.xml

XML file

Holds the definition of the toolbars and popup menus for the Attribute Table on the Information Tab. Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

ExplorerMenusForDocuments Tab.xml

XML file

Holds the definition of the toolbars and popup menus for the tables on the Documents Tab. Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

ExplorerMenusForReplacemen tsTab.xml

XML file

Holds the definition of the toolbars and popup menus for all tables on the Replacements Tab. Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

ExplorerMenusForUsesTab.x ml

XML file

Holds the definition of the toolbars and popup menus for all tables on the Uses Tab. Located in:
<Windchill>/codebase/config/logicreposito ry/xml/explorer/structureexplorer

ActionAccess

XML element

Holds the definition of a MenuBar, related Menus and MenuItems. Each ActionAccess element (i.e., MenuBar definition) must include all the actions that will be used in the related Toolbars and Popup Menus. Note: Adding new actions to the MenuBar definition is not supported. Contained in PDMLinkExplorerMenus.xml and ExplorerMenus*.xml

ModeToolBar

XML element XML element

Defines a toolbar for a specific mode. Specifies the ApplicationMode (via an Import) and a list of MenuItemIdentifiers. Defines a popup menu for a specific mode. Simply specifies the mode and a list of MenuItemIdentifiers.

ModePopupMenu

18-4

Windchill Customizers Guide

Element

Type

Description

ExplorerMode MenuItemIdentifier

XML element XML element

Sub-element of ModeToolBar or ModePopupMenu. Specifies the mode. Sub-element of ModeToolBar or ModePopupMenu. Identifies (through the id parameter) a defined Action.

Procedure Customizing the Toolbar


It is possible to change the content of the Toolbar for a given mode. Adding existing, deleting and re-ordering the items in the definitions are supported. Consider the Toolbar that is displayed in Draft Mode for the main PSE window. For the example of adding the action to create a New Query to the toolbar, simply insert the MenuItemIdentifier for that entry into the XML
<ModeToolBar id="ToolBarB"> <Import id="ptc.wnc.exp.DraftAppMode"/> <MenuItemIdentifier id="FileNewPartMI"/> <MenuItemIdentifier id="FileOpenPartMI"/> <Separator/> <MenuItemIdentifier id="FileSaveChangesMI"/> <MenuItemIdentifier id="FileAnnotationValidationMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CloseMI"/> <MenuItemIdentifier id="ptc.wnc.exp.LaunchNewPSEMI"/> <MenuItemIdentifier id="SetConfigSpecMI"/> <Separator/> <MenuItemIdentifier id="ptc.wnc.exp.InfoPageMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CutMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CopyMI"/> <MenuItemIdentifier id="ptc.wnc.exp.PasteMI"/> <Separator/> <MenuItemIdentifier id="ptc.wnc.exp.CopyToWindchillClipboardMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CopyFromWindchillClipboardMI"/> <Separator/> <MenuItemIdentifier id="SelectedAddChildMI"/> <MenuItemIdentifier id="SelectedAddNewChildMI"/> <MenuItemIdentifier id="SelectedAddInsertNewMI"/> <Separator/> <MenuItemIdentifier id="SelectedReplaceExistingMI"/> <MenuItemIdentifier id="SelectedReplaceCreateAndReplaceMI"/> <MenuItemIdentifier id="SelectedReplaceNewMI"/> <MenuItemIdentifier id="SelectedReplaceAlternateMI"/> <Separator/> <MenuItemIdentifier id="FileSpecEditorLaunchMI"/> <MenuItemIdentifier id="ptc.wnc.exp.ReviseMI"/> <MenuItemIdentifier id="SelectedRemoveMI"/> <Separator/> <MenuItemIdentifier id="ptc.wnc.exp.SelectParentMI"/> <MenuItemIdentifier id="ptc.wnc.exp.ExpandAllMI"/> <Separator/>

Customizing the Product Structure Explorer (PSE)

18-5

<MenuItemIdentifier <Separator/> <MenuItemIdentifier <MenuItemIdentifier <Separator/> <MenuItemIdentifier </ModeToolBar>

id="EditEditModeMI"/> id="ptc.wnc.exp.FindInStructureMI"/> id="NewQueryMI"/> id="HelpTopicsMI"/>

This results in the New Query icon appearing in the toolbar as shown in Section Intended Outcome.

Customization Points Customizing a Popup Menu


It is possible to change the content of a Popup Menu for a given mode. Adding existing actions, deleting and re-ordering the items in the definitions are supported. Consider the Uses Tab. The popup menu for the table does not, out-of-the-box; include the actions Insert Existing and Insert New in Draft mode. To add these to the popup menu, simply change the XML in ExplorerMenusForUsesTab.xml such that these MenuItemIdentifier is inserted.
<ModePopupMenu id="PopupMenuB"> <Import id="ptc.wnc.exp.DraftAppMode"/> <Import id="ptc.wnc.exp.AnnotateAppMode"/> <MenuItemIdentifier id="ptc.wnc.exp.CutAssocMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CopyAssocMI"/> <MenuItemIdentifier id="ptc.wnc.exp.PasteAssocMI"/> <Separator/> <MenuItemIdentifier id="AddChildMI"/> <MenuItemIdentifier id="NewChildMI"/> <Separator/> <MenuItemIdentifier id="ReplaceExistingMI"/> <MenuItemIdentifier id="CreateAndReplaceMI"/> <MenuItemIdentifier id="ReplaceNewMI"/> <MenuItemIdentifier id="ReplaceAlternateMI"/> <Separator/> <MenuItemIdentifier id="ptc.wnc.exp.RevertAssocMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CommentAssocMI"/> </ModePopupMenu>

The results in the Replace with Alternate/Substitute appearing in the popup in the Uses Tab as shown the Intended Outcome section on 18-2.

Limitations
Adding new MenuItems to Menus, Toolbar or Popup menus for actions that are not defined is not supported, as PSE currently has no supported API to allow custom actions to be created. Also adding actions to tables for which they are not designed is not supported.

18-6

Windchill Customizers Guide

Other Resources Related Customization Documentation


Managing Customizations chapter on page 5-1

Customizing the Product Structure Explorer (PSE)

18-7

Customizing PSE Table Display


Objective
You wish to change the default display order of columns in a PSE table, whether a specific column is mandatory or optional, or whether a column is frozen.

Background
With Windchill PDMLink Rev 9, PSE now provides the capability for users to customize the display of columns in tables. For example the Columns Details for the Uses Tab.

However, what a user can do is controlled within the bounds set in the PSE XML files that define the columns in each table.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all users of PSE.

Intended Outcome
The Rev 9 default display is that Number is a frozen mandatory column that is frozen (so it does not scroll) in the Uses Tab. Lets consider that we wish that Name is a mandatory attribute to display, that it and Reference Designator Range are frozen columns, Number is not frozen and is displayed though optional, Line Number is available but not displayed. As Number is optional, it will be removed from the tabular input search.

18-8

Windchill Customizers Guide

This is how the PSE User Interface will appear:

Solution
The CellDefinition element used in the PSE XML files has a number of attributes that control the display of columns in a table and dictate to what extent a user can change the tables appearance and behavior.
Attribute Description

mandatory displayWhenNoPreferenceSet pinnable pinned usedByTabularInput

If mandatory, the user may not hide the column Whether the column will be displayed, if it is not mandatory Whether the column may be frozen by the user Whether the column appears frozen by default In Draft and Annotate modes specifies if the cell will be used in Data Entry search.

Many of the PSE Tables including the Uses Tab Table are defined in the file
<Windchill>/codebase/config/logicrepository/xml/explorer/structure explorer/ExplorerForTablesAndPanels.xml

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Management of XML file customizations

Customizing the Product Structure Explorer (PSE)

18-9

Solution Elements
Element Type Description

ExplorerForTablesAndPanels.xml

XML file

Holds the definition of the tables and panels. Located in:


<Windchill>/codebase/config/logicrepo sitory/xml/structureexplore

Table CellDefinition

XML element XML element

Defined the table and contents The attribute with its appropriate behavior to be displayed in the AttributeTable.

Procedure
The Table id ptc.wnc.exp.PartUsesLinkTabTable in the file: <Windchill>/codebase/config/logicrepository/xml/explorer/structureexplorer/Exp lorerForTablesAndPanels.xml is used to show the Uses Table BOM, when showing occurrences ptc.wnc.exp.PartUsesOccTabTable us used. By change the order of the CellDefinitions for the Table, and specifying appropriate values for mandatory, displayWhen NoPreferenceSet, pinnable, pinned and usedByTabularInput, the desired table can be formed.
<Table id="ptc.wnc.exp.PartUsesLinkTabTable" selectionMode="multi-non-contiguous" displayMode="view"> <CellDefinition id="name" pinned="true" mandatory="true" usedByTabularInput="true" displayModeOverride="edit"> <AttributeDefinition attributeId="name"> <Import id="ptc.wnc.exp.SurfaceAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="referenceDesignatorRange" pinned="true" mandatory="false" displayModeOverride="edit"> <Label> <Resource key="referenceDesignatorRangeLabel"/> </Label> <AttributeDefinition attributeId="referenceDesignatorRange"> <Import id="ptc.wnc.exp.RefDesRangeAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="number" pinned="false" mandatory="false" displayWhenNoPreferenceSet="true" usedByTabularInput="false" displayModeOverride="edit"> <AttributeDefinition attributeId="number"> <Import id="ptc.wnc.exp.SurfaceAttrAction"/>

18-10

Windchill Customizers Guide

</AttributeDefinition> </CellDefinition> <CellDefinition id="usedLineNumber" pinned="false" mandatory="false" displayWhenNoPreferenceSet="false" displayModeOverride="edit"> <Label> <Resource key="lineNumberLabel"/> </Label> <AttributeDefinition attributeId="usedLineNumber"

rendererClass="com.ptc.windchill.explorer.structureexplorer.render er.component.LineNumberComponent"> <Import id="ptc.wnc.exp.LineNumberAttrAction"/> </AttributeDefinition> </CellDefinition>

After this change has been made, the method server has to be re-started. The client UI may still not appear correct, this is because a user preference is used to hold the current table layout. To clear this use the File->Preference action and reset the column/window layout preferences. When PSE is restarted, the Uses Tab table should appear as shown in the Intended Outcome section on 18-8.

Customization Points
The definition of the PSE Structure with id ptc.pdm.pse.ExplorerTreeTable is to be found in:

Customizing the Product Structure Explorer (PSE)

18-11

<Windchill>/codebase\config\logicrepository\xml\explorer\ productstructure\PDMLinkExplorerForTablesAndPanels.xml

Also, if Windchill Supplier Management is installed, its tables are defined in:
<Windchill>/codebase\config\logicrepository\xml\explorer\ productstructure\ExplorerForTablesAndPanelsForSUMA.xml

Other Resources Related Customization Documentation


Managing Customizations chapter on page 5-1

18-12

Windchill Customizers Guide

Customizing PSE for Soft Types


Objective
You have used the Attribute and Type Manager to define soft types of WTPart and possibly added attributes to WTPartUsageLink. Although these types and attributes typically appear in PSE without customization, you wish to control the display of these attributes in the PSE UI.

Background
The selection of a type of Part in PSE typically automatically detects if soft types have been defined with the Type Manager. Attributes will automatically be prompted for, and displayed. This is achieved in the PSE XML files by entries referencing attribute definitions with ids of: ALL_SOFT_SCHEMA_ATTRIBUTES ALL_SOFT_CLASSIFICATION_ATTRIBUTES ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES

Although these entries are useful, it is not possible to control the order of display. Also, some values may get set programmatically on the server, and so the user should not be allowed to specify values. Consider the simple example where WTPart has had an IBA myDescription added to the base definition. A myMechanical Part has been defined in the Type Manager with attributes of myCost and myWeight, WTPartUsageLink has been extended to have an IBA of myColor. The steps to insert a new myMechanical Part into an assembly would result in these screens.

Customizing the Product Structure Explorer (PSE)

18-13

The Insert New wizard would present a drop down of instantiable types. The user selects myMechanical part.

After the Name and other properties have been specified, the last step in the wizard will prompt for the IBAs, although the Attribute column can be sorted, the default order is not controlled.

The info Tab for myMechanical Part presents all attributes, but not in any sort of order. The attributes in the upper part of the display represent the fixed set applicable to identify that object; some of these may not be relevant. The attributes in the lower editable table include attributes inherited from WTPart and are in no controlled order.

18-14

Windchill Customizers Guide

The myColor attribute would not appear in the Uses Tab, but it might be useful for the user to see the value with the other UsageLink attributes. By customizing the PSE XML files, it is possible to explicitly define those attributes to be presented to the user. This typically impacts the Information Tab, and Part Creation and Insert wizards.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all users of PSE.

Intended Outcome
Considering the example described above.

When specifying the attributes of the New Part, the attributes in the last step of the wizard appear in the order defined in the PSE XML.

Customizing the Product Structure Explorer (PSE)

18-15

files.

The attributes in the lower table of the Information Tab can also be ordered.

The Uses BOM Table can be configured to show the Usage Link attribute.

Solution
For the dataType, defined a new ExplorerElementGroup with the context application of ptc.wnc.StructureExplorer. Within this element define the contents of the Attribute Tables. It is likely that if you are doing this customization you have many types of WTPart defined. Although these element definitions can be added to the file

18-16

Windchill Customizers Guide

<Windchill>/codebase/config/logicrepository/xml/explorer/structureexplorer/Exp lorerForTablesAndPanels.xml This file is getting large, and it is difficult to identify customer extensions. So the suggestion is to create a file per soft part type to hold the customization. The AttributeTables with ids ptc.wnc.exp.CreatPartTab3, ptc.wnc.exp.CreatePartNoUsageLinkTab3 and ptc.wnc.exp.EditPropertiesTable would be defined for each dataType. The addition of the attributes in the Uses Tab is achieved by including the appropriate CellDefinition for the table with id ptc.wnc.exp.PartUsesLinkTable in ExplorerForTablesAndPanels.xml

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The management of XML file customizations

Solution Elements

Element

Type

Description

ExplorerForTableAndPanels.xml

XML file

Holds the definition of the PSE Tables and panels Located in:
<Windchill>/codebase/config/logicrepo sitory/xml/structureexplore

LogicContext AttributeTable CellDefinition Placement remove=true

XML element XML element XML element XML element

Specifies the application and data type that the definition is to be applied Defined the attribute table and contents The attribute with its appropriate behavior to be displayed in the AttributeTable. Remove=true is used to stop a property from appearing due to inheritance.

Procedure
Either create a new file representing the Soft Part (myMechanical.xml) in the directory:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree xplorer

and insert the following lines, or add the ExplorerElementGroup to

Customizing the Product Structure Explorer (PSE)

18-17

Windchill>/codebase/config/logicrepository/xml/explorer/structuree xplorer/ExplorerForTablesAndPanels.xml <?xml version="1.0" standalone="no" ?> <!DOCTYPE LogicRepository SYSTEM "/config/logicrepository/dtd/LogicRepository.dtd"> <LogicRepository> <ExplorerElementGroup> <LogicContext application="ptc.wnc.StructureExplorer" dataType="com.aprilia.www.myMechanical"/> <AttributeTable id="ptc.wnc.exp.CreatePartTab3"> <Table id="Table" displayMode="edit"> <!-- These 3 entries remove the inherited entries from WTPart --> <CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <!-- Add the entries for attributes on Parts and UsageLink in the specific order --> <CellDefinition id="myDescription"> <AttributeDefinition attributeId="com.aprilia.www.myDescription" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myColor"> <AttributeDefinition attributeId="com.aprilia.www.myColor" imageName="com/ptc/windchill/explorer/config/images/usesTab.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myCost"> <AttributeDefinition attributeId="com.aprilia.www.myCost" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myWeight"> <AttributeDefinition attributeId="com.aprilia.www.myWeight" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> </Table>

18-18

Windchill Customizers Guide

<Import id="ptc.wnc.exp.NewObjectAttrTableAA"/> </AttributeTable> <AttributeTable id="ptc.wnc.exp.CreatePartNoUsageLinkTab3"> <Table id="Table" displayMode="edit"> <!-- These 2 entries remove the inherited entries from WTPart --> <CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <!-- Add the entries for attributes on Parts in the specific order --> <CellDefinition id="myDescription"> <AttributeDefinition attributeId="com.aprilia.www.myDescription" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myCost"> <AttributeDefinition attributeId="com.aprilia.www.myCost" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myWeight"> <AttributeDefinition attributeId="com.aprilia.www.myWeight" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> </Table> <Import id="ptc.wnc.exp.NewObjectAttrTableAA"/> </AttributeTable> <AttributeTable id="ptc.wnc.exp.EditPropertiesTable"> <Table id="Table" displayMode="edit"> <!-- These 3 entries remove the inherited entries from WTPart --> <CellDefinition id="source"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="partType"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="ALL_SOFT_SCHEMA_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="ALL_SOFT_CLASSIFICATION_ATTRIBUTES">

Customizing the Product Structure Explorer (PSE)

18-19

<Placement remove="true"/> </CellDefinition> <CellDefinition> id="ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES"> <Placement remove="true"/> </CellDefinition> <!-- Add the entries for attributes on Parts and UsageLink in the specific order --> <CellDefinition id="myDescription"> <AttributeDefinition attributeId="com.aprilia.www.myDescription" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myColor"> <AttributeDefinition attributeId="com.aprilia.www.myColor" imageName="com/ptc/windchill/explorer/config/images/usesTab.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myCost"> <AttributeDefinition attributeId="com.aprilia.www.myCost" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> <CellDefinition id="myWeight"> <AttributeDefinition attributeId="com.aprilia.www.myWeight" imageName="wtcore/images/part.gif"> <Import id="ptc.wnc.exp.CreatePanelAttrAction"/> </AttributeDefinition> </CellDefinition> </Table> <Import id="ptc.wnc.exp.EditPropertiesTableAA"/> </AttributeTable> </ExplorerElementGroup> </LogicRepository>

This results in the attributes being requested in the Wizard and Information Tab as shown in Section Intended Outcome. To add the IBA to the Uses Tab, edit:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree xplorer/ExplorerForTablesAndPanels.xml

Locate the Table entry with id ptc.wnc.exp.PartUsesLinkTabTable and add:


<CellDefinition id="myColor" displayModeOverride="edit"> <AttributeDefinition attributeId="com.aprilia.www.myColor"> <Import id="ptc.wnc.exp.AssocAttrAction"/>

18-20

Windchill Customizers Guide

</AttributeDefinition> </CellDefinition>

The method server will need to be re-started in order that these changes are applied.

Further customization
To extend the above example, consider adding the myDescription attribute to the Uses Tab. When editing this String attribute, the user may want to specify many characters, however to perform this in the space of the cell in a table is not easy. So, it is possible to associate a different renderer to this attribute that will popup a dialog when editing the value, allow the user to enter many lines of text. Edit:
Windchill>/codebase/config/logicrepository/xml/explorer/structuree xplorer/ExplorerForTablesAndPanels.xml

Locate the Table entry with id ptc.wnc.exp.PartUsesLinkTabTable and add


<CellDefinition id="myDescription" displayModeOverride="edit"> <AttributeDefinition attributeId="com.aprilia.www.myDescription" rendererClass="com.ptc.windchill.explorer.structureexplorer.renderer.component.Mult ilineStringComponent"> <Import id="ptc.wnc.exp.AssocAttrAction"/> </AttributeDefinition> </CellDefinition>

Just using the Golf Cart as an example, this will result in the following dialog being presented when the button is selected in the cell.

This renderer could also be applied to the attributes in the Information Tab.

Customizing the Product Structure Explorer (PSE)

18-21

Customization Points
In section Background there are a number of special attributes that are defined in LogicalAttributes.xml that allow PSE to display a number of attributes for a single definition. These include:
Logical Form Description

ALL_SOFT_ATTRIBUTES ALL_SOFT_CLASSIFICATION_A TTRIBUTES ALL_SOFT_NON_SCHEMA_ATT RIBUTES ALL_SOFT_SCHEMA_ATTRIBUT ES ALL_SOFT_NON_CLASSIFICATI ON_SCHEMA_ATTRIBUTES ALL_SOFT_NON_CLASSIFICATI ON_ATTRIBUTES ALL_SOFT_USAGE_LINK_SCHE MA_ATTRIBUTES ALL_SOFT_SCHEMA_ATTRIBUT ES_FOR_INPUT_TYPE

All IBAs persisted on the object All IBAs associated with the classification of the object. All IBAs persisted on the object that are not associated with the type of the object. All IBAs associated with the type of the object. All IBAs associated with the type of the object that are not also associated with the classification of the object. All IBAs persisted on the object that are not associated with the classification of the object In the context of a part, all IBAs on the part usage link(s) that are associated with the type of the part usage link All IBAs associated with the type specified in the filter, which may be a supertype of the actual object

In Rev 9, PSE uses ALL_SOFT_SCHEMA_ATTRIBUTES", "ALL_SOFT_CLASSIFICATION_ATTRIBUTES" and ALL_SOFT_USAGE_LINK_SCHEMA_ATTRIBUTES" in the definition of Information Tab attribute table (and also in the Create Wizard. In the Information Tab) Using ALL_SOFT_ATTRIBUTES instead of ALL_SOFT_SCHEMA_ATTRIBUTES or adding an entry for ALL_SOFT_NON_SCHEMA_ATTRIBUTES would allow attributes programmatically populated from CAD to be displayed.

18-22

Windchill Customizers Guide

Other Resources Related Customization Documentation


Managing Customizations chapter on page 5-1

Customizing the Product Structure Explorer (PSE)

18-23

Customizing PSE to Handle Modeled Subclasses


Objective
You have created a custom modeled business object; you want to customize the PSE so that it will fully support your modeled subclass.

Scope/Applicability/Assumptions
You have separately created your modeled subclass.

Intended Outcome
Instances of your modeled subclass will be detected and presented by PSE in the same manner as out-of-the-box modeled objects.

Solution
Make changes in the following three areas: LogicalAttributes.xml PSE Tables and Panels Customized command delegates

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The management of XML file customizations The management of RBINFO file customizations

Solution Elements

Element

Type

Description

LogicalAttributes.xml

XML file

Used to configure modeled attribute mappings from a "logical form" to its "external form".

Procedure Customizing PSE to Handle Modeled Subclasses


This section contains the following topics: LogicalAttributes.xml PSE Tables and Panels Customized command delegates

18-24

Windchill Customizers Guide

LogicalAttributes.xml

A LogicalAttributes.xml file, located in <Windchill>/codebase/LogicalAttributes.xml, is used to configure modeled attribute mappings from a "logical form" to its "external form". A mapping is required for all modeled attributes that represent an association from one object to another. For example some of the entries defined for the WTPart to WTPartMaster reference are:
<Class name="wt.part.WTPart"> <Property> <LogicalForm>defaultUnit</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|defaultUnit</ExternalForm> </Property> <Property> <LogicalForm>masterReference</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster</ExternalForm> </Property> <Property> <LogicalForm>name</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|name</ExternalForm> </Property> <Property> <LogicalForm>number</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|number</ExternalForm> </Property> <Property> <LogicalForm>organizationReference</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|organizationReference^WCTYPE| wt.org.WTOrganization</ExternalForm> </Property> <Property> <LogicalForm>organizationName</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|organizationReference^WCTYPE| wt.org.WTOrganization~MBA|name</ExternalForm> </Property> <Property> <LogicalForm>usedLineNumber</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|uses@WCTYPE| wt.part.WTPartUsageLink~MBA| lineNumber.value</ExternalForm> </Property> <Property> <LogicalForm>usedLink</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| wt.part.WTPartMaster~MBA|uses@WCTYPE| wt.part.WTPartUsageLink</ExternalForm> </Property> </Class>

Customizing the Product Structure Explorer (PSE)

18-25

Using the example that "ext.cust.CustPart" extends wt.part.WTPart, and "ext.cust.SubPartMaster" extends wt.part.WTPartMaster, the following should be added to the site-specific file called <Windchill>/codebase/LogicalAttributesSite.xml:
<Class name="ext.cust.CustPart"> <Property> <LogicalForm>defaultUnit</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|defaultUnit</ExternalForm> </Property> <Property> <LogicalForm>masterReference</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster</ExternalForm> </Property> <Property> <LogicalForm>name</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|name</ExternalForm> </Property> <Property> <LogicalForm>number</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|number</ExternalForm> </Property> <Property> <LogicalForm>organizationReference</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|organizationReference^WCTYPE| wt.org.WTOrganization</ExternalForm> </Property> <Property> <LogicalForm>organizationName</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|organizationReference^WCTYPE| wt.org.WTOrganization~MBA|name</ExternalForm> </Property> <LogicalForm>usedLineNumber</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|uses@WCTYPE| wt.part.WTPartUsageLink~MBA| lineNumber.value</ExternalForm> </Property> <Property> <LogicalForm>usedLink</LogicalForm> <ExternalForm>MBA|masterReference^WCTYPE| ext.cust.SubPartMaster~MBA|uses@WCTYPE| wt.part.WTPartUsageLink</ExternalForm> </Property> </Class>

18-26

Windchill Customizers Guide

PSE Tables and Panels

You do not need to add new modeled attributes to the LogicalAttributes.xml file, but you must add them to the appropriate PSE configuration XML files. Refer to Customizing PSE for Soft Types on page 18-13 for additional information. Note: When specifying new modeled attributes that are defined only for subclass objects, the corresponding "AttributeGroup" or AttributeTable or "Table defined in a "wt.part.WTPart" context should be copied to the appropriate subclass context. Only new modeled attributes need to be listed. Existing attributes will be inherited. For example, name and number will be inherited from WTPart. To remove attributes from a sub-classed panel that are inherited, use "<Placement remove="true"/>", E.g.
<AttributeDefinition id="containerName> <Placement remove="true"/>" </AttributeDefinition>

A good practice when adding element groups for customized objects is to put all customized changes in a separate file, rather than edit existing files. Name them consistently, e.g. CustomExplorerForTablesAndPanels.xml. Using the previous example of "ext.cust.CustPart" extends "wt.part.WTPart", the following AttributeGroup
<ExplorerElementGroup> <LogicContext application="ptc.wnc.StructureExplorer" dataType="wt.part.WTPart"/> <AttributeGroup id="ptc.wnc.exp.ViewPropertiesPanel" displayMode="view"> <CellDefinition id="number"> <AttributeDefinition attributeId="number"/> </CellDefinition> <CellDefinition id="organizationIdentifier"> <AttributeDefinition attributeId="organizationIdentifier"/> </CellDefinition> <CellDefinition id="name"> <AttributeDefinition attributeId="name"/> </CellDefinition> <CellDefinition id="versionIterationView"> <AttributeDefinition attributeId="versionIterationView"/> </CellDefinition> ... </AttributeGroup> </ElementGroup>

should be copied under the LogicContext for "ext.cust.CustPart" like this:


<ExplorerElementGroup> <LogicContext application="ptc.wnc.StructureExplorer" dataType=" ext.cust.CustPart "/> <AttributeGroup id="ptc.wnc.exp.ViewPropertiesPanel" displayMode="view"> <!-- name and number will inherit from WTPart --> <!-- adding new modeled attributes here -->

Customizing the Product Structure Explorer (PSE)

18-27

<CellDefinition id="intMBA"> <AttributeDefinition attributeId="intMBA"/> </CellDefinition> ... </AttributeGroup> </ElementGroup>

Customized command delegates

PSE uses a Command/CommandDelegate mapping to control some of its operations. The most notable example is the "Duplicate Action". To "duplicate" a customized class, you need to subclass the appropriate copy delegate. In the case of "CustPart", you need to create a class that is a subclass of wt.enterprise.CopyWTPartDelegate and handle the copying of your customized modeled attributes.

Writing a Copy Delegate for A Custom Class


When an out of the box business object (such as part) is customized to create a modeled sub-class, it is necessary to create and configure a custom copy delegate class so that when the part is copied (or saved as), additional modeled attributes are handled properly.

This document illustrates the steps with a simple example: a custom part class MyPart that extends wt.part.WTPart with a single string attribute myAttr.
Creating a Copy Delegate

As illustrated in the figure, you can simply extend wt.enterprise.CopyWTPartDelegate and override its newCopy() method. The purpose is to handle any custom attributes, in this particular case, myAttr. Heres how this method is implemented:
public final RevisionControlled newCopy( RevisionControlled object )throws WTException {

18-28

Windchill Customizers Guide

//##begin newCopy%461E645C0050f.body preserve=yes if (object == null) return null; MyPart new_copy = (MyPart) super.newCopy(object); MyPart original = (MyPart) object; String my_attr = original.getMyAttr(); if (my_attr != null) { try { new_copy.setMyAttr(original.getMyAttr()); } catch (WTPropertyVetoException e) { throw new WTException(e); } } return new_copy; //##end newCopy%461E645C0050f.body }

Configuring a Copy Delegate

To instruct Windchill to use the custom copy delegate CopyMyPartDelegate as the copy delegate class for MyPart, the following line needs to be inserted into configuration file <windchill-installdirectory>/codebase/wt/enterprise/EnterpriseServerDelegate.properties.
wt.services/svc/default/wt.enterprise.CopyDelegate/null/<mypackage>.MyPart/0=<mypackage>. CopyMyPartDelegate/singleton

Customization Points Customizing Localizable Labels and Enumerations


Caution: When working with RBINFO files, follow the practices recommended in the Managing Customizations chapter starting on page 5-1, for example Changing Displayed Text Found in RBINFO Files. Each modeled object has an associated RBINFO file, created during generation, that contains localized strings that are used as the labels for attributes and columns in PSE. If the label needs to be changed, the corresponding RBIFNO file should be edited. For example, in the file CustPartModelRB.rbInfo, to change the label for the attribute "booleanMBA", edit the following line:
CustPart.booleanMBA.value=New Label for booleanMBA

For more information, see the Customizing Localizable Display Names for Modeled Elements in the Generic UI Customizations chapter on page 9-3. Modeled enumerations will display the internal values of the enumerations, when rendered as a drop-down menu in PSE. To change the labels displayed in a dropdown menu, the corresponding RBINFO file for the enumeration should be

Customizing the Product Structure Explorer (PSE)

18-29

edited. For example, if you generate a class, "public final class MyEnum extends EnumeratedType" with values "apple", "dog", "cat" and you wish to change the display value in the drop-down menu, edit the file MyEnumRB.rbInfo like this:
# Entry Contents apple.value=Apples dog.value=Dogs cat.value=Cats

More information can be found in the Enumerated Types chapter on page 33-1.

Other Resources
Customizing PSE Table Display on page 18-8

18-30

Windchill Customizers Guide

Customizing PSE Structure Queries


Objective
You want to customize the PSE New Query dialog to include soft types of WTPart and allow queries to be created referencing IBAs of the soft type.

Background
The dialog launched from the View->Query->New Query menu entry allows the user to construct a query that will locate objects in the structure that match the specified criteria. The out-of-the-box configuration allows specific attributes of WTPart to be queried.

Customers will create their own soft types of WTPart with their own attributes. In order to allow these to be used in the query, customization of the PSE XML files is required.

Scope/Applicability/Assumptions
As these changes are being made to the PSE XML files, they will apply to all users of PSE.

Intended Outcome
You may want to include the soft WTPart myPart in the searchable Types, and allow the attributes myCost and myDescription to be queried. As End Item,

Customizing the Product Structure Explorer (PSE)

18-31

Generic and Reference Designator are not relevant to this type, these are removed from the Property drop-down.

Solution
Add the appropriate element group in
<Windchill>/codebase/config/logicrepository/xml/explorer/structure explorer/ExplorerSearchableTypes.xml

The element group will define CellDefinitions (both additions and removals) for the AttributeGroup with id="ptc.wnc.exp.QuerySearchableAttrs " for the myPart type.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The management of XML file customizations

18-32

Windchill Customizers Guide

Solution Elements
Element Type Description

ExplorerSearchableTypes.xml

XML file

Holds the definition of types and attributes that will be exposed in the New Query dialog. Located in:
<Windchill>/codebase/config/logicreposi tory/xml/structureexplore

LogicContext AttributeGroup

XML element XML element

Specifies the application and data type that the definition is to be applied PSE locates all the attribute groups with id ptc.wnc.exp.QuerySearchableAttres, and uses the type inheritance to find all the properties (CellDefinitions) that will be displayed. The id of the property that will appear. Remove=true is used to stop a property from appearing due to inheritance.

CellDefinition Placement remove=true

XML element XML element

Procedure
Edit the file ExplorerSearchableTypes.xml, before the final line </LogicRepository> insert the following lines:
<!-- New Query definition for soft type myPart --> <ExplorerElementGroup> <LogicContext application="ptc.wnc.StructureExplorer" dataType="com.aprilia.www.myPart"/> <AttributeGroup id="ptc.wnc.exp.QuerySearchableAttrs" displayMode="view"> <!-- Remove the following that would otherwise be inherited from WTPart Definition --> <CellDefinition id="endItem"> <Placement remove="true"/> </CellDefinition> <CellDefinition id="genericType> <Placement remove="true"/> </CellDefinition> <CellDefinition id="referenceDesignator"> <Placement remove="true"/> </CellDefinition> <!-- Add the specific attributes of myPart --> <CellDefinition id="myCost"> <AttributeDefinition attributeId="com.aprilia.www.myCost"/> </CellDefinition> <CellDefinition id="myDescription"> <AttributeDefinition attributeId="com.aprilia.www.myDescription"/> </CellDefinition> </AttributeGroup> </ExplorerElementGroup>

Customizing the Product Structure Explorer (PSE)

18-33

After the method server is restarted, this results in myPart appearing in the Type drop-down, with Property entries End Item, Generic and Reference Designator removed, and myCost and myDescription added, as shown in Section Intended Outcome. Alternatively, if the changes are to be made to other aspects of the PSE UI via XML customization, these additional lines can be added to an XML file that holds all the myPart customization.

Customization Points
It is valid to remove the WTPart definition from ExplorerSearchableTypes.xml, so Part does not appear in the type drop-down. However, no definitions of the properties will be inherited by the soft type definitions, so these will have to be added.

Other Resources Related Customization Documentation


Managing Customizations chapter on page 5-1

18-34

Windchill Customizers Guide

Customizing Attribute Displays within Section Headings


You can control the display of attributes by customizing the SectionHeading tag. This section contains the following topics: Customizing the Display of Attributes in Groups on page 18-35 Expanding/Collapsing the Display Groupings on page 18-40 Customizing the Number of Columns to Display on page 18-41

Customizing the Display of Attributes in Groups


There is a clause in the SectionHeading element that allows you to edit the detail of a group of attributes. Using this clause you can hide or show specific attribute from panels in the display, such as the Create Part Wizard, Insert Child Wizard, or the Information Tab. In the following sample code "allowAttrDetails=true" clauses have been added to the SectionHeading element of the CreateChildPartTab2 attribute group that is used by the Insert Child Wizard. Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreateChildPartTab2" scrollable="true" displayMode="edit"> <SectionHeading allowAttrDetails="true"> <Label> <Resource key="Properties Top"/> </Label> </SectionHeading> <CellDefinition id="name"> <AttributeDefinition attributeId="name"/> </CellDefinition> <CellDefinition id="number"> <AttributeDefinition attributeId="number" rendererClass="com.ptc.windchill.explorer.structureexplorer.render er.component.PartNumberComponent"/> </CellDefinition> <SectionHeading allowAttrDetails="true"> <Label> <Resource key="Properties 1"/> </Label> </SectionHeading> <CellDefinition id="view"> <AttributeDefinition attributeId="view" rendererClass="com.ptc.windchill.explorer.structureexplorer.render er.component.ViewComponent"/> </CellDefinition> <CellDefinition id="folder"> <AttributeDefinition attributeId="folder" rendererClass="com.ptc.windchill.explorer.structureexplorer.render er.component.DefaultContainerFolderBrowserComponent"/>

Customizing the Product Structure Explorer (PSE)

18-35

</CellDefinition> <CellDefinition id="source"> <AttributeDefinition attributeId="source"/> </CellDefinition> <CellDefinition id="partType"> <AttributeDefinition attributeId="partType"/> </CellDefinition> <SectionHeading allowAttrDetails="true"> <Label> <Resource key="Properties 2"/> </Label> </SectionHeading> <CellDefinition id="usedQuantityAmount"> <AttributeDefinition attributeId="usedQuantityAmount"/> </CellDefinition> <CellDefinition id="usedQuantityUnit"> <AttributeDefinition attributeId="usedQuantityUnit"/> </CellDefinition> <CellDefinition id="usedTraceCode"> <AttributeDefinition attributeId="usedTraceCode"/> </CellDefinition> <CellDefinition id="effPropagationStop"> <AttributeDefinition attributeId="effPropagationStop"/> </CellDefinition> <CellDefinition id="jobAuthorizationNumber"> <AttributeDefinition attributeId="jobAuthorizationNumber"/> <EnabledDependency inverted="false"> <Assembly assembly="wadm"/> </EnabledDependency> </CellDefinition> <CellDefinition id="contractNumber"> <AttributeDefinition attributeId="contractNumber"/> <EnabledDependency inverted="false"> <Assembly assembly="wadm"/> </EnabledDependency> </CellDefinition> <CellDefinition id="phase"> <AttributeDefinition attributeId="phase"/> <EnabledDependency inverted="false"> <Assembly assembly="wadm"/> </EnabledDependency> </CellDefinition> </AttributeGroup>

Adding the "allowAttrDetails=true" clauses produces the following output in the UI. Adding a SectionHeading creates the box around the group of attributes that follow the SectionHeading. The Label clause of the SectionHeading gives the text for the box.

18-36

Windchill Customizers Guide

The allowAttrDetails="true" clause enables the Details icon to show after the label and also enables a popup menu for the panel.

Customizing the Product Structure Explorer (PSE)

18-37

This is the Details dialog that displays after you click the Details icon after the label. The user can hide or show individual attributes, but cannot change the order of the attributes.

For example, the user can choose to hide the Location attribute within the Properties 1 section. This is now saved as a preference for this user and will stay this way the next time the user loads PSE.

18-38

Windchill Customizers Guide

Customizing the Product Structure Explorer (PSE)

18-39

Expanding/Collapsing the Display Groupings


If multiple groups are displayed on a tab or in a step in a wizard, this could cause the contents of the frame to scroll. This might be annoying to a user, especially if they only want to enter the minimum number of attributes. You can customize the Title to allow the user to expand/collapse the set of attributes displayed. This setting will be remembered from session to session. This is an example of what the UI might look like. The "Responsibilities" group is collapsed, so the + icon is available to expand it. The "Production Data" group is expanded so the - icon is available to collapse it.

Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreateChild" displayMode="edit"> <SectionHeading id="ptc.wnc.exp.CreateChild.Responsibilities" allowAttrDetails="true" allowCollapsable="true"> <Label> <Resource key="responsibilitiesSectionLabel"/> </Label> </SectionHeading> cell definitions for the group here </AttributeGroup>

18-40

Windchill Customizers Guide

Customizing the Number of Columns to Display


You can customize the number of columns to display within the SectionHeading tag. You can create layouts like the following example.

If you specify a SectionHeading before a group of attributes, those attributes will be enclosed in a border with a title specified by the <Label> tag. See Customizing the Display of Attributes in Groups on page 18-35 for more information on the <Label> tag. If the numberOfColumns is set to 1, a single column of attributes will display; if set to 2 two columns of attributes will display. In the example screenshot above, URL0: is a single attribute that happens to have two fields for input. Note that if any of the attribute in a section is required, the label on the border is also marked as required. Sample Code:
<AttributeGroup id="ptc.wnc.exp.CreatePartTab4" scrollable="true" displayMode="edit"> <SectionHeading numberOfColumns="1"> <Label> <Resource key="checkoutInfoStateLabel"/> </Label> </SectionHeading> <CellDefinition id="String0"> <AttributeDefinition attributeId="IBA|String0"/> </CellDefinition> <CellDefinition id="URL0"> <AttributeDefinition attributeId="IBA|URL0"/> </CellDefinition>

Customizing the Product Structure Explorer (PSE)

18-41

<SectionHeading numberOfColumns="2"> <Label> <Resource key="serialNumberValueLabel"/> </Label> </SectionHeading> <CellDefinition id="Boolean0"> <AttributeDefinition attributeId="IBA|Boolean0" required="true"/> </CellDefinition> <CellDefinition id="Integer0"> <AttributeDefinition attributeId="IBA|Integer0" required="true"/> </CellDefinition> <CellDefinition id="Real0"> <AttributeDefinition attributeId="IBA|Real0"/> </CellDefinition> <CellDefinition id="DateTime0"> <AttributeDefinition attributeId="IBA|DateTime0"/> </CellDefinition> </AttributeGroup>

18-42

Windchill Customizers Guide

Customizing Tabs - Configure Existing Tabs with Subtabs


This process consists of customizing the sub-tab and then changing the Information tab that makes use of the customization. To customize your XML to show sub-tabs, a <Tab> tag may now include a <TabSet>. For example the Information Tab used to Import a Panel tag. Now it includes a <TabSet> that contains four <Tab>s. All the standard tab actions (hiding/showing tabs, moving tabs, pop-up menus, and preferences that remember tab settings) are available for the main tabs are also available for subtabs. The Identity tab displays thumbnail and read-only attributes.

The Object Attributes tab shows only those attributes that are attached directly to the selected part, not the link attributes.

Customizing the Product Structure Explorer (PSE)

18-43

The Usage Attributes tab only shows the link attributes. Note that the tab is not enabled when the top node is selected, because there is not a usage link so there cannot be any link attributes.

The Classification tab is only visible if the PartsLink module is installed. It displays all the classification attributes.

18-44

Windchill Customizers Guide

Allow Additional Steps During New Object Creation


The PSE create wizards are defined in ExplorerForTablesAndPanels.xml. The "create new object" wizard is defined by the WizardList segment with the id of ptc.wnc.exp.CreateWizardList and the "insert new child" wizard is defined by the WizardList segment with the id of ptc.wnc.exp.CreateChildWizardList. It is recommended that you customize these wizards in separate xml files rather than editing ExplorerForTablesAndPanels.xml. The current steps allowed in the WizardList are AttributeGroup and AttributeTable. To add a new AttributeGroup or AttributeTable redefine the WizardList in your customization file and include your new steps along with placements segments. For example:
<WizardList id="ptc.wnc.exp.CreateChildWizardList"> <AttributeGroup id="ptc.custom.exp.CustomCreatePartTab2A"> <Placement insertKey="after" insertId="ptc.wnc.exp.CreateChildPartTab2"/> <CellDefinition id="endItem"> <AttributeDefinition attributeId="endItem"/> </CellDefinition> </AttributeGroup> </WizardList>

The first line duplicates the id of the WizardList you want to modify. The second line shows the addition of a new AttributeGroup inline, it could also be defined in another place then imported here similar to the original WizardList definition. The Placement segment indicates that your new AttributeGroup is to be shown after CreateChildPartTab2. You can also remove an AttributeGroup or AttributeTable from the original WizardList that you don't want to use. For example, the following xml removes the last step of the wizard (the AttributeTable that shows all the soft attributes):
<WizardList id="ptc.wnc.exp.CreateChildWizardList"> <AttributeTable id="ptc.wnc.exp.CreatePartTab3"> <Placement remove="true"/> </AttributeTable> </WizartList>

The ExplorerForTablesAndPanels.xml contains many good examples of how to create AttributeGroups or AttributeTables. Within either of these segments, define the list of CellDefinitions for each attribute you want to show. You could also redefine the existing AttributeGroups or AttributeTables and add or remove Celldefinitions using Placement segments. For example:
<AttributeGroup id="ptc.wnc.exp.CreatePartTab2"> <CellDefinition id="partType"> <AttributeDefinition attributeId="partType"/> <Placement insertKey="before" insertId="endItem"/> </CellDefinition> <CellDefinition id="genericType"> <AttributeDefinition attributeId=" genericType"/>

Customizing the Product Structure Explorer (PSE)

18-45

<Placement remove="true"/> </CellDefinition> </AttributeGroup>

This example takes the existing AttributeGroup defined for the CreatePartTab2 step and adds the partType attribute before the endItem and removes the genericType attribute. Note that CreatePartTab2 is imported into both the CreateWizardList and the CreateChildWizardList so you will be modifying both wizards.

18-46

Windchill Customizers Guide

Type Picker Display Customization


In the Explorer.dtd, the parameter hideSingleValueTypePicker has been added to the <AttributeGroup> element, the default value is false. This flag controls whether or not the Type Picker will be displayed if it has only one value in the list. By default it will be displayed if it has only one value. Customizing for a User Searching for an Existing Type To configure this for situations where the user is searching for an existing type, and the Type Picker is being populated with a list of Types to choose from, e.g. File >> Open >> Part 1. Locate the following XML file:
ExplorerForSearch.xml ExplorerForSearchForSuma.xml

2. Locate the <ExplorerElementGroup> for which you want to configure this setting. The dataType attribute of the <LogicContext> element will define the Types this change will be effective for. 3. Locate the <AttributeGroup> element with id=ptc.wnc.exp.SearchCriteriaPanel 4. Add the parameter hideIfListSizeIsOne with true/false value. E.g.:
<AttributeGroup id=ptc.wnc.exp.SearchCriteriaPanel hideSingleValueTypePicker =false>

Note: This change will be effective for ALL instances of the GUI panel for the Type defined in the <LogicContext> element. Customizing for a User Creating a New Instance of a Type To configure this for situations where the user is creating a new instance of a Type, and the Type Picker is being populated with a list of Types to choose from, e.g. File >> New >> Part 1. Locate the following XML file:
ExplorerForTablesAndPanels.xml

2. Locate the <ExplorerElementGroup> for which you want to configure this setting. The dataType attribute of the <LogicContext> element will define the Types this change will be effective for. 3. Locate the <AttributeGroup> element with id=ptc.wnc.exp.CreatePartTab1 4. Add the parameter hideIfListSizeIsOne with true/false value. E.g.:
<AttributeGroup id= ptc.wnc.exp.CreatePartTab1 hideSingleValueTypePicker =false>

Customizing the Product Structure Explorer (PSE)

18-47

Note: This change will be effective for ALL instances of the GUI panel for the Type defined in the <LogicContext> element. Note: Dropdowns in the Find In Structure dialog and Create/Edit Query Wizard are not impacted by this change and will remain as they were.

18-48

Windchill Customizers Guide

Disabling Actions by Object Type


To disable an action in PSE by object type, follow these instructions: 1. Edit the ExplorerStructures.xml file. Create a <TypeDefinition> element for the type(s) you will disable the action(s) for. E.g. for the types org.my.MyTypeA , org.my.MyTypeB and org.my.MyTypeD which are children of WTPart you would define the following elements:
<TypeDefinition id="com.my.MyTypeATD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeA"/> <TypeDefinition id="com.my.MyTypeBTD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeB"/> <TypeDefinition id="com.my.MyTypeDTD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeD"/>

2. Edit the ExplorerValidators.xml file. Create a <ValidatorDefinition> element for the group of types you wish to disable actions for. This will return false if the the type of the selected part matches one of the types referenced in the validator definition. E.g. for the three types above, you would define a validator as follows:
<ValidatorDefinition id="com.my.IsNotEqualToTypesABDVAL" validatorClass="com.ptc.windchill.explorer.structureexplorer.va lidators.IsValidTypeValidator" inverted="true"> <Import id="com.my.MyTypeATD"/> <Import id="com.my.MyTypeBTD"/> <Import id="com.my.MyTypeDTD"/> </ValidatorDefinition>

Note: It is important that the value for the validatorClass attribute of ValidatorDefinition be the exact class listed above, and that the the inverted attribute be set to true. 3. Edit the ExplorerActions.xml file. Add a <ValidatorEntry> element to the actions you wish to have disabled for the specified types.
<ActionDefinition id="ptc.wnc.exp.EditCommonAttrsAction" ... > ... <ValidatorEntry> <Import id="com.my.IsNotEqualToTypesABDVAL"/> </ValidatorEntry> ... </ActionDefinition>

This configuration will disable the Edit Common Attributes action in the PSE application whenever an part of type A, B or D is selected.

Customizing the Product Structure Explorer (PSE)

18-49

Validator isValidTypeValidator
The validator isValidTypeValidator is implemented by the class: com.ptc.windchill.explorer.structureexplorer.validators.IsValidTypeValidator. For a given set of type definitions, this validator will return true if the type of the currently selected part is in the aformentioned set. For example, if an instance of this validator is defined with type definitions for types A, B and D. When a part of type A, B or D is selected, the validator will return true. If a part of any other type, e.g. C, is selected, it will return false. A <ValidatorDefinition> which would return true if the selected type is A, B or D would be defined in the following way:
<ValidatorDefinition id="com.my.IsEqualToOneOfTypesABDVAL" validatorClass="com.ptc.windchill.explorer.structureexplorer.va lidators.IsValidTypeValidator"> <Import id="com.my.MyTypeATD"/> <Import id="com.my.MyTypeBTD"/> <Import id="com.my.MyTypeDTD"/> </ValidatorDefinition>

Conversely, a <ValidatorDefinition> which would return false if the selected type is A, B or D would be defined in the following way (note the inclusion of the inverted attribute):
<ValidatorDefinition id="com.my.IsNotEqualToTypesABDVAL" validatorClass="com.ptc.windchill.explorer.structureexplorer.va lidators.IsValidTypeValidator" inverted="true"> <Import id="com.my.MyTypeATD"/> <Import id="com.my.MyTypeBTD"/> <Import id="com.my.MyTypeDTD"/> </ValidatorDefinition>

The <Import> elements refer to <TypeDefinition> elements which would be defined as follows (assuming that each type is a direct child of WTPart):
<TypeDefinition id="com.my.MyTypeATD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeA"/> <TypeDefinition id="com.my.MyTypeBTD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeB"/> <TypeDefinition id="com.my.MyTypeDTD" typeId="WCTYPE|wt.part.WTPart|org.my.MyTypeD"/>

18-50

Windchill Customizers Guide

Creating a Requirements Tab


This section contains instructions for displaying a Requirements tab in PSE. Following these instructions will create a Requirements tab which will be displayed in PSE and will only be enabled when a part of a specified type is selected in the structure tree. The tab will display the Requirement objects which are associated with the selected object and provide some operations for working with Requirements as well. This documentation describes changes to existing files. It is suggested that you create a separate customer file to contain all new elements created. The following instructions are provided: Updating the <TabSet> element to include the Requirements tab on page 18-51 Define a <Tab> element for the Requirements tab on page 18-52 Define the <AssociationTable> element for the Requirements tab on page 18-53 Define the <StructureAuthorDefinition> element for the association table on page 18-53 Define the <StructureDefinitionSimple> element for the part to requirement association on page 18-54 Define the <Table> element for the Requirement type on page 18-54 Define the menus for the Requirements tab on page 18-56 Define the labels, tool tips and mnemonics for the Requirements tab on page 18-59 Define <ActionDefinition> elements referred to in the <MenuItem> elements on page 18-60 Implement an 'enabled decider' class to control when the tab is enabled on page 18-62

Updating the <TabSet> element to include the Requirements tab


This will add a reference to a Requirements tab to the defined TabSet. 1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. Locate the <TabSet> element and add an import for the new Requirements tab, and place it in the desired location:
<TabSet id="ptc.pdm.pse.ExplorerTaskTabSet" tabPlacement="top" tabIdWithFocus="ptc.wnc.exp.PropertiesTab">

Customizing the Product Structure Explorer (PSE)

18-51

<Import <Import <Import <Import <Import <Import <Import <Import <Import </TabSet>

id="ptc.wnc.exp.PropertiesTab"/> id="ptc.wnc.exp.StructureChildrenTab"/> id="mycom.wnc.exp.RequirementsTab"/> id="ptc.wnc.exp.GpsParamTab"/> id="ptc.wnc.exp.GpsConstraintsTab"/> id="ptc.wnc.exp.ViewTab"/> id="ptc.wnc.exp.DocTab"/> id="ptc.wnc.exp.ReplacementsTab"/> id="ptc.wnc.exp.UsedByTab"/>

Define a <Tab> element for the Requirements tab


This will define the Requirements tab element. 1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. After the <TabSet> element, define a <Tab> element for the Requirements tab:
<TabSet id="ptc.pdm.pse.ExplorerTaskTabSet" ... > ... </TabSet> <Tab id="mycom.wnc.exp.RequirementsTab" tabClass="com.ptc.windchill.explorer.structureexplorer.explorer .tabs.ShowTablesTab" enabledDeciderClass="com.mycom.windchill.explorer.structureexpl orer.deciders.RequirementsEnabledDecider"> <Label imageName="wtcore/images/change_action.gif"> <Resource key="requirementsTabLabel"/> </Label> <Panel> <Import id="mycom.pdm.pse.RequirementAssocTable"/> </Panel> </Tab>

Note: The id attribute for the Tab element must match the id specified in the import sub-element of the <TabSet> element defined above. The class defined for the enabledDeciderClass attribute of the Tab element, controls what types this tab will be enabled for when parts are selected in the structure tree. This must be implemented by the customer. The imageName attribute of the <Label> sub-element defines the icon to display on the tab. The <Resource> sub-element of <Label> refers to the defined text label for the tab. The <Panel> element contains an import to the defined table to be displayed.

18-52

Windchill Customizers Guide

Define the <AssociationTable> element for the Requirements tab


This will define the AssociationTable element used by the Requirements tab. 1. Open the PDMLinkExplorerMain.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. After the <Tab> element definition for the Requirements tab, define the <AssociationTable> element.
<Tab id="mycom.wnc.exp.RequirementsTab" ... > ... </Tab> <AssociationTable id="mycom.pdm.pse.mycom.pdm.pse.RequirementAssocTable"> <Label> <Resource key="requirementsLabel"/> </Label> <Import id="mycom.wnc.exp.RequirementSAD"/> <Import id="mycom.wnc.exp.ChangeActionTabTable"/> <Import id="mycom.wnc.exp.ChangeActionAssocTableAA"/> </AssociationTable>

Note: The id attribute for the <AssociationTable> must match the id specified in the import sub-element of the <Tab> element defined above. The <Resource> sub-element of the <Label> element refers to the text label defined in the resource file to be used for the table.

Define the <StructureAuthorDefinition> element for the association table


This defines the StructureAuthorDefinition element used by the AssociationTable. 1. Open the ExplorerStructures.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/struct ureexplorer

2. Find the section in the file where the structure author definitions are defined. After the last <StructureAuthorDefinition> element, add the following definition for the Requirements:
<StructureAuthorDefinition id="mycom.wnc.exp.RequirementSAD"> <Import id="mycom.wnc.exp.PartToRequirementSD"/> </StructureAuthorDefinition>

Note:

Customizing the Product Structure Explorer (PSE)

18-53

The id attribute for the <StructureAuthorDefinition> must match the id specified in the import sub-element of the <AssociationTable> element defined above.

Define the <StructureDefinitionSimple> element for the part to requirement association


This defines the StructureDefinitionSimple element used by the StructureAuthorDefinition element. 1. Open the ExplorerStructures.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/struct ureexplorer

2. Find the section in the file where the structure definitions are defined. After the last <StructureDefinition> element, add the following definition:
<StructureDefinitionSimple id="mycom.wnc.exp.PartToRequirementSD" parentToChild="addressedPartMasterReference" childDisplayId="number"> <Import id="ptc.wnc.exp.WTPartTD"/> </StructureDefinitionSimple>

Note: The id attribute for the <StructureDefinitionSimple> must match the id specified in the import sub-element of the <StructureAuthorDefinition> element defined above.

Define the <Table> element for the Requirement type


This will define a table to display Requirements (Change Actions) associated with the selected part in the Structure Tree. The following data will be displayed in columns: The number of the Requirement The effectivity range of the Requirement The status of the Requirement The number of the ChangeDirective owning this requirement The identifier of the part which fulfills this Requirement The number of this Requirement's predecessor Requirement

To define the <Table> element for the Requirement type 1. Open the PDMLinkExplorerForTablesAndPanels.xml file from the following location:

18-54

Windchill Customizers Guide

<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. At the end of the file: a. Create the following <ExplorerElementGroup> as a sub-element of the <LogicRepository> element. b. Define a <LogicContext> sub-element of the <ExplorerElementGroup> with the data type of the Requirement. c. Define the <Table> element and the columns, <CellDefinition> elements, to be displayed in the table.
<LogicRepository> ... <ExplorerElementGroup> <LogicContext application="ptc.pdm.ProductStructureExplorer" dataType="wt.change2.ChangeAction"/>

<Table id="airbus.wnc.exp.ChangeActionTabTable" selectionMode="multi-non-contiguous" displayMode="view"> <CellDefinition id="number" mandatory="true" pinned="true"> <Label> <Resource key="reqNumberLabel"/> </Label> <AttributeDefinition attributeId="number"/> </CellDefinition> <CellDefinition id="effVector" mandatory="true"> <Label> <Resource key="reqValidityLabel"/> </Label> <AttributeDefinition attributeId="displayEffectivity"/> </CellDefinition> <CellDefinition id="theActionState" mandatory="true"> <Label> <Resource key="reqStatusLabel"/> </Label> <AttributeDefinition attributeId="theActionState"/> </CellDefinition> <CellDefinition id="owningChangeDirective" mandatory="true"> <Label> <Resource key="relatedCINLabel"/> </Label> <AttributeDefinition attributeId="MBA| owningChangeDirectiveReference^WCTYPE| wt.change2.WTChangeDirective~MBA|number" rendererClass="com.ptc.windchill.explorer.structureexplorer.ren derer.component.TypeIconifiedStringComponent"/> </CellDefinition> <CellDefinition id="satisfyPartMaster" mandatory="true">

Customizing the Product Structure Explorer (PSE)

18-55

<Label> <Resource key="fulfillingDSLabel"/> </Label> <AttributeDefinition attributeId="MBA| satisfyPartMasterReference^WCTYPE|wt.part.WTPartMaster~MBA| masterReference@WCTYPE|wt.part.WTPart~SCA|displayIdentifier" rendererClass="com.ptc.windchill.explorer.structureexplorer.ren derer.component.TypeIconifiedStringComponent"/> </CellDefinition> <CellDefinition id="oldActionReference" displayWhenNoPreferenceSet="false"> <Label> <Resource key="reqPredecessorLabel"/> </Label> <AttributeDefinition attributeId="MBA| oldActionReference^WCTYPE|wt.change2.ChangeAction~MBA|number" rendererClass="com.ptc.windchill.explorer.structureexplorer.ren derer.component.TypeIconifiedStringComponent"/> </CellDefinition> </Table> </ExplorerElementGroup> </LogicRepository>

Note: The dataType attribute of the <LogicContext> element defines the type of part which will be displayed in the table defined. The id attribute for the <Table> must match the id specified in the import subelement of the <AssociationTable> element defined above. The attributeId attribute of the <CellDefinition> element defines the qualified attribute data to be displayed in that cell. The rendererClass attribute of the <CellDefinition> element is optional and overrides the default renderer for the cell. The <Resource> sub-element of the <Label> element refers to the text label defined in the resource file to be used for column header.

Define the menus for the Requirements tab


This will define the menus and toolbar for the Requirements tab. A toolbar will be defined with the following structure: The standard Info button A Generate Requirements button. This button will trigger an action to generate requirements for the currently selected part in the structure. A Fulfill Requirement button. This button will present the user with a list of candidate parts from which to select and designate as fulfilling the currently selected Requirement.

18-56

Windchill Customizers Guide

A View Effectivity Log button. This button will open a browser window and display the effectivity log for the currently selected Requirement. The standard Revert button The standard Comment button The standard Revert button The standard Comment button

Popup menus are also defined for the table which contain menu items for the three new operations: Generate Requirements Fulfill Requirement View Effectivity Log

To define menus for the Requirements tab 1. Open the PDMLinkExplorerMenusForRequirementsTab.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. Add the following content to the file:


<?xml version="1.0" standalone="no" ?> <!DOCTYPE LogicRepository SYSTEM "/config/logicrepository/dtd/LogicRepository.dtd"> <LogicRepository> <ExplorerElementGroup> <LogicContext application="ptc.pdm.ProductStructureExplorer"/> <ActionAccess id="mycom.wnc.exp.ChangeActionAssocTableAA"> <MenuBar id="MenuBar"> <Menu id="Menu"> <Import id="ptc.wnc.exp.InfoPageAssocMI"/> <Separator/> <MenuItem id="GenerateReqsMI"> <Label imageName="com/ptc/windchill/explorer/config/images/child_creat e.gif"> <Resource key="generateReqsLabel"/> </Label> <ToolTip> <Resource key="generateReqsToolTip"/> </ToolTip> <Import id="mycom.wnc.exp.GenerateRequirementsAction"/> </MenuItem> <MenuItem id="FulfillReqMI">

Customizing the Product Structure Explorer (PSE)

18-57

<Label imageName="com/ptc/windchill/explorer/config/images/child_add.g if"> <Resource key="fulfillReqLabel"/> </Label> <ToolTip> <Resource key="fulfillReqToolTip"/> </ToolTip> <Import id="mycom.wnc.exp.FulfillRequirementAction"/> </MenuItem> <MenuItem id="ViewEffLogMI"> <Label imageName="com/ptc/windchill/explorer/config/images/child_repor t.gif"> <Resource key="viewEffLogLabel"/> </Label> <ToolTip> <Resource key="viewEffLogToolTip"/> </ToolTip> <Import id="mycom.wnc.exp.ViewEffectivityLogAction"/> </MenuItem> <Separator/> <MenuItem id="RevertMI"> <Label imageName="com/ptc/windchill/explorer/config/images/revert.gif" > <Resource key="revertLabel"/> </Label> <ToolTip> <Resource key="revertToolTip"/> </ToolTip> <Import id="ptc.wnc.exp.RevertForAltAssocAction"/> </MenuItem> <Import id="ptc.wnc.exp.CommentAssocMI"/> </Menu> </MenuBar> <ModeToolBar id="ToolBarA"> <Import id="ptc.wnc.exp.EditAppMode"/> <MenuItemIdentifier id="ptc.wnc.exp.InfoPageAssocMI"/> <Separator/> <MenuItemIdentifier id="GenerateReqsMI"/> <MenuItemIdentifier id="FulfillReqMI"/> <MenuItemIdentifier id="ViewEffLogMI"/> </ModeToolBar> <ModeToolBar id="ToolBarB"> <Import id="ptc.wnc.exp.DraftAppMode"/> <Import id="ptc.wnc.exp.AnnotateAppMode"/> <Import id="ptc.wnc.exp.ReadOnlyAppMode"/> <MenuItemIdentifier id="ptc.wnc.exp.InfoPageAssocMI"/> <Separator/>

18-58

Windchill Customizers Guide

<MenuItemIdentifier id="GenerateReqsMI"/> <MenuItemIdentifier id="FulfillReqMI"/> <MenuItemIdentifier id="ViewEffLogMI"/> <Separator/> <MenuItemIdentifier id="RevertMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CommentAssocMI"/> </ModeToolBar> <ModePopupMenu id="PopupMenuA"> <Import id="ptc.wnc.exp.EditAppMode"/> <MenuItemIdentifier id="GenerateReqsMI"/> <MenuItemIdentifier id="FulfillReqMI"/> <MenuItemIdentifier id="ViewEffLogMI"/> </ModePopupMenu> <ModePopupMenu id="PopupMenuB"> <Import id="ptc.wnc.exp.DraftAppMode"/> <Import id="ptc.wnc.exp.AnnotateAppMode"/> <MenuItemIdentifier id="GenerateReqsMI"/> <MenuItemIdentifier id="FulfillReqMI"/> <MenuItemIdentifier id="ViewEffLogMI"/> <Separator/> <MenuItemIdentifier id="RevertMI"/> <MenuItemIdentifier id="ptc.wnc.exp.CommentAssocMI"/> </ModePopupMenu> </ActionAccess> </ExplorerElementGroup> </LogicRepository>

Note: The id attribute for the <ActionAccess> element must match the id specified in the import sub-element of the <AssociationTable> element defined above. The <Resource> sub-element of the <Label> and <Tooltip> elements refers to the text label defined in the resource file to be used for column header.

Define the labels, tool tips and mnemonics for the Requirements tab
Define the text for the labels, tool tips and mnemonics used in the Requirements tab. 1. Open the ConfigurationResource.rbInfo file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. Add the following to the end of the file:


# # Tabbed Pane - Requirements #

Customizing the Product Structure Explorer (PSE)

18-59

requirementsTabLabel.value=Requirements # Change Item to Requirements table requirementsLabel.value=Requirements reqNumberLabel.value=Number reqValidityLabel.value=Effectivity reqStatusLabel.value=Status relatedCINLabel.value=Originating From fulfillingDSLabel.value=Fulfilled By reqPredecessorLabel.value=Predecessor generateReqsLabel.value=Generate Requirements generateReqsToolTip.value=Generate Requirements fulfillReqLabel.value=Fulfill Requirement fulfillReqToolTip.value=Fulfill Requirement viewEffLogLabel.value=View Effectivity Calculation Log viewEffLogToolTip.value=View Effectivity Calculation Log

Note: The property name defined in the file, e.g. <property name>.value, must match the key attribute of the <Resource> element in the XML configuration files.

Define <ActionDefinition> elements referred to in the <MenuItem> elements


These are instructions for presenting the actions on the Requirements tab in PSE. These instructions will provide an action to correspond with the menu and toolbar item entries for the Fulfill Requirement action defined in the customization instructions for setting up the Requirements Tab. 1. Open the PDMLinkExplorerActions.xml file from the following location:
<Windchill>/codebase/config/logicrepository/xml/explorer/produc tstructure

2. Locate the <ExplorerElementGroup> element with a sub-element <LogicContext> with the application attribute value of 'ptc.pdm.ProductStructureExplorer'. The ActionDefinition elements will be added after the LogicContext element. 3. Define the appropriate element using the steps found in the following sections.

Define the ActionDefinition Element for the Fulfill Requirements Action


This will define the Action Definition element for the Fulfill Requirements action. As detailed above, locate the <ExplorerElementGroup> element with a subelement <LogicContext> with the application attribute value of 'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an ActionDefinition element like the following:

18-60

Windchill Customizers Guide

<ActionDefinition id="mycom.wnc.exp.FulfillRequirementAction" actionClass="com.ptc.windchill.explorer.structureexplorer.panel .actions.FulfillChangeActionForStructureWithIntermediateNodeAct ion"> <StructureAuthorAction> <Import id="mycom.wnc.exp.PartToRequirementSD"/> </StructureAuthorAction> <Import id="ptc.wnc.exp.IsValidInAllWithReadVAL"/> </ActionDefinition>

Note: The id attribute defined in the <ActionDefinition> must match the import id defined for the FulfillReqMI menu item defined in PDMLinkExplorerMenusForRequirementsTab.xml. The actionClass attribute will be defined based on the node structure for Change Items and Design Solutions. If the set of Design Solutions are immediately under the Change Item node, then the following class should be specified: com.ptc.windchill.explorer.structureexplorer.panel.actions.FulfillChangeActi onAction. If the set of Design Solutions are located two levels down from their Change Item node, then the following class should be specified: com.ptc.windchill.explorer.structureexplorer.panel.actions.FulfillChangeActi onForStructureWithIntermediateNodeAction. The import id in the <StructureAuthorAction> element must match the id of the structure definition defined in the ExplorerStructures.xml file. All parts located at the level defined by the actionClass will be considered potential Design Solutions for fulfillment and presented to the user in a picklist.

Define the ActionDefinition Element for the Generate Change Actions Action
This will define the Action Definition element for the Generate Change Actions action. As detailed above, locate the <ExplorerElementGroup> element with a subelement <LogicContext> with the application attribute value of 'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an ActionDefinition element like the following:
<ActionDefinition id="mycom.wnc.exp.GenerateRequirementsAction" actionClass="com.ptc.windchill.explorer.structureexplorer.panel .actions.GenerateChangeActionsAction"> <Action/> <Import id="ptc.wnc.exp.IsValidInAllVAL"/> </ActionDefinition>

Customizing the Product Structure Explorer (PSE)

18-61

Note: The id attribute defined in the <ActionDefinition> must match the import id defined for the GenerateReqsMI menu item defined in PDMLinkExplorerMenusForRequirementsTab.xml.

Define the ActionDefinition Element for the View Effectivity Log Action
This will define the Action Definition element for the View Effectivity Log action. As detailed above, locate the <ExplorerElementGroup> element with a subelement <LogicContext> with the application attribute value of 'ptc.pdm.ProductStructureExplorer'. After the LogicContext element, add an ActionDefinition element like the following:
<ActionDefinition id="mycom.wnc.exp.ViewEffectivityLogAction" actionClass="com.ptc.windchill.explorer.structureexplorer.panel .actions.AssociationUrlAction"> <UrlAction selectionMode="single" urlBaseName="servlet/TypeBasedIncludeServlet?"> <UrlParameter value="oid={selected_oid}"/> </UrlAction> <Import id="ptc.wnc.exp.IsValidForHTMLLaunchMasterOkVAL"/> </ActionDefinition>

The id attribute defined in the <ActionDefinition> must match the import id defined for the ViewEffLogMI menu item defined in PDMLinkExplorerMenusForRequirementsTab.xml.

Implement an 'enabled decider' class to control when the tab is enabled


This creates a new class which will control when the Requirements tab is enabled and disabled. Only when a part is selected in the structure tree, which matches one of the types specified in the enabled decider class, will the Requirements tab be enabled and operational. 1. Create the RequirementsEnabledDecider.java file from the following location:
<Windchill>/codebase/com/mycom/windchill/explorer/structureexpl orer/deciders

2. Modify the following implementation as necessary: Modify the common_ancestry string so that it matches the parent type hierarchy of the parts for which you want to view Requirements. In the static code block, add an entry to the type_id_list for each part type which you want to view the Requirements

package com.mycom.windchill.explorer.structureexplorer.deciders; import java.util.ArrayList; import java.util.List;

18-62

Windchill Customizers Guide

import wt.services.applicationcontext.implementation.DefaultServicePro vider; import com.ptc.core.foundation.struct.common.StructureConstants; import com.ptc.core.meta.common.AssociationIdentifier; import com.ptc.core.meta.common.AssociationTypeIdentifier; import com.ptc.core.meta.common.AttributeTypeIdentifier; import com.ptc.core.meta.common.IdentifierFactory; import com.ptc.core.meta.common.TypeIdentifier; import com.ptc.core.meta.common.TypeInstanceIdentifier; import com.ptc.core.meta.type.common.TypeInstance; import com.ptc.windchill.explorer.structureexplorer.config.AbstractCon fig; import com.ptc.windchill.explorer.structureexplorer.deciders.EnabledDe cider; import com.ptc.windchill.explorer.structureexplorer.utility.CommonData ; public class RequirementsEnabledDecider implements EnabledDecider { private static IdentifierFactory identifierFactory = (IdentifierFactory) DefaultServiceProvider.getService(IdentifierFactory.class, "logical"); //$NON-NLS-1$ private static List<TypeIdentifier> type_id_list = new ArrayList<TypeIdentifier>(); private static String common_ancestry = "WCTYPE| wt.part.WTPart|com.mycom.MyPart|"; //$NON-NLS-1$ static { try { type_id_list.add( (TypeIdentifier)identifierFactory.get(common_ancestry + "com.mycom.CustomPartA")); //$NON-NLS-1$ type_id_list.add( (TypeIdentifier)identifierFactory.get(common_ancestry + "com.mycom.CustomPartB")); //$NON-NLS-1$ type_id_list.add( (TypeIdentifier)identifierFactory.get(common_ancestry + "com.mycom.CustomPartC")); //$NON-NLS-1$ type_id_list.add( (TypeIdentifier)identifierFactory.get(common_ancestry + "com.mycom.CustomPartD")); //$NON-NLS-1$ } catch(Exception e)

Customizing the Product Structure Explorer (PSE)

18-63

{ e.printStackTrace(); } }

public boolean isItemEnabled(TypeInstance node_ti, TypeInstance parent_node_ti, AbstractConfig item_config, CommonData common_data) { boolean enabled = true; if (node_ti != null) { enabled = isValidPart(node_ti); } return enabled; } /** * is this node a generic part or a configurable generic part? **/ public static boolean isValidPart(TypeInstance node_ti) { if (node_ti == null) { return false; } TypeInstanceIdentifier node_tii = (TypeInstanceIdentifier) node_ti.getIdentifier(); if (node_tii == null) { return false; } try { if (IsMastered(node_ti)) { return false; } TypeIdentifier type_id = trimTypeId((TypeIdentifier) node_tii.getDefinitionIdentifier()); for(TypeIdentifier spec_type_id : type_id_list) { if(type_id.isDescendedFrom(spec_type_id)) { return true; } } return false; } catch (Exception e)

18-64

Windchill Customizers Guide

{ return false; } }

/** * Assumes an iteration... * * isMastered is an unpersisted Iteration and a persisted Master. * @param ti * @return * */ private static boolean IsMastered(TypeInstance ti) { try { TypeInstanceIdentifier tii = (TypeInstanceIdentifier) ti.getIdentifier(); if (tii instanceof AssociationIdentifier) { tii = ((AssociationIdentifier) tii).getTail(); } if (!tii.isInitialized()) { AttributeTypeIdentifier master_ati = (AttributeTypeIdentifier) identifierFactory.get(StructureConstants.MASTER_REFERENCE_ID_ST R, tii.getDefinitionIdentifier()); Object object = ti.getSingle(master_ati); TypeInstanceIdentifier master_tii = null; if (object instanceof TypeInstanceIdentifier) { master_tii = (TypeInstanceIdentifier) object; } if (master_tii.isInitialized()) { return true; } } } catch (Exception ex) { return false; } return false; } private static TypeIdentifier trimTypeId(TypeIdentifier type_id) { if (type_id instanceof AssociationTypeIdentifier) {

Customizing the Product Structure Explorer (PSE)

18-65

return ((AssociationTypeIdentifier) type_id).getTail(); } return type_id; } }

18-66

Windchill Customizers Guide

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 Manager" chapter of the Windchill Business Administrators 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: %WT_HOME%/loadfiles/configurableLinks/ConfigurableLinkExamples/xml Note: The load file loads both the link types and the association constraints. %WT_HOME%/codebase/config/actions/ConfigurableLinkExamplesactionmodels.xml %WT_HOME%/codebase/config/actions/ConfigurableLinkExamplesactions.xml %WT_HOME%/codebase/com/ptc/windchill/enterprise/object/configurableLink ExamplesResource.class

The .rbinfo file ties the registry of the 3rd level navigation table to the link type that is implemented for the table, the table header, and the action title. %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExam ples.xconf %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExam ples-wt.properties.xconf

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 18-68 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:

Customizing the Product Structure Explorer (PSE)

18-67

xconfmanager -i %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLin kExamples.xconf -p

3. Restart your method server. 4. Load the loadfile:


windchill wt.load.LoadFromFile -d %WT_HOME%/loadfiles/configurableLinks/ConfigurableLinkExamples/ xml

Note: The actionmodels.xml file overrides the third-level navigation menus on the info page 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 %WT_HOME%/declarations.xconf file. 2. Remove the entry containing the string: "ConfigurableLinkExamples.xconf" 3. Save and close the %WT_HOME%/declarations.xconf file. 4. Open the %WT_HOME%/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 %WT_HOME%/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.

18-68

Windchill Customizers Guide

Customizing Configurable Link Tables


This sectiom 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 soft types and the relationship constraints for each link type. This is done in the ConfigurableLinkExamples.xml file. This file contains 2 sections: Configurable Link Soft Types: The first part defines the Configurable Link Soft Types. The name, description and Logical Identifier for each link type must be defined here. The nodeName that is defined here 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 following fields - nodeName, description, displayName, heirarchyDisplayName, and logicalIdentifier must be filled-in 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 soft types 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 nodeName that is defined in the Configurable Link Soft Type 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 dropdown menu. Clicking on an action will 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.

Customizing the Product Structure Explorer (PSE)

18-69

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 (see Creating labels for the table header and action title on page 18-71). 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 3rd level navigation. steps 3a and 3b describe how to create a model, and then display it. The end result is that the UI for the 3rd level navigation will have a new menu option. The drop-down for this 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 "configLinkExamples" in the OOTB example. The resourceBundle definition after the name is the location of the resource bundle that contains the key-value pairs of the display names (see Creating labels for the table header and action title on page 18-71).

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 intended 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 3rd level navigation of the info pages of objects that intend to display it. In this example, it is intended to be displayed from the part and document info pages. That is done by overriding the pre-existing definition for the 3rd level navigation for these 2 objects, and this is described below. b. Displaying the model

18-70

Windchill Customizers Guide

The model "third_level_nav_part" contains the list of 3rd level navigation menus available for parts. OOTB, this model is defined in PartManagementactionmodels.xml, and the menu options are "general", "relatedItems", "history", "collaboration". In order to add the newly created configLinkExamples 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 ("ConfigurableLinkExamplesactionmodels.xml" in this case). Then add the newly defined model ("configLinkExamples" 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 3rd level navigation menus of an info page 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 a key-value pair in an rbinfo file. In the OOTB example, this is done in the configurableLinkExamplesResource.rbinfo file. This file ties the registration of the 3rd level navigation table to the link type that is implemented for the table, the table header and the action title. The tieup for the link type is done in the moreurlinfo field. The value for this field has the configurableLinkType set to the value of the "nodeName" 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 %WT_HOME%/codebase/com/ptc/windchill/enterprise/object 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: %WT_HOME%/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

Customizing the Product Structure Explorer (PSE)

18-71

ConfigurableLinkChildTableActionValidator should be used respectively as the serviceClass. 6. 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 "configLinksExamples" submodel. It is important to perform Step 6 in such a way that these new files are added to the global definition after the OOTB definition. In this example, ConfigurableLinksExample-actionmodels.xml must be added after PartManagement-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 7) 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 6, or placed before the OOTB model definitions, then the OOTB behavior will be observed for the specific 3rd level navigation menus. 7. Collecting the registrations in Steps 5 and 6 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 and 6 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 18-67.

18-72

Windchill Customizers Guide

Defining Access Control Policy Rules for Configurable Links


After defining a Configurable Link Soft Type based on ConfigurableMastersLink, the access control policy rules for the configurable link soft type 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 soft types. 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 Administrator to add access policies for the ConfigurableMastersLink soft types. 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 soft types 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 soft types. 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 soft types of ConfigurableMastersLink.
<AccessControlRule> <domainName>/Default</domainName> <externalTypeId>wt.configurablelink.ConfigurableMastersLink</ex ternalTypeId> <lifecycleState>ALL</lifecycleState> <WTPrincipalReference isInternal="true"> <groupName>teamMembers</groupName> <groupType>teamMembers</groupType> </WTPrincipalReference>

Customizing the Product Structure Explorer (PSE)

18-73

<grantPermissionSet> <AccessPermissionSet> <permissionField name="READ"/> <permissionField name="MODIFY"/> <permissionField name="CREATE"/> <permissionField name="DELETE"/> </AccessPermissionSet> </grantPermissionSet> </AccessControlRule>

18-74

Windchill Customizers Guide

19
Customizing Windchill MPMLink

This chapter describes how to customize Windchill MPMLink. Topic Page

Customizing Windchill MPMLink Overview...................................................19-2 General Windchill MPMLink Customizations..................................................19-5 Customizing the Process Plan Explorer ............................................................19-7 Customizing the Manufacturing Product Structure Explorer..........................19-19

19-1

Customizing Windchill MPMLink Overview


Windchill MPMLink is an add-on module to Windchill PDMLink and all Windchill MPMLink explorers are built using the Product Structure Explorer (PSE) infrastructure. Many of the customizations that can be done to Windchill PDMLink, in particular customizations affecting the PSE, are propagated to Windchill MPMLink. For more information on customizing Windchill PDMLink and the PSE, refer to the relevant sections in this guide. Additionally, many aspects of the way Windchill MPMLink appears and behaves can be customized by using the Preferences Manager. Windchill MPMLink preferences are located in the Product Structure Explorer section of the Preferences Manager. Any changes made to the XML configuration changes are applied when the Method Server is restarted. To avoid having to restart the method server after each configuration change activate the following property using Windchill Shell:
xconfmanager -d com.ptc.windchill.explorer.monitorXmlConfigChanges=true -t codebase/wt.properties

This property will automatically rebuild the jar that contains all XML configurations. However you will need to restart your applet and clear you client Java cache. Any error in an XML file will prevent the jar from being built properly. To enable logging in the Method Server console add the following line to the file codebase\ WEB-INF\log4jMethodServer.properties.
log4j.logger.com.ptc.core.logic.LogicRepository=DEBUG

Note: When moving to new versions of Windchill, changes in the XML files will NOT be automatically migrated. Changes in these files should be clearly documented. See Setting Up a Directory Structure for Managing Customized Files and Text Tailoring in Chapter 5, "Managing Customizations" for more detailed recommendations.

19-2

Windchill Customizers Guide

XML Configuration Files


Windchill MPMLink configuration files are located in the following directory: codebase/config/logicrepository/xml/explorer The following table lists the main Windchill MPMLink Explorer configuration files. Additional configuration files pertaining to more specific customizations are listed in various sections in this chapter.
File Description

<explorer>Main.xml <explorer>Structures.xml

Defines the general application layout (tree, tabs) Defines the navigation model for the application (tree hierarchy, selection to tabs). Defines the actions. Defines what are the visible attributes in the tree, tables and on panels (wizards). Defines the attributes that appear in your search criteria as well as the ones to display in your search results. Defines the different menu items and their associated action. Defines the menus and toolbars. Defines the different validators. A validator is used to enable/disable (grayed/not grayed) an action or a user interface element.

<explorer>Action*.xml <explorer>TablesAndPanels.xml

<explorer>ForSearch.xml

<explorer>MenuItems.xml <explorer>Menus/MenusFor*.xml <explorer>Validators.xml

Tip: The following files are the default files recommended for customizing Windchill MPMLink. New customization files can be created provided these files use the same application ID: codebase\config\logicrepository\xml\explorer\customization

Customizing Windchill MPMLink

19-3

When creating customization files for a specific explorer it is recommended that you use the following locations: CustAssociativeBOMExplorerMain.xml: The default file for Manufacturing Product Structure Explorer customizations. You can use other files, but the application ID for all XML segments must be: ptc.cust.ProductStructureExplorer CustManufacturingStandardExplorerMain.xml: The default file for Manufacturing Standards Explorer customizations. You can use other files but the application ID for all XML segments must be: ptc.cust.StandardExplorer CustMfgResourceExplorerMain.xml: The default file for Manufacturing Resource Explorer customizations. You can use other files but the application ID for all XML segments must be: ptc.cust.ResourceExplorer CustProcessPlanExplorerMain.xml: The default file for Process Plan Explorer customizations. You can use other files but the application ID for all XML segments must be: ptc.cust.ProcessPlanExplorer

19-4

Windchill Customizers Guide

General Windchill MPMLink Customizations


The following customizations describe typical changes you may want to apply to Windchill MPMLink explorers.

Changing the Availability of Windchill MPMLink Explorers


When installed all Windchill MPMLink users have access to all explorers; Product Structure Explorer Manufacturing Product Structure Explorer Manufacturing Resource Explorer Manufacturing Standards Explorer Process Plan Explorer Manufacturing Gantt Explorer

In certain configurations you may want to limit access to an explorer. For example, so that only manufacturing users can have access to the Manufacturing Product Structure Explorer, with all other users having access to the Product Structure Explorer. To set this configuration at the Product or Library level navigate to the Team tab and click the configure actions for roles icon.

To set this configuration at the Site or Organization level; Create a profile for manufacturing users, using the Profile tab, Add the individual users you wish to give access to the explorer to that profile.

Changing Default Units of Measure


Windchill MPMLink objects are defined with a set of attributes for such things as time, cost and dimension. The default system of measurement is metric. To change this, for example to the US system, modify the following preference using the Preference Manager:
Attribute Handling > Measurement System

To change the default unit for an individual attribute, such as time, cost or dimension, use the Type and Attribute Manager.

Customizing Windchill MPMLink

19-5

To change the base unit of measurement for a given system, for example to change all times to minutes, use the Measurement System Manager tab.

To change the default unit for a given attribute use the Attribute Definition Manager tab. Navigate to the attribute you would like to change, and enter the new value in the Override field.

19-6

Windchill Customizers Guide

Customizing the Process Plan Explorer


Process plans are the detailed description of what needs to be done on the shop floor in order to produce, inspect, repair, or maintain a given part or assembly. They contain the operations to be performed, the order in which they must be done, the physical resources, plants and skills required, document references, text description, and time and cost requirements. Using Windchill MPMLink Process Plans you can define: The operations needed to carry out the manufacturing of a product. The sequences in which these operations are carried out. The time, costs, and constraints for each operation. The physical resources and skills required to carry out operations. The parts required to manufacture the product, as well as where and how they are used during the manufacturing process.

In Windchill MPMLink Process plans are also used to create shop-floor Work Instructions. Work instructions are the step by step instructions that are used on the shop floor when producing, inspecting, repairing or maintaining parts. A work instruction is a dynamically generated HTML document that combines process plan information (sequences, operations, part allocations, resource allocations, time, etc.) and all related documents such as drawings, images and 3D sessions with annotations.

Changing Units of Measure for Cumulated Time and Cost


The Cumulated Time and Cost function of the Process Plan Explorer does not use the Measurement System default units. To change the units for the time & cost roll-up, the following properties must be modified:
com.ptc.windchill.mpml.CumulatedTimeAndCostActionTimeUnit com.ptc.windchill.mpml.CumulatedTimeAndCostActionCostUnit

These properties can be located in the following location:


codebase/com/ptc/windchill/mpml/xconf/mpmlin.properties.xconf

The default values are min and $, respectively.

Customizing Work Instructions


The work instruction template installed with Windchill MPMLink can be customized to fit your needs. To customize work instructions you should have a basic knowledge of JSPs and Info*Engine.

Customizing Windchill MPMLink

19-7

Info*Engine tasks are used to gather the information that is to be displayed in the work instruction, while the JSPs are used to arrange and format the display of that information.:
Location Description

<WT_Home>codebase\netmarkets\jsp\ mpml <WT_Home>\tasks\com\ptc\windchill\ mpml\workinstructions <WT_Home>\codebase\com\ptc\ windchill\mpml\xconfs\ mpmlink.properties.xconf <WT_Home>codebase\ netmarkets/css/workInstructionStyles.css

Location of the JSPs used in work instructions. Location of the Info*Engine tasks used to collect work instruction data. Location of work instruction properties. Location of the work instruction style sheet. This file can be used to change the fonts used in work instructions, as well as the color of report titles.

JSPs Used in Work Instructions


The following table lists and describes the JSPs used to configure work instructions.
JSP Description

headerWorkInstruction.jsp

Creates the logo image shown in the top corner of the work instructions report. Right next to the logo, it creates a table showing information about the process plan for the operations shown in the report. At the far right, it creates the assembly table information for which this process plan was associated. Creates the configuration specification table used in the work instructions report. Three types of configuration specifications are valid for this report: standard, baseline, and effectivity. The values shown are the ones for the expansion criteria that were applied to the data when the work instructions report was launched.

configSpecWorkInstruction.jsp

19-8

Windchill Customizers Guide

JSP

Description

operationHeaderWorkInstruction .jsp

Displays the information created in the sequenceHeaderWorkInstruction.jsp in the left margin. Creates the label number of the operation or sub-operation and places it next to the sequence number. Below the label number, it creates a table showing the name, number, version, and short description of that operation. Creates the table below the operations header. It shows details of the operation, including work centers used, times and costs. Creates the tables with the operation long description, its associated parts, its allocated resources, and its associated documents. If the value of the Displayed column in the documents table is Yes, the associated document is a recognized image to be displayed in the work instructions panel on the left of these detail tables. Image files that can be shown in work instructions must end with an extension specified by the following property:
com.ptc.windchill.mpml.WorkInstruct ionIllustrationFileExtensionAllowed

operationDetailHeaderWorkInstr uction.jsp

operationDetailWorkInstruction. jsp

sequenceHeaderWorkInstruction .jsp

When operations are part of a sequence, this JSP creates links to the branching and return operations. If the operation is a suboperation of another operation, this JSP creates links to the parent operation. Creates the footer area shown at the end of each operation section. This displays the present state of the operation, its status, its inspection, when it was first created, who updated the operation last, and the last date and time of the update.

footerWorkInstruction.jsp

Customizing Windchill MPMLink

19-9

JSP

Description

coreWorkInstruction.jsp

The core JSP that constructs the work instructions report. Processes the URL parameters and calls the Info*Engine tasks used to gather the data related to the operations found in a process plan. If the JSP is launched from a process plan, it calls
processPlanLogicWorkInstruction.jsp

If launched from an operation it calls


operationLogicWorkInstruction.jsp

This JSP also computes the parent and child relationship between operations, and the sequence branching and return operations. For each operation, it will call the JSPs that create the tables and displays the data returned by the Info*Engine tasks. operationLogicWorkInstruction.j sp Launches Info*Engine tasks that find all operations and standard procedures under an operation. Operations are sorted by operation label number. This JSP does not display items in the report. Launches Info*Engine tasks that find all operations, sequences, and standard procedures under an operation. The operations found are sorted by operation label number. This JSP does not display items in the report.

processPlanLogicWorkInstructio n.jsp

19-10

Windchill Customizers Guide

Info*Engine Tasks Used in Work Instructions


The following table lists and describes the Info*Engine tasks used to gather the data used in work instructions.
Info*Engine Task Description

describeAttributes.xml

Each webject in this task creates a group where the values of the attributes are localized. These localized values are then displayed in the work instructions report. The webjects in this task query an operation for the data that is displayed in the work instructions report. The following data sets are collected: work center, process, parts, manufacturing capabilities, resources, and documents. Each set of data is stored in an Info*Engine group. The webjects in this task create a group containing all the first depth sub-operations and standard procedures found under a particular operation. The webjects in this task create a group containing information on the assembly associated to the process plan.

getOperationData.xml

getOperationsAndStProcedur esUnderAnOperation.xml

getProcessPlanAndAssembly Information.xml

Customizing Windchill MPMLink

19-11

Info*Engine Task

Description

getSequencesAndStProcedure sUnderAProcessPlan.xml

The webjects in this task create a group containing all the first depth sequences and standard procedures found under a process plan. The webjects in this task create a group containing the sub-operations and standard procedures found under a particular operation. It also sorts the operations and standard procedures in each level. Currently, the algorithm is not recursive; it goes up to a depth of 3 levels. That is, it will only find 3 levels of sub-operations and then stop regardless if there are more sub-operations. To get to deeper levels, follow the pattern applied in this task and add more levels accordingly. The webjects in this task create a group containing the sub-sequences and standard procedures found under a particular sequence. It also sorts the sequences and standard procedures in each level. Currently, the algorithm is not recursive; it goes up to a depth of 3 levels. That is, it will only find 3 levels of sub-sequences and then stop regardless if there are more sub-sequences. To get to deeper levels, follow the pattern applied in this task and add more levels accordingly.

sortingOperations.xml

sortingSequences.xml

Work Instruction Properties


The following table lists and describes the properties used to configure work instructions.
Property Description

com.ptc.windchill.mpml.WorkInstruc tionIllustrationNamePattern

Pattern that defines which representations should be displayed in work instructions. The name of the ProductView representations meant to be displayed in work instructions must start with the pattern specified in this property. The default is wi_illustration.

19-12

Windchill Customizers Guide

Property

Description

com.ptc.windchill.mpml.WorkInstruc tionIllustrationPpValue

Property used in the URL of work instructions when the process plan OID is not available. The default is Value_Not_Considered. Date format used in the effectivity configuration specification. The default is mm/dd/yyyy. Configures the list of image extension types that can be seen in work instructions. The default is .jpeg,.png,.tif,.gif,.bmp,.jpg

com.ptc.windchill.mpml.WorkInstruc tionEffectivityDateFormat com.ptc.windchill.mpml.WorkInstruc tionIllustrationFileExtensionAllowed

Customizing Windchill MPMLink

19-13

Work Instruction Customizations


Work instructions can be customized for a number of reasons, including to replace the header and logo with your own information, or to provide simpler work instructions. The following table lists some common work instruction customizations.
Customizations Description

To change the time units of an operation:

Modify the following JSP:


timeUnit in coreWorkInstruction.jsp

For example, to change from seconds to minutes, change to m. To change the time units for the steps in an operation: Modify the following JSPs, as required:
setupTimeUnit processingTimeUnit laborTimeUnit queueTimeUnit, teardownTimeUnit, waitTimeUnit, moveTimeUnit

For example, to change from seconds to minutes, change to m. To relocate a table in the work instruction: Navigate to the end of the following JSP:
coreWorkInstruction.jsp

Then re-design the HTML display.

19-14

Windchill Customizers Guide

Customizations

Description

To display the processing cost of an operation in a work instruction:

Navigate to the following tasks: getOperationsAndStProceduresUnde rAnOperation.xml sortingOperations.xml

Add the following attribute to the above tasks:


MPM_Attr_MPMOperationProcessing Cost

Then create the column and display data in the following JSP:
operationDetailHeaderWorkInstru ction.jsp

To change the font, size, or color of the titles in a work instruction:

Modify the following CSS file and the JSPs that use the definitions in the CSS file:
workInstructionStyles.css

To change the logo at the top of the work instruction, or in the operation table:

Use the following procedure:


xconfmanager -d com.ptc.windchill.mpml.WorkInst ructionLogo=<logo> -t codebase/wt.properties

where <logo> is the full path to the logo .gif file found in the following folder: codebase\netmarkets\jsp\mpml. The default value is: ../../images/ptcLogo_workInstructions .gif corresponding to folder codebase\ netmarkets\images To add an image extension type: Add the extension type to the following property:
com.ptc.windchill.mpml.WorkInst ructionIllustrationFileExtensio nAllowed

To re-arrange, remove, or add new tables:

Modify the following JSP:


coreWorkInstructions.jsp

Customizing Windchill MPMLink

19-15

Customizing a Windchill MPMLink Explorer


Use the following procedures to customize Windchill MPMLink Explorers. This procedure introduces new XML fragments that modify the default behavior of an explorer.

Adding Custom Attributes to a Creation Wizard


Use the following procedure to add additional attributes to a creation wizard, such as the Insert New Operation wizard: 1. Navigate to the following directory:
codebase\config\logicrepository\xml\explorer\customization

2. Edit the following file:


CustProcessPlanExplorerMain.xml

3. Add the following XML fragments: Note: In this example inspectionNeeded and inspectionInterval are the attributes that are being added to the Insert New Operation wizard. Modify the code to suit the wizard you would like to customize, and to add your own customized attributes.

<ExplorerElementGroup> <LogicContext application="ptc.cust.ProcessPlanExplorer"

19-16

Windchill Customizers Guide

dataType="com.ptc.windchill.mpml.processplan.operation.MPMOpera tion"/> <AttributeGroup id="ptc.mpm.exp.CreateTab2" scrollable="true" displayMode="edit"> <CellDefinition id="inspectionNeeded"> <Label> <Resource key="inspectionNeededLabel"/> </Label> <AttributeDefinition attributeId="inspectionNeeded"/> </CellDefinition> <CellDefinition id="inspectionInterval"> <Label> <Resource key="inspectionIntervalLabel"/> </Label> <AttributeDefinition attributeId="inspectionInterval"/> </CellDefinition> </AttributeGroup> </ExplorerElementGroup>

4. Clear your Java cache and restart the Process Plan Explorer. In this example note that: The application ID used for this XML fragment is ptc.cust.ProcessPlanExplorer. This is the one recommended application ID for customizing the Process Plan Explorer. The default second creation wizard for the MPMOperation object, ptc.mpm.exp.CreateTab2, is defined in: codebase\config\logicrepository\xml\explorer\mpmexplorer\ MPMExplorerForTablesAndPanels.xml. To add more attributes to the same creation wizard, the same AttributeGroup ID, ptc.mpm.exp.CreateTab2, must be used. Only the cell definitions for the new attributes are added in this XML segment.

Tip: By default cell definitions need to be added after the default cell definitions. To specify a different location use the Placement tag.
<Placement insertKey="after|before" insertId="attributeName"replace="true|false"/>

For example:
<CellDefinition id="inspectionNeeded"> <Label> <Resource key="inspectionNeededLabel"/> </Label> <AttributeDefinition attributeId="inspectionNeeded"/> <Placement insertKey="after" insertId="folder"/>

Customizing Windchill MPMLink

19-17

</CellDefinition>

Note: Folder is the ID of the attribute after which the inspectionNeeded attribute is added.

Changing Operation Numbering


Windchill MPMLink numbers operations in sequential increments of 10. For example operation 10, operation 20, and so on. However, you may wish to configure your operations so that automatically increment by a different numbering scheme. To change the numbering scheme modify the following properties: wt.operationLabelIncrement wt.operationLabelNumberOfCharacters

For example, to have operation labels with three characters and which are increased by 5 (005, 010), put the following in site.xconf, and then run xconfmanager -pF: <Property name="wt.operationLabelIncrement" overridable="true" targetFile="codebase/wt.properties" value="5"/> <Property name="wt.operationLabelNumberOfCharacters" overridable="true" targetFile="codebase/wt.properties" value="3"/>

19-18

Windchill Customizers Guide

Customizing the Manufacturing Product Structure Explorer


The primary deliverables for a design engineer are product specifications and an engineering bill of materials (eBOM), typically accompanied by 3D digital mockups. These specifications, along with the eBOM, outline the initial design concepts for a product. Using the eBOM and the digital mock-ups, manufacturing engineers establish strategies on how to build a product that satisfies these engineering specifications. Manufacturing engineers re-organize and re-structure the eBOM into a manufacturing bill of materials (mBOM) that outlines the product from a manufacturing process and strategy point of view. Use the Manufacturing Product Structure Explorer to define manufacturing product structures. The Manufacturing Product Structure Explorer is also used to manage manufacturing parts, and the associations between different BOMs, when transforming an engineering bill of materials into a manufacturing bill of materials, and to manage the associations between parts and process plans.

Customizing the Transforming of an eBOM into an mBOM


Transforming an engineering bill of materials (eBOM) into a manufacturing bill of materials (mBOM) is a key component of the manufacturing process. Typically the as-designed, or engineering view of how a product is manufactured differs from the as-planned, or manufacturing view of how the product is actually built. Windchill MPMLink allows both design and manufacturing engineers to not only modify their respective bill of materials, but to maintain links between the two. This ensures that any changes made to the design of a product are immediately communicated to the manufacturing engineers, and the impact of such changes are immediately known.

Copying Part Attributes from the eBOM to the mBOM


When transforming an eBOM into an mBOM it is possible to customize Windchill MPMLink so that the attributes, soft type attributes (IBAs) and associations of the eBOM part are automatically copied over to the mBOM part when performing a BOM transformation. This scenario could arise when; Copying the attributes from an upstream part master to a downstream child part master; Copying the attributes and associations from an upstream iteration of a part to a downstream part.

Tip: For more information and examples refer to the comments in the property file.

Customizing Windchill MPMLink

19-19

Use the following procedure to copy part attributes from the eBOM to the mBOM: 1. Navigate to the following directory:
\codebase\com\ptc\windchill\mpml\xconfs\ mpmlink.properties.xconfs

2. Search for the following property:


com.ptc.windchill.mpml.copyOver

3. Update the property as in the following example:


<Property name="com.ptc.windchill.mpml.copyOver.<create or update>.wt.part.WTPartMaster" default="WCTYPE|wt.part.<WTPart or WTPartMaster>~MBA|<attribute>"/>

Where: <create or update> defines whether part attributes are copied over at the creation of the equivalent link for the downstream part (create), or when the equivalent link of the downstream part is updated (update). If <create> is used alone there is no synchronization between the upstream and downstream parts. To create a scenario where upstream and downstream parts are synchronized update the property to include both <create> and <update> options. <WTPart or WTPartMaster> defines whether the copied attributes are from the upstream iteration of the part (WTPart) or from the upstream part master (WTPartMaster). <attribute> is the attribute to be copied over during BOM transformation.

Tip: To keep the copied attributes specific to a product update the property must include the product library container. For example:
<Property name="com.ptc.windchill.mpml.copyOver.<create or update>.wt.part.WTPartMaster.<PDMLinkProduct.Product1>" default="WCTYPE|wt.part.<WTPart or WTPartMaster>~MBA| defaultUnit"/>

Where:

<PDMLinkProduct.Product1> is the name of the product container.

Note: To copy over multiple soft attributes, or attributes that are sub-classes of other attributes, you must include the full path to the attributes you want to copy over, using the delimiter specified in the following property:
<Property name="com.ptc.windchill.mpml.copyOverDelimeter" default=","/>

19-20

Windchill Customizers Guide

Defining Rules for the Add Children from Upstream BOM Window
When transforming an eBOM into an mBOM using the paste with associative links preference the following window appears:

Windchill MPMLink can be customized so that this window is automatically populated with certain options if a predefined set of rules has been met. This is done using a Windchill MPMLink delegate. For example, Windchill MPMLink is configured by default to populate the Add Options field with Add Selected Part if the copied upstream part has a Source value defined as Buy. Use the following procedure to change this behavior, or to add additional customizations: 1. Navigate to the following directory:
\codebase\com\ptc\windchill\mpml\xconfs\ mpmlink.properties.xconfs

2. Search for the following property:


mpmlink.typedservices.properties.xconf

3. Search for:
<Option cardinality="singleton" requestor="WCTYPE| wt.associativity.EquivalenceLink" serviceClass="com.ptc.windchill.mpml.MPMCopyOverEquivalenceLink Delegate"/>

4. Substitute "com.ptc.windchill.mpml.MPMCopyOverEquivalenceLinkDelegate" with the name of the class that implements the new behavior. Or modify the class itself to change the behavior.

Customizing Windchill MPMLink

19-21

19-22

Windchill Customizers Guide

20
Customizing Search Functionality

This chapter describes how to customize various aspects of the search functionality. Topic Page

Adding a Search Component.............................................................................20-2 Searching for Soft Types and Attributes ...........................................................20-6 Adding Attributes to the Search Pages..............................................................20-7 The SearchableAttributes.properties File ..........................................................20-8 Adding Actions to the Search Results Table.....................................................20-9 Changing the Layout of the Search Page ........................................................20-10 Adding a New Type to the Search User Interface...........................................20-11 Customizing the Layout of the Search Results Page.......................................20-12 Adding Different Formats for Exporting Search Results................................20-14 Customizing Index Search Capabilities ..........................................................20-15 Customizing Indexing Behavior......................................................................20-19 Windchill Client Architecture Search Customization .....................................20-24 Loading an OOTB Saved Query .....................................................................20-30 Search Elements and Associated JSPs ............................................................20-42

20-1

Adding a Search Component


Introduction
The common search component allows a developer to create a search component that can be used anywhere within any Windchill product. A unique componentId is associated with each search component; it is used to define the types that can be searched for within that search component, as well as the container types that a search can be constrained within. For example, the following entries (in SearchableTypes.properties; see below) would define a search component with a componentId of PDMLink.exampleSearch within the Windchill PDMLink solution. This search component will search for Change Issues and Change Requests, constraining its searches within Libraries and Products.
PDMLink.exampleSearch.0=wt.change2.WTChangeIssue PDMLink.exampleSearch.1=wt.change2.WTChangeRequest2 PDMLink.exampleSearch.containerType.0=wt.inf.library.WTLibrary PDMLink.exampleSearch.containerType.1=wt.pdmlink.PDMLinkProduct

The following sections describe how to define a search component, then how to use it.

Defining a Search Component


Search components are defined in the following properties file:
<Windchill>/codebase/com/ptc/windchill/enterprise/search/server /SearchableTypes.properties

Out of the box, this file contains search component definitions that can be used as a guide for creating a new one. The first part of the search component definition is the Windchill solution with which the component is associated. This part can have one of the following five valid entries: Foundation WindchillPDM PDMLink ProjectLink ProI

These values are linked to the entries in <Windchill>/codebase/installed.properties that define the solutions that are installed on your system. If a component is defined with a solution that is not currently installed, it will not work as expected.

20-2

Windchill Customizers Guide

The second part of the search component definition is a unique key that you assign to it. This key is used to determine the object types and container types that will be used within this search component. An example provided with Windchill is the Foundation Container Search functionality. The Foundation Container Search functionality is an out-of-the-box search component that is used in Windchill PDMLink and Windchill ProjectLink to search for container type objects. The definition for this search component follows:
Foundation.containerSearch.0=wt.projmgmt.admin.Project2 Foundation.containerSearch.1=wt.pdmlink.PDMLinkProduct Foundation.containerSearch.2=wt.inf.library.WTLibrary

The value Foundation indicates that this search component can be used with any Windchill solution that is installed, because Foundation (i.e., Windchill Services) is installed with every Windchill solution. The value containerSearch is the key assigned to the component. Each object type is given a unique sequential numerical value as well.

You can also define for a search component the container types to which the search should be constrained. An example provided with Windchill is the sandbox1 picker constraints that are defined for Windchill ProjectLink as follows:
# Open Sandbox picker container constraints for use in ProjectLink ProjectLink.openSandboxConstraint.containerType.0= wt.inf.library.WTLibrary ProjectLink.openSandboxConstraint.containerType.1= wt.pdmlink.PDMLinkProduct

These definitions are almost identical to the definitions for the object picker, except for the addition of the containerType keyword to indicate the type of entry.

1.

The term sandbox is used in code and programmer documentation to refer to the functionality that allows you to make PDM data from a PDM environment (that is, Windchill Foundation & PDM or Windchill PDMLink) available to a project, and vice versa.

Customizing Search Functionality

20-3

Using a Component
Once a component has been defined, it can be used as a picker. This can be done by calling the CommonSearchPicker.jsp page. The following query parameters can be used to modify the picker display and functionality: selectorType Specifies the type of selector used in the search results (for example, multi, single, or none). The default is multi (meaning that 1 or many objects can be selected in the search results table). componentId This parameter has two functions: To pass multiple object types that are designated as the "searchable types" that are available through this search picker, that is, the types that can be targeted by a search through this picker. To pass multiple container types to constrain a search (that is, to do a query for all of the objects in a specific set of container types).

The specified types and container types are configured for the search component using the SearchableTypes.properties file as described above. The componentId parameter is not required. If no componentId is specified, the aggregate list of searchable types for component name "allSearch" for all installed solutions is returned. The same behavior is true for container types. objectType Specifies the object type that the picker initially selects as the object type to search for (for example, wt.part.WTPart). This parameter is not required. If objectType is not passed, the search targets all of the searchable types that are available through this search picker (see the description of the componentId parameter above). In this case, the picker displays "All Item Types" in the Search For: field. It also presents a Find... button that enables the user to select a particular object type for the search. containerRef Specifies a container; the search component is then constrained to search within that container. The value is an OBID of the container. containerType Specifies a container type to which a picker is constrained. You can specify a container type in two ways: To pass a single container type, use the CONTAINER_TYPE SearchObjects Webject parameter. To pass 1 or more container types, add entries to the following properties file:

20-4

Windchill Customizers Guide

<Windchill>/codebase/com/ptc/windchill/enterprise/search/server/Searc hableTypes.properties This allows you to specify multiple container types based on a componentId passed through the Search-Objects Webject. If both a containerType and a componentId are passed, the value passed through the CONTAINER_TYPE parameter overrides the list of container types defined for the componentId. The following is a sample definition:
Foundation.allSearch.containerType.0= wt.inf.container.ExchangeContainer

In this example, Foundation.allSearch is the componentId value, and containerType is required to differentiate between a type and a container type. This allows the same componentId to be used to define a set of types and container types. frameTitleLabel The label that will be shown at the top of the search component. This is usually used to convey the purpose of the picker. showObjectTypeNonEditable Set this parameter to false to cause the picker to provide the Find... button along with the object type. This allows the user to change the object type for the search. This parameter is not required. If this parameter is not passed and objectType is passed, then the picker shows the object type as a text field with no Find... button. base_where_clause This parameter accepts a valid WHERE clause enclosed in braces. To determine the effective WHERE clause for the search, the picker will use AND and this WHERE clause with the search WHERE clause generated from input fields. This parameter is not required. showUserType Specifies whether active and/or deleted users will be displayed. Valid values are ActiveOnly, DeletedOnly, and ActiveAndDeleted. The default is ActiveOnly. Note: If a containerType and a componentId are passed for the container type list functionality, the container type is used and the componentId is ignored. Also, for container types, if a combination of object type and componentId, but no container type are passed, the container types are resolved using the componentId.

Customizing Search Functionality

20-5

Searching for Soft Types and Attributes


Note: This section applies only to Windchill PDMLink and Windchill ProjectLink. This functionality does not apply to Windchill Foundation & PDM. The following subsections describe how search capabilities work for site-defined types and attributes created using the Type Manager. For further information about the Type Manager, see the Windchill Business Administrators Guide. In this discussion, types and attributes created using the Type Manager are called soft types and soft attributes to distinguish them from site-defined types and attributes that may have been modeled.

Soft Types in Searches


The first time the object type picker is launched from the Advanced Search page after a soft type has been created, the new type is automatically available for selection. To select the new type, the user must expand the parent type by clicking on the arrow next to the parent type. When a new soft type is created, there is no need to create additional DCA configuration specifications for the new type because DCA picks up the configuration fragments from the parent types. However, DCA configuration specifications can be added in the context of the new type to override any DCA elements from the parent types. Soft types can be created at different levels of the organization, at the site and organization levels. The soft types shown depend on where the Search page was launched and the user who launched it. To add the soft type at the root level add a type entry into searchableTypes.properties. The following example demonstrates the proper formatting for the entry:
Foundation.edaCompare.2=WCTYPE|wt.part.WTPart|com.mycompany.myPart

Soft Attributes in Searches


Note: In order to use a soft attribute in searches, you must assign a Logical Identifier to it while creating it in the Attribute Definition Manager. Soft attributes are only visible on the advanced search page. If an object type contains any soft attributes they will appear in the "Criteria" pulldown list along with the modeled attributes for that type.

Soft Attributes in Search Results Table


To show the soft attributes in the search results table you should add DCA configurations specific to the newly created soft type.

20-6

Windchill Customizers Guide

Adding Attributes to the Search Pages


Adding Attributes to Advanced Search Page
Additional search attributes should only be added to the "Criteria" pulldown.

Adding Attributes to "Criteria" pulldown


The attributes that are available within the "Criteria" pulldown are defined in the following properties file: <Windchill>/codebase/com/ptc/windchill/enterprise/search/server/Searchabl eAttributesByType.properties. Note: Only modeled attributes are defined in this properties file, all soft attributes are retrieved by default. To add attributes for a particular type, simply add the logical attribute name to the comma separated list for that type. The logical attribute name is the attribute retrieved from introspection or defined within the <Windchill>/codebase/LogicalAttributes.xml file. For example, if we were to add "partType" to wt.part.WTPart, it would look like this:
advancedSearch.wt.part.WTPart=folderingInfo.cabinet,thePersistInfo.createStamp,iter ationInfo.creator,defaultUnit,lock.locker,name,number,ownership.owner,source,state. state,thePersistInfo.modifyStamp,iterationInfo.modifier,view.id,organizationReferen ce,partType

Customizing Search Functionality

20-7

The SearchableAttributes.properties File


The query layer supports searches against multiple types in a single query for both modeled types and soft types, and their attributes. The means for specifying what attributes and types are to be queried against is the com.ptc.core.query.common.ResultSpec class. If only one type is defined, that type is used as context to specify the AttributeTypeIdentifiers for the ResultSpec (for example, WCTYPE| wt.part.WTPart~MBA|masterReference^WCTYPE|wt.part.WTPartMaster~MBA| name). If more than one type is defined, wt.fc.Persistable is used as the default context for AttributeTypeIdentifiers in the ResultSpec (for example, WCTYPE| wt.fc.Persistable~MBA|name) Additionally, the query layer expects each AttributeTypeIdentifier with a wt.fc.Persistable context to have the correct AttributeTypeIdentifier type, e.g., ModeledAttributeTypeIdentifier, NonPersistedAssociationTypeIdentifier (see the com.ptc.core.meta.common and com.ptc.core.meta.common.impl package entries in your installed Windchill Javadoc for more information). Specifying a context of wt.fc.Persistable and an attribute name is not enough information to determine what type of AttributeTypeIdentifier to create. Currently, search functionality against multiple types is the only part of the product that uses this query functionality. Therefore, the following property file was created to provide a means for determining what type of AttributeTypeIdentifier should be created, given a wt.fc.Persistable context and an attribute name: <Windchill>/codebase/com/ptc/windchill/enterprise/search/server/Searchabl eAttributes.properties You can add entries to SearchableAttributes.properties for attributes that should be used in searches against multiple types. Entries are not needed for attributes that will be used in searches against a single type. See the SearchableAttributes.properties file for examples of entries and further information.

20-8

Windchill Customizers Guide

Adding Actions to the Search Results Table


Adding Table Actions
Table actions are the actions that appear at the top of the search results table in the table header. There are two types of table actions, actions that require objects to be selected and actions that don't require any objects to be selected.

Object Selection Actions


These are the first set of actions in the table header with the darker background color. These actions require one or more objects from the table to be selected, by using the checkboxes or radio buttons along the right side of the table, before the action can be executed. These actions are defined in <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/CommonSearch.xml in the "elementGroup.tableSelectionActions" group.

Table Actions That Require No Object Selection


These are the second set of actions in the table header with the lighter background color. These actions can be executed without any objects being selected. They are also defined in <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/CommonSearch.xml, in the "elementGroup.tableActions" group.

Row Level Actions


Please refer to Action Models in the JSP Framework in the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-1 for adding actions to the "See Actions" dialog that appears in each row of the search results table.

Customizing Search Functionality

20-9

Changing the Layout of the Search Page


The search page has been modified at this release to take advantage of common DCA elements known as DCA patterns. One of the DCA patterns is the search pattern. The search pattern defines the basic layout of the search page; it defines the search criteria panel as the top element and the search results table is the bottom element. The search criteria element further defines the key elements that make it up. The pattern also defines the components that are common to all the different search pages, components such as the search action and the object type picker. Most of the components that are initially defined in the search pattern can be overridden. Note: When customizing DCA applications, it is advised not to make changes directly to the out-of-the-box DCA configurations files that are under <Windchill>/conf/dca/com/ptc/. The content of these files are subject to change during the maintenance lifecycle of the release. See the Windchill DCA Client Technology Guide for further information. The main Search page and the Advanced Search page are derived from the search pattern by overriding some of the components. Components that are common to both the main Search page and the Advanced Search page are defined within CommonSearch.xml. The components that are specific to those individual search pages are defined within SimpleSearch.xml and AdvancedSearch.xml, respectively. The search criteria layout for each search page is defined within the appropriate DCA configuration file by overriding the element "elementGroup.layoutRows.searchPattern.searchCriteria".

20-10

Windchill Customizers Guide

Adding a New Type to the Search User Interface


The site-defined preference, /com/ptc/windchill/enterprise/search/allSearchTypes, determines the list of types that are to be included when a user searches across "all" item types. This is the same list that a user can choose from within the Item Type picker for the Customize link on the Search page, and the Search For link on the Advanced Search page. The allSearchTypes preference defines a base list of types; out-of-the-box searching rules include all soft types defined from one of these types. It does not, however, include any modeled subclasses. Any new modeled object type should be defined in the allSearchTypes preference to make it available for searches. By default, the allSearchTypes site preference is overrideable and can be modified by any of the Organizations in the system. While this preference can be overridden at the Library, Project or PDMLinkProduct level, the search UI does not support the listing of these types at that level. Only preferences defined at the Organization context or the Site context will be used in the search UI. The SearchableTypes.properties file defines the list of item types that may be loaded into the allSearchTypes preference upon MethodServer startup. As defined within this file, the list of types will depend on the particular combination of Windchill solutions that are found to be installed at the startup of the method server. The types are loaded into allSearchTypes if either or both of the following conditions hold: the allSearchTypes preference is currently not defined, the property com.ptc.windchill.search.refreshTypesFromProperties is set to true in wt.properties. By default, this property is not included in the wt.properties file. When needed, use xconfmanager to define it and set it to true. If neither condition holds (i.e., if allSearchTypes is already defined and refreshTypesFromProperties is false), then allSearchTypes is not reloaded. Caution: When the types are loaded, the allSearchTypes preference is completely reloaded according to the contents of the SearchableTypes.properties file; any previous overrides are ignored and will be lost. In particular, modeled types that were added to allSearchTypes since the previous loading will need to be re-entered.

Customizing Search Functionality

20-11

Customizing the Layout of the Search Results Page


This section provides an example of customizing the search results page. The goal in this example is to swap the search results table with the search criteria, so that the results appear before the criteria. The first two steps below are required in order to properly set the number of results per page when the results appear before the criteria. Refer to the Windchill Client Technology Guide for details on configuring actions and tables. 1. In <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/action.xml i. Locate the element <Action activationKey="\u000D" id="action.search">

ii. Modify the search action executeActionDoer event, adding a new Copy element (shown in bold below) as follows:
<On at="end" event="executeActionDoer"> <if condition="%[frame#SavedQueryWhereClause]!="> <Copy from="true" to="%[bean#compositeTable.searchResults.%[context#type]#Dirty]"/> </if> <Copy from="%[request#where_clause]" to="%[frame#compositeTable.searchResults.%[context#type].where_clause]"/> <Copy from="%[attribute#propertyPanel.searchCriteria#memberOfContainer]" to="%[frame#com.ptc.windchill.enterprise.search.memberOfContainerParam]"/> <Copy from="%[attribute#propertyPanel.searchCriteria#adhocPageCount]" to="%[frame#adhocPageCount]"/> <Copy from="true" to="%[frame#com.ptc.windchill.enterprise.search.AdvancedSearchQuery]"/> <Remove to="%[frame#compositeTable.searchResults.%[context#type].paging_session_id]"/> <Remove to="%[frame#compositeTable.searchResults.%[context#type].page_offset]"/> <if condition="%[context#isPicker]!=true"> <Copy from="true" to="%[bean#propertyPanel.savedQueries#Dirty]"/> </if> <Remove to="%[frame#com.ptc.windchill.enterprise.search.useSortingTaskParams]"/> </On>

2. In <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/table.xml i. Locate the element <ElementGroup id="elementgroup.searchResults.taskParameters">

ii. Modify
<TaskParameter adhocValue="%[attribute#propertyPanel.searchCriteria#adhocPageCount]" function= "com.ptc.windchill.enterprise.search.client.CoFunction_Model_Param_AdhocPageCount" if="%[context#isPropertyPicker]!=true"/>

as

20-12

Windchill Customizers Guide

<TaskParameter adhocValue="%[frame#adhocPageCount]" function= "com.ptc.windchill.enterprise.search.client.CoFunction_Model_Param_AdhocPageCount" if="%[context#isPropertyPicker]!=true"/>

3. Also in <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/table.xml i. Locate the element <Layout id="layout.searchPage">

ii. Within that element, exchange the locations of the Search Criteria and the Search Results LayoutRow elements:
<!-- Search Criteria --> <LayoutRow id="layoutRow.searchCriteria.searchPage"> ... </LayoutRow>

and
<!-- Search Results --> <LayoutRow id="layoutRow.searchResults.searchPage"> ... </LayoutRow>

Customizing Search Functionality

20-13

Adding Different Formats for Exporting Search Results


There are three file formats (.csv, .xml, .html) available out of the box for exporting search results. Additional formats can be added by completing the following steps. 1. Update the DCA configurations to display the new format in the export client. 2. Create a style sheet for the new format.

Update DCA Configurations


The file that will need to be edited to add a new format is <Windchill>/conf/dca/com/ptc/windchill/enterprise/search/ExportSearchResults. xml First, a labelArea element will need to be defined for the new format. The following is an example of what this might look like for a new format .abc:
<LabelArea id="labelArea.formatType.abc" labelType="text"> <Label resource="abc" /> </LabelArea>

To make the new format available in the export client the "enumerator.formatType" element will need to be updated by inserting the new labelArea in the enumerator. Example for new format .abc:
<Enumerator id="enumerator.formatType"> <Insert ref="labelArea.formatType.csv" value="csv" /> <Insert ref="labelArea.formatType.xml" value="xml" /> <Insert ref="labelArea.formatType.html" value="html" /> <Insert ref="labelArea.formatType.abc" value="abc" /> .............. ............... </Enumerator>

Create New Style Sheet


A new style sheet must be created for the format being added. The style sheet should be placed in the following location: <Windchill>/codebase/wtcore/xsl/com/ptc/windchill/enterprise/search/ Style sheets for the existing formats are located there as well. The file should be named using the format: SearchResults_<abc>.xsl Where <abc> is the file extension of the new format being added.

20-14

Windchill Customizers Guide

Customizing Index Search Capabilities


There is support for creating a new Customized search application with Index. The Indexed-Search webject queries the indexing engine for the indexed content of Windchill objects if Index Search is installed. It accepts a 'keyword' String as input and returns XML formatted results (see below). It includes the ufid(obid), the object class, a rank, and a teaser for every associated contentItem for that object. It also may include one or more spelling suggestions.
<wc:COLLECTION xmlns:wc="http://www.ptc.com/infoengine/1.0"> - <wt.fc.WTObject NAME="output" TYPE="Unknown" STATUS="0"> <wc:INSTANCE /> - <wc:INSTANCE> <obid>VR:wt.doc.WTDocument:22052</obid> <class>wt.doc.WTDocument</class> <teaser>Basketball rules Basics Goal is to shoot the ball into a basket (10' high) to score points. A basic shot counts as 2 points, and shots from the three point line count as 3 points and free throws count as 1 point.</teaser> <rank>1997</rank> <contentItem>OR:wt.content.ApplicationData:22059|1898|Basketball rules Basics Goal is to shoot the ball into a basket (10' high) to score points. A basic shot counts as 2 points, and shots from the three point line count as 3 points and free throws count as 1 point.</contentItem> </wc:INSTANCE> <wc:INSTANCE> <suggest>wrong</suggest> </wc:INSTANCE> </wt.fc.WTObject> </wc:COLLECTION>

Input Parameters to the Index-Search Webject


SESSION_ID Session identifier with all tasks TYPE Specifies the set of Windchill Business Types to constrain the search. This would be wt.part.WTPart, wt.doc.WTDocument, etc. WHERE If specified, the indexing tool will attempt to filter results based on the whereClause. KEYWORD Specifies a query expression identifying the keyword string to be sent to Index Search. LIBRARIES Specifies the set of Index Search libraries (collections) to search for the keyword.

Customizing Search Functionality

20-15

FETCH_FIELDS Specifies a set of fields that are stored in Index Search to be retrieved as part of the query. The default fields that will always be requested is the ufid, which is used by Search-Objects to retrieve the results from the Indexed-Search from Windchill. SORTBY Specifies a set of attributes that are both specified to be returned by the query and that have sorting preferences defined. Multiple values can be specified for this parameter. If multiple values are specified, then the first value is the primary sort attribute, the second value is the secondary sort attribute, and so on. This parameter is optional. SORTED Specifies whether the current attribute to sort by should be sorted as descending or ascending. The default for this parameter is descending. This parameter is optional. FILTER_ACCESS When set the indexing engine will use a filter the result set to a 'Potential' read list. SPELL_CHECK If set to true, then Indexing Engine will attempt to validate spelling and suggest possible query terms. TYPE_CONTAINER Determines the set of base types to be used in the search from the incoming type parameter. QUERY_TYPE Determines the type of query to perform, Simple or Advanced. A Simple query sends the keyword to Index Search as a keyword only. An Advanced query sends the keyword as an Index Search query, so it must have valid syntax for an Index Search query. See the Instream SDK Query Language Parameters Guide for valid Index Search query syntax. MAX_DOCS Determines the maximum amount of documents to return from index search. MIN_HITS This parameter is ignored. CONTAINER_REF Filters the search results to those objects within the container reference. INSTANCE Specifies the name of the Windchill adapter. You can define the adapter name when you configure the adapter on the Info*Engine Property Administrator service form. This parameter is required.

20-16

Windchill Customizers Guide

COMPONENT_ID Specifies which client component is invoking the search. This parameter is used to select the list of classes to query against as defined in com/ptc/windchill/enterprise/search/server/SearchableTypes.properties. SEARCH_IN_USER_ORG Search only in containers (contexts) belonging to principal's org. AND_OR_OPERATOR Determines if the Index Search query uses SIMPLEANY (OR) or SIMPLEALL (AND). ATTRIBUTE_TYPE_CONTEXT Filters the search results by attribute type. UNFORMATTED This parameter is ignored. GROUP_OUT Specifies the name of the output group containing the results. If this parameter is omitted the name of the output group is constructed by appending the string "-Output" to the webject name. This parameter is optional. The resulting group is not access controlled, but can then be used to query Windchill for the appropriate objects, to include access control. The group could be combined with other criteria as well to perform a more specific search. Please see the Windchill Adapter Guide for more information around setting up SearchObjects and Query-Objects webjects.

Sorting IndexSearch Search Results


You can sort the results returned by IndexSearch when invoked through the Indexed-Search webject. To accomplish this, customize the task search-IndexSearch.xml (in <Windchill>/tasks/com/ptc/windchill/enterprise/search/). If they do not already exist, add two parameters to this task as follows:
<ie:param name="SORTBY" data="sortBy"/> <ie:param name="SORTED" data="sorted"/>

These two are optional parameters. The default values are "sortBy" and "sorted", respectively. If the parameters are not present, or if the default values are used, no sorting is done. To specify the fields to sort by, set the SORTBY parameter value to any of the fields defined for the particular library. The default library (collection) provided in Windchill is wblib; the list of fields (for example, "name", "number", "title") is shown in the IndexSearch

Customizing Search Functionality

20-17

Administration UI, on the Search page. To view all available fields, check the "Show All Fields" checkbox in Advanced Controls. If you specify a value in SORTBY that is not a default and does not match any of the library fields, then it is ignored and no sorting will be done. The SORTBY parameter is a case sensitive field. Hence for sorting the results based on number, and in ascending order, the parameters to add would be:
<ie:param name="SORTBY" data="number"/> <ie:param name="SORTED" data="ascending"/>

You can give multiple fields and their corresponding sort orders by space separated values. For example:
<ie:param name="SORTBY" data="name number"/> <ie:param name="SORTED" data="asc"/>

This would sort the results first on name and then number. For further information on the Indexed-Search webject, see the Windchill Adapter Guide.

20-18

Windchill Customizers Guide

Customizing Indexing Behavior


You can modify the information stored in the search engines index that is associated with a Windchill business object either by extending the wt.index.InstreamIndexDelegate class and providing customized behavior, or by simply using xconfmanager to update the wt.index.Index.Fields property in <Windchill>/codebase/wt.properties. The default InstreamIndexDelegate indexes every attribute, every soft attribute, the identity of every object reference connected with the business object (that is, the owner), the text of content files, and the links and descriptions of attached URLs. You most likely need to modify the behavior of the wt.index.InstreamIndexDelegate if your site has a customized object with a particular attribute that you want to appear in its own field in the search engines index. If this field is a modeled attribute, then simply adding it to the wt.index.IndexFields property would suffice. The following sections describe the predefined Index Search fields supplied with Windchill and how to add the capability to index data into new fields.

IndexSearch Fields
In addition to the full text index of object metadata and content files, text can be indexed into specific IndexSearch fields. When text is indexed into fields, it is possible to restrict, or filter, query responses by entering search terms in data fields, such as title, number, date, and so on. These queries can be used in combination with a full text query or used alone to limit the types of documents returned. Windchill provides a Index Search Profile configured with the fields in the table below. If you want a library to contain additional fields, you must add those fields to the profile before data is indexed into the library. Refer to the Index Profile Features Management section of the InStream Configuration Guide for further information on setting up library fields. After the fields have been defined for the library, you can write a custom InstreamIndexDelegate subclass to populate the new fields with the appropriate data, or you can simply append them onto the following property in wt.properties:
wt.index.IndexFields= name,lifeCycleState,description,number,title,containerReference,modifyTimestamp

Notice that some attributes are indexed automatically and cannot be overridden.

Field

Description

Required

businesstype

This is the actual type of the object, it is used internally to filter queries in a more performant manner.

Yes

Customizing Search Functionality

20-19

Field

Description

Required

iscontent

This is a flag to indicate if an index entry represents content or not. Could be used to filter by content vs metadata. This is the id of the ContentItem that is actually indexed. This is used as a way to keep track of multiple indexed items with one Windchill Object. The name of the indexed object. The number of the indexed object. This field contains all of the miscellaneous attributes for an object that are not defined in any other field. The lifecycleState of the object (In Work, Released, etc) The object reference of the container the object belongs to. The last modified stamp of the object The created timestamp of the object. This is a field that represents all of the soft attributes associated with an object. Note: The name of the field comes from the fact that soft attributes have sometimes been referred to as instance-based attributes (IBAs).

Yes

ufid

Yes

name number metadata

No No Yes

lifecyclestate containerreference modifytimestamp createtimestamp ibas

No No No No Yes

organizationreference

The object reference of the organization the object belongs to.

Creating a Custom InstreamIndexDelegate


The default InstreamIndexDelegate implementation indexes all object metadata and any soft attributes associated to the current object. Creating a custom InstreamIndexDelegate object is appropriate if you know which fields you want indexed for an object and you only want those fields indexed. This is the primary reason for creating a custom InstreamIndexDelegate. A custom InstreamIndexDelegate could theoretically improve indexing performance

20-20

Windchill Customizers Guide

because fewer attributes would need to be processed and written to IndexSearch but this should be a secondary consideration when determining if creating a custom InstreamIndexDelegate is appropriate. To create a custom InstreamIndexDelegate, use Rational Rose to model your new class, making it extend the InstreamIndexDelegate class. Then generate the Java code and provide implementations for the following method signatures:
public void custom_getAdditionalMetaData( Indexable indexable, IndexingObject indexingObject ) throws WTException, IndexingException { public void custom_getAdditionalFieldData( Indexable indexable, IndexingObject indexingObject ) throws WTException, IndexingException {

These methods do nothing in the base class, so anything added will be additional functionality for the indexing system. There are examples below on how to call specific methods to write customized fields, or specify additional metadata on an indexed object. To put your custom InstreamIndexDelegate into action, you must update the service.properties file to reflect this change. Following is the default InstreamIndexDelegate entry:
# ##################################################### # The wt.index.IndexServiceDelegate service. # ########################################################### wt.services/svc/default/wt.index.IndexServiceDelegate/null/ wt.index.Indexable/0=wt.index.InstreamIndexDelegate/duplicate

As part of the changes introduced in 8.0, the ability to subclass the delegate by type is no longer supported. However, this functionality can easily be reproduced by logic in a customer IndexServiceDelegate. Also, the ability to define a delegate for a single library is no longer supported either, but fields that are not defined in a particular library are ignored, so sending additional information to IndexSearch is not an issue. For this example, assume that you have a custom InstreamIndexDelegate named InstreamSubClassIndexDelegate that you want to use to index. If you want to override the default InstreamIndexDelegate you must add the following line to service.properties:
wt.services/svc/default/wt.index.IndexServiceDelegate /null/wt.index.Indexable/0= wt.index.InstreamSubClassIndexDelegate/duplicate

(Note that you should actually enter only one line; the indentation shown here indicates a continuation of the preceding line, necessary for presentation of lines within the book.)

Customizing Search Functionality

20-21

Overriding the custom_getAdditionalFieldData custom_getFieldData() Method


Overwrite the custom_getAdditionalFieldData( Indexable indexable, IndexingObject indexingObject ) method and add your specific code into this method. See below for a very simple example. There are two methods in IndexingObject parameter that can be used to send information to Index Search. The first is the appendMetadataField method which allows you to add information to the meta data field in Index Search. The second is the appendSearchField method, which will add an indexed search field of a specified type you would like to index with the object.
*********EXAMPLE*********** package wt.index; import wt.index.InstreamIndexDelegate; import wt.index.IndexingException; import wt.util.WTException; public class InstreamSubClassIndexDelegate extends InstreamIndexDelegate { /** * This method can be used to provide customized fields to be indexed * in your Indexing engine. **/ public void custom_getAdditionalFieldData( Indexable indexable, IndexingObject indexingObject ) throws WTException, IndexingException { String newField = "myValue"; //this will add meta data to the index indexingObject.appendMetadataField("MyNewMetadata"); //This will add the a new search field to the index indexingObject.appendSearchField ("MetaData", newField, "string"); ********EXAMPLE**********

20-22

Windchill Customizers Guide

IndexingObject Method Reference


Following are IndexingObject methods that are applicable to customizing your class: public void appendMetadataField(String value) This method appends the string value to the metadata field in the index. public void appendIBAField(String value) This method appends the string value to the IBA field in the index. public void addContentItem (Object key, InputStream value, long size) This methods adds the content contained in the InputStream value with the specified size to the index with the specified key, normally the ufid of the content. public void appendSearchField(String inSearchField, Object inSearchValue, String inSearchType) This method appends the search field with name inSearchField, value inSearchValue and type inSearchType to the search fields in the index. The inSearchType value should be one of "string", "double", "float", "int32" or "datetime".

Customizing Search Functionality

20-23

Windchill Client Architecture Search Customization


Search customization Scenarios
Scenario A - Best practice to add attribute in criteria drop down on advanced search page Scenario B - Best practice to add new action to search result table Scenario C - Best practice to add new item type to search item picker

Objective
Scenario A: Allow user to add customized attribute to Criteria drop down Scenario B: Allow user to add new action for given type to search result table Scenario C: Allow user to add new customized type to search item picker

Background
Scenario A - An out-of-the-box user can search on all the modeled attributes as well as soft attributes for given Object Tyep. User can not see attributes that are added by modeling the Object in Rational Rose. Scenario B - The site-defined preference, /com/ptc/windchill/enterprise/search/allSearchTypes,determines the list of types that are to be included when a user searches across "all" Object types. This is the same list that a user can choose from within the Object Type picker for the Customize link on the Search page, and the Search For link onthe Advanced Search page Scenario C - The allSearchTypes preference defines a base list of types; outof-the-box searching rules include all soft types defined from one of these types. It does not, however, include any modeled subclasses. Any new modeled object type should be defined in the allSearchTypes preference to make it available for searches.

Scope/Applicability/Assumptions
Scenario A - New attributes are added to item by Rational Rose modeling. Scenario B - New actions are defined Scenario C - New item or object type is modeled in Rational Rose

Intended Outcome
Scenario A - Adding new criteria to search result table:

An out-of-the-box user will not get added extra attributes in Criteria drop down on advanced search page. Once user adds entry for logical attribute name for new

20-24

Windchill Customizers Guide

attributes in SearchableAttributesByType.properties, user can see new attribute criteria drop down.

In above case user has added new attribute Real and Real _Units which are added by rose modeling.
Scenario B - Adding new action to search result table.

Out-of-the-box there are fixed actions defined for all Object type on simple search page whereas on advanced search page Object Type specific actions are available on search result table. Out-of-the-box on simple search page Copy, Delete, Add to Project, Move, Reassign Life Cycle, Export actions are provided. We have to add action Set State on simple search page.

Scenario C - Adding new item to search item picker

The allSearchTypes preference defines a base list of types; out-of-the-box searching rules include all soft types defined from one of these types. It does not, however, include any modeled subclasses. Any new modeled object type should be defined in the allSearchTypes preference to make it available for searches.

Customizing Search Functionality

20-25

Solution Solution For Scenario A:


Add the logical attribute name against given Object Type in <Windchill>/codebase/com/ptc/windchill/enterprise/search/server/SearchableAttr ibutesByType.properties.

Solution For Scenario B:


Add action name and type in <Windchill>/codebase/config/actions/searchactionmodels.xml

Solution For Scenario C:


Add new sub class modeled type entry in <Windchill>/codebase/com/ptc/windchill/enterprise/search/server/SearchableTyp es.properties.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving HTML forms, JSP, XML, Java

20-26

Windchill Customizers Guide

Solution Elements

Element

Type

Description

Scenario A SearchableAttributesByType.properties

properties

Runtime location <Windchill>/codebase/com/ptc/windchil l/enterprise/search/server/SearchableAttr ibutesByType.properties Runtime <Windchill>/codebase/config/actions/se a rch-actionmodels.xml Runtime location <Windchill>/codebase/com/ptc/windchil l/enterprise/search/server/SearchableByT ypes.properties

Scenario B - search-actionmodels.xml

XML

Scenario C SearchableTypes.properties

properties

Scenario A: Procedure Adding new attribute in Criteria drop down


To add attributes for a particular type, simply add the logical attribute name to the comma separated list for that type in SearchableAttributesByType.properties. The logical attribute name is the attribute retrieved from introspection or defined within the <Windchill>/codebase/LogicalAttributes.xml file. For example, if we were to add "Real" to wt.part.WTPart, it would look like this:
advancedSearch.wt.part.WTPart=folderingInfo.cabinet,thePersistInfo .creat eStamp,iterationInfo.creator,defaultUnit,lock.locker,name,number,o wnership.owner,source,state.state,thePersistInfo.modifyStamp,itera tionInfo.modifier,view.id,organizationReference,Real

Scenario B: Procedure Adding new action to Search Result table


To add new action to search result table, add entries to search-actionmodels.xml file.Suppose we want to add new action Set State on simple search page, add following entry to search-actionmodels.xml as:
<model name="search table actions"> <action name="list_copy" type="object"/> <action name="list_delete" type="object"/> <action name="CREATEPROMOTIONNOTICE" type="pdmObject"/> <action name="SBAddToPrj" type="sandbox"/> <action name="WFSAVEAS" type="pdmObject"/> <action name="CONTAINERMOVE" type="pdmObject"/> <action name="userInitiatedReplication" type="replication"/> <action name="reassignLC" type="lifecycle"/> <action name="setState" type="lifecycle"/> <action name="exportSearchResults" type="search"/> </model>

Customizing Search Functionality

20-27

Scenario C: Procedure - Add new Object type to Object Type picker


To add new Object type for picker, add new object name to SearchableTypes.properties. We have new sub class as searchPart. For this new object add entry to add in SearchableTypes.properties as :
PDMLink.allSearch.0=wt.change2.WTChangeIssue PDMLink.allSearch.1=wt.change2.WTChangeRequest2 PDMLink.allSearch.2=wt.change2.WTChangeOrder2 PDMLink.allSearch.3=wt.part.WTPart PDMLink.allSearch.4=wt.doc.WTDocument PDMLink.allSearch.5=wt.epm.EPMDocument PDMLink.allSearch.6=wt.workflow.engine.WfProcess PDMLink.allSearch.7=wt.part.WTProductInstance2 PDMLink.allSearch.8=wt.part.WTProductConfiguration PDMLink.allSearch.9=wt.query.template.ReportTemplate PDMLink.allSearch.10=wt.vc.baseline.ManagedBaseline PDMLink.allSearch.11=wt.meeting.Meeting PDMLink.allSearch.12=wt.org.WTOrganization PDMLink.allSearch.13=wt.inf.library.WTLibrary PDMLink.allSearch.14=wt.pdmlink.PDMLinkProduct PDMLink.allSearch.15=wt.dataops.archive.Archive PDMLink.allSearch.16=wt.part.WTPart.searchPart

After adding the new type you should set the property com.ptc.windchill.search.refreshTypesFromProperties to "true" in wt.properties.

Sample Code Scenario A: Entries from SearchableAttributesByType.properties for new attribute part Type
advancedSearch.wt.part.WTPart=folderingInfo.cabinet,thePersistInfo .creat eStamp,iterationInfo.creator,defaultUnit,lock.locker,name,number,o wnership.owner,source,state.state,thePersistInfo.modifyStamp,itera tionInfo.modifier,view.id,organizationReference,Real

Scenario B: Entries from search-actionmodels.xml


<model name="search table actions"> <action name="list_copy" type="object"/> <action name="list_delete" type="object"/> <action name="CREATEPROMOTIONNOTICE" type="pdmObject"/> <action name="SBAddToPrj" type="sandbox"/> <action name="WFSAVEAS" type="pdmObject"/> <action name="CONTAINERMOVE" type="pdmObject"/> <action name="userInitiatedReplication" type="replication"/> <action name="reassignLC" type="lifecycle"/> <action name="setState" type="lifecycle"/> <action name="exportSearchResults" type="search"/> </model>

20-28

Windchill Customizers Guide

Scenario C: Entries from SearchableTypes.properties


PDMLink.allSearch.0=wt.change2.WTChangeIssue PDMLink.allSearch.1=wt.change2.WTChangeRequest2 PDMLink.allSearch.2=wt.change2.WTChangeOrder2 PDMLink.allSearch.3=wt.part.WTPart PDMLink.allSearch.4=wt.doc.WTDocument PDMLink.allSearch.5=wt.epm.EPMDocument PDMLink.allSearch.6=wt.workflow.engine.WfProcess PDMLink.allSearch.7=wt.part.WTProductInstance2 PDMLink.allSearch.8=wt.part.WTProductConfiguration PDMLink.allSearch.9=wt.query.template.ReportTemplate PDMLink.allSearch.10=wt.vc.baseline.ManagedBaseline PDMLink.allSearch.11=wt.meeting.Meeting PDMLink.allSearch.12=wt.org.WTOrganization PDMLink.allSearch.13=wt.inf.library.WTLibrary PDMLink.allSearch.14=wt.pdmlink.PDMLinkProduct PDMLink.allSearch.15=wt.dataops.archive.Archive PDMLink.allSearch.16=wt.part.WTPart.searchPart

Customizing Search Functionality

20-29

Loading an OOTB Saved Query


This section contains information on creating saved searches out of the box. 1. Create SavedQuery.xml file with one or many saved queries in it (example is given later in this document) 2. Create a folder named SavedQueries as: \Windchill\loadFiles\SavedQueries 3. Put the SavedQueries.xml in SavedQueries folder, 4. Add the entry of handler in : \Windchill\codebase\registry\ixb\handlers\netmarketsX10.xml as:
<elementImporter> <tag>SavedQueries</tag> <dtd>standardX10.dtd</dtd> <handler>wt.query.ixb.handlers.forclasses.SavedQueryHandler< /handler> </elementImporter>

5. Add the entry in \Windchill\codebase\wt\load\foundationLoad.xml as:


<loadFile filename="SavedQueries/SavedQueries.xml" rbinfo="wt.load.loadResource" localized="true" title="OOTB Saved Queries"/>

6. In this example, the SavedQueries tag is used, user can use any tag provided that user has to write handler for that tag and have to add the entry for that tag in several dtds. Add <!ELEMENT SavedQueries (SavedQuery*)> in: \Windchill\codebase\registry\ixb\dtds\standardX10.dtd\netmarkets.dtd and \Windchill\loadXMLFiles\standardX10.dtd 7. User can add multiple saved queries in single xml file, for that the SavedQuery tag will be repeted inside the SavedQueries tag.

Example: SavedQuery.xml
The contents of SavedQuery.xml would be something like the following.
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE SavedQueries SYSTEM "standardX10.dtd"> <SavedQueries> <SavedQuery> <name>Product</name> <description> ((null))</description> <owningClient>dcaSimpleSearch</owningClient> <SearchCriteria>

20-30

Windchill Customizers Guide

<CommonCriteria> <searchElement> <searchKey>searchClass</searchKey> <searchValue>wt.part.WTPart,wt.change2.WTChangeIssue,wt.change2.WT ChangeOrder2,wt.epm.EPMDocument,wt.change2.WTChangeRequest2,wt.doc .WTDocument</searchValue> </searchElement> <searchElement> <searchKey>searchInUserOrg</searchKey> <searchValue>null</searchValue> </searchElement> <searchElement> <searchKey>memberOfContainer</searchKey> <searchValue>null</searchValue> </searchElement> <searchElement> <searchKey>networkSearch</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>containerTypeList</searchKey> <searchValue>wt.pdmlink.PDMLinkProduct</searchValue> </searchElement> <searchElement> <searchKey>pageCount</searchKey> <searchValue>15</searchValue> </searchElement> <searchElement> <searchKey>search_keyword</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>relatedItemSearch</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>is_keyword_required</searchKey> <searchValue>null</searchValue> </searchElement> <searchElement> <searchKey>searchType</searchKey> <searchValue>wt.part.WTPart,wt.change2.WTChangeIssue,wt.change2.WT ChangeOrder2,wt.epm.EPMDocument,wt.change2.WTChangeRequest2,wt.doc .WTDocument</searchValue> </searchElement> <searchElement> <searchKey>savedQueryTableViewID</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>showResults</searchKey> <searchValue>&amp;</searchValue> </searchElement> <searchElement> <searchKey>containerName</searchKey>

Customizing Search Functionality

20-31

<searchValue></searchValue> </searchElement> <searchElement> <searchKey>name</searchKey> <searchValue>null</searchValue> </searchElement> <searchElement> <searchKey>organization</searchKey> <searchValue>null</searchValue> </searchElement> <searchElement> <searchKey>number</searchKey> <searchValue>null</searchValue> </searchElement> </CommonCriteria> <NetworkCriteria></NetworkCriteria> <CustomCriteria> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hPickerComponent" id="orgField"> <searchElement> <searchKey>pickerTextBoxLength</searchKey> <searchValue>25</searchValue> </searchElement> <searchElement> <searchKey>defaultValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey> <searchValue>com.ptc.netmarkets.search.rendering.renderers.SearchP ickerComponentRenderer</searchValue> </searchElement> <searchElement> <searchKey>containerRef</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.SearchPickerSearchTermP roducer</searchValue> </searchElement> <searchElement> <searchKey>pickerRef</searchKey> <searchValue>genericPicker</searchValue> </searchElement> <searchElement> <searchKey>objectType</searchKey> <searchValue>wt.org.WTOrganization</searchValue> </searchElement> <searchElement> <searchKey>displayValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement>

20-32

Windchill Customizers Guide

<searchKey>calledFromAdvSearch</searchKey> <searchValue>true</searchValue> </searchElement> <searchElement> <searchKey>pickedAttributes</searchKey> <searchValue>name</searchValue> </searchElement> <searchElement> <searchKey>typeComponentId</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>pickerType</searchKey> <searchValue>search</searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>uiID</searchKey> <searchValue>orgField</searchValue> </searchElement> <searchElement> <searchKey>attrID</searchKey> <searchValue>organization.id</searchValue> </searchElement> <searchElement> <searchKey>searchResultsViewId</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>hiddenFieldName</searchKey> <searchValue>organization.idorgField</searchValue> </searchElement> <searchElement> <searchKey>pickedDataFetcher</searchKey> <searchValue>/Windchill/netmarkets/jsp/search/pickedData.jsp</sear chValue> </searchElement> <searchElement> <searchKey>defaultHiddenValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>isRenderedFromTable</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>showVersion</searchKey> <searchValue>false</searchValue> </searchElement>

Customizing Search Functionality

20-33

<searchElement> <searchKey>baseWhereClause</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>showTypePicker</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>pickerId</searchKey> <searchValue>organization.idorgField</searchValue> </searchElement> <searchElement> <searchKey>readOnlyPickerTextBox</searchKey> <searchValue>true</searchValue> </searchElement> <searchElement> <searchKey>pickerCallback</searchKey> <searchValue>SearchPickerInputComponentCallback</searchValue> </searchElement> <searchElement> <searchKey>componentId</searchKey> <searchValue>pickerSearch</searchValue> </searchElement> <searchElement> <searchKey>pickerTitle</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>multiSelect</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>hiddenValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> </row> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hTextBox" id="numberField"> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>uiID</searchKey> <searchValue>numberField</searchValue> </searchElement>

20-34

Windchill Customizers Guide

<searchElement> <searchKey>value</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>width</searchKey> <searchValue>20</searchValue> </searchElement> <searchElement> <searchKey>attrID</searchKey> <searchValue>number</searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey> <searchValue>com.ptc.core.components.rendering.renderers.TextBoxRe nderer</searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.SearchTextBoxTermProduc er</searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>name</searchKey> <searchValue>numbernumberField_SearchTextBox</searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> </row> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hTextBox" id="nameField"> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>uiID</searchKey> <searchValue>nameField</searchValue> </searchElement> <searchElement> <searchKey>value</searchKey> <searchValue></searchValue> </searchElement>

Customizing Search Functionality

20-35

<searchElement> <searchKey>width</searchKey> <searchValue>20</searchValue> </searchElement> <searchElement> <searchKey>attrID</searchKey> <searchValue>name</searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey> <searchValue>com.ptc.core.components.rendering.renderers.TextBoxRe nderer</searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.SearchTextBoxTermProduc er</searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>name</searchKey> <searchValue>namenameField_SearchTextBox</searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> </row> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hTextBox" id="keywordField"> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>uiID</searchKey> <searchValue>keywordField</searchValue> </searchElement> <searchElement> <searchKey>value</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>width</searchKey> <searchValue>50</searchValue> </searchElement> <searchElement>

20-36

Windchill Customizers Guide

<searchKey>attrID</searchKey> <searchValue>keyword</searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey> <searchValue>com.ptc.core.components.rendering.renderers.TextBoxRe nderer</searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.KeywordSearchTermProduc er</searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>name</searchKey> <searchValue>keywordkeywordField_SearchTextBox</searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> </row> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hDateComponent" id="createdField"> <searchElement> <searchKey>uiID</searchKey> <searchValue>createdField</searchValue> </searchElement> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>value</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>attrID</searchKey> <searchValue>thePersistInfo.createStamp</searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey> <searchValue>com.ptc.netmarkets.search.rendering.renderers.SearchD ateRenderer</searchValue>

Customizing Search Functionality

20-37

</searchElement> <searchElement> <searchKey>attributeType</searchKey> <searchValue>1</searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.DateSearchTermProducer< /searchValue> </searchElement> <searchElement> <searchKey>isQueryBuilder</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>isRange</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>sinceValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> </row> <row className="com.ptc.netmarkets.search.rendering.guicomponents.Searc hDateComponent" id="lastUpdatedField"> <searchElement> <searchKey>uiID</searchKey> <searchValue>lastUpdatedField</searchValue> </searchElement> <searchElement> <searchKey>operatorValue</searchKey> <searchValue>=</searchValue> </searchElement> <searchElement> <searchKey>value</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>attrID</searchKey> <searchValue>thePersistInfo.modifyStamp</searchValue> </searchElement> <searchElement> <searchKey>renderer</searchKey>

20-38

Windchill Customizers Guide

<searchValue>com.ptc.netmarkets.search.rendering.renderers.SearchD ateRenderer</searchValue> </searchElement> <searchElement> <searchKey>attributeType</searchKey> <searchValue>1</searchValue> </searchElement> <searchElement> <searchKey>searchTermProducer</searchKey> <searchValue>com.ptc.netmarkets.search.stp.DateSearchTermProducer< /searchValue> </searchElement> <searchElement> <searchKey>isQueryBuilder</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>isRange</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>isRequired</searchKey> <searchValue>false</searchValue> </searchElement> <searchElement> <searchKey>sinceValue</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>displayName</searchKey> <searchValue></searchValue> </searchElement> <searchElement> <searchKey>attTypeForOperator</searchKey> <searchValue>java.lang.String</searchValue> </searchElement> </row> </CustomCriteria> </SearchCriteria> </SavedQuery> </SavedQueries>

Sample Code: Handler written for the tag SavedQueries


The sample code for the handler written for the tag SavedQueries is as follows:
package wt.query.ixb.handlers.forclasses; import import import import import import java.util.Enumeration; java.util.Vector; wt.inf.container.WTContainerRef; wt.ixb.publicforapps.Exporter; wt.ixb.publicforhandlers.*; wt.ixb.publicforapps.Importer;

Customizing Search Functionality

20-39

import wt.ixb.handlers.netmarkets.NMProjectConstants; import wt.ixb.handlers.netmarkets.NMIxResources; import wt.ixb.handlers.netmarkets.ProjectIXUtils; import wt.pom.Transaction; import wt.util.WTException; /** * This class is the handler for the <SavedQueries> tag. */ public class SavedQueryHandler extends ClassExporterImporterTemplate { private static final String _rb = "wt.ixb.handlers.netmarkets.NMIxResources"; private static final String OOTB_SAVED_QUERIES = "SavedQueries"; public SavedQueryHandler() { } public void exportObject(Object obj, Exporter exp) throws wt.util.WTException { Object[] params = {obj.getClass().getName()}; throw new WTException(_rb, NMIxResources.EXPORT_NOT_SUPPORTED,params); } /** * This controls the import of all the objects. * On exception all transactions are rolled back. */ public Object createObject(IxbElement elem, Importer imp) throws wt.util.WTException { ProjectIXUtils.checkTag(elem, OOTB_SAVED_QUERIES); WTContainerRef orgRef = imp.getTargetContainerRef(); imp.generalContext.put(IxbHndHelper.CONTAINER_SCOPE,orgRef); Transaction trx = new Transaction(); try { trx.start(); boolean firstTime = true; Vector parmSet = new Vector(); // Enumeration files = elem.getElements(orgTags.LOAD_XML_FILE); Enumeration files = elem.getElements(IxbHndHelper.XML_SAVEDQUERY); while(files.hasMoreElements()) { if(firstTime) { parmSet.add(IxbHndHelper.XML_SAVEDQUERY);

20-40

Windchill Customizers Guide

ProjectIXUtils.postFeedback(imp,_rb,NMIxResources.LOAD_TYPE,parmSe t.toArray(),NMProjectConstants.TYPE_LEVEL); firstTime = false; } IxbElement file = (IxbElement) files.nextElement(); imp.importElement(file); } if(!firstTime) { ProjectIXUtils.postFeedback(imp,_rb,NMIxResources.TYPE_LOADED,parm Set.toArray(),NMProjectConstants.TYPE_LEVEL); parmSet.clear(); } firstTime =true; ProjectIXUtils.postFeedback(imp,_rb,NMIxResources.ORG_IMPORT_SUCCE EDED,null,0); trx.commit(); return null; } finally { if(trx != null) { trx.rollback(); } } } public int getImportPriority() throws wt.util.WTException { return 42; } public Object findAmongExistingObjects(IxbElement obj, Importer imp) throws wt.util.WTException { return null; } public Object storeObject(Object obj, IxbElement elem, Importer imp) throws wt.util.WTException { //all objects are stored, by the handlers, this is just the driver. return obj; } }

Customizing Search Functionality

20-41

Search Elements and Associated JSPs


Search element and their associated JSP for Simple Search Page Search element and their associated JSP for Advanced Search Page

Search element and their associated JSP for Simple Search Page

Search UI Element Search Page Search Page Navigation

Search sub Element

Associated JSP /netmarkets/jsp/search/exe cuteSearch.jsp

Associated Custom Tag (if any)

Search Advanced Search Saved Searches Keyword Show Results Results Per Page Search In Search For

/netmarkets/jsp/search/sear chNavigation.jsp /netmarkets/jsp/search/co mmonSearch.jsp

searchNavigation

Common Search Page

searchTextBox

Search In Search For Name Number Organization FileName Last Updated Created On Save This Search,Search,Clear Button Search Results Table Save This Search

/netmarkets/jsp/search/sho wContext.jsp /netmarkets/jsp/search/typ eChooser.jsp /netmarkets/jsp/search/sear chCriteria.jsp /netmarkets/jsp/search/sear chCriteria.jsp /netmarkets/jsp/search/sear chCriteria.jsp /netmarkets/jsp/search/sear chButton.jsp /netmarkets/jsp/search/sear chResults.jsp /netmarkets/jsp/search/cust omizeQuery.jsp

searchInContext

searchTextBox

searchPicker searchDate

20-42

Windchill Customizers Guide

Search element and their associated JSP for Advanced Search Page
Search UI Element Search Page Search Page Navigation Search Advanced Search Saved Searches Keyword Show Results Results Per Page Search In Search For Search sub Element Associated JSP /netmarkets/jsp/searc h/executeSearch.jsp /netmarkets/jsp/searc h/searchNavigation.j sp /netmarkets/jsp/searc h/commonSearch.jsp searchNavigation Associated Custom Tag (if any)

Common Search Page

searchTextBox

Search In Search For Search For Type Picker Define Search Criteria for Archived Objects Options for Part advanced search SuMA sourcing contexts Criteria:

/netmarkets/jsp/searc h/showContext.jsp /netmarkets/jsp/searc h/typeChooser.jsp /netmarkets/jsp/searc h/handleArchiveSear ch.jsp

searchInContext

archivePanel

Search For Search For

searchDDLComponent /netmarkets/jsp/searc h/sourcingContext.js p /netmarkets/jsp/searc h/queryBuilder.jsp /netmarkets/jsp/searc h/searchButton.jsp /netmarkets/jsp/searc h/searchResults.jsp /netmarkets/jsp/searc h/customizeQuery.js p

Select Search Criteria Save This Search,Search,Clear Button Search Results Table Save This Search

Customizing Search Functionality

20-43

20-44

Windchill Customizers Guide

III
Business Logic Customization Section

Chapter

Page

Customizing Business Logic............................................................................. 21-1 Customizing Change Management ................................................................... 22-1 Customizing Life Cycle Administration ........................................................... 23-1 Customizing Workflow Administration............................................................ 24-1 Customizing Workgroup Managers .................................................................. 25-1 Customizing Windchill Visualization Services ................................................ 26-1 Report Generation ............................................................................................. 27-1 Customizing Event Audits ................................................................................ 28-1 Customizing Communication Tools ................................................................. 29-1

21
Customizing Business Logic
This chapter describes how to customize business logic. Topic Page

Identified Business Classes ..............................................................................21-2 Customizing Iteration and Version Identifiers ................................................21-17 Customizing a Bill of Materials ......................................................................21-19 Customizing User Preferences ........................................................................21-24 Writing a Servlet Helper to Use URLFactory Functionality...........................21-30 Updating a Master Through an Iteration .........................................................21-32

21-1

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 WTParts 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.

How Identity Is Assigned and Managed User-Assigned Identity Attributes


User-assigned identity attributes can be set by a user when an object is created. Unlike other attributes, they cannot be modified after the object is created. However, the user can change the values of identity attributes using the rename operation in Windchill Explorer. This is actually accomplished by calling the changeIdentity operation of the IdentityService. The name attribute of the WTDocument class is an example of a user-assigned identity attribute.

System-Assigned Identity Attributes


System-assigned identity attributes have values that are generated by the system when the object is created. The number attribute for the WTChangeOrder2 class is an example of a system-assigned identity attribute.

Changing an Objects Identity


Currently, all Windchill classes that have user-assigned identity attributes can be modified later by the user, but system-assigned identity attributes cannot be modified by the user. This is not a hard and fast rule, however. For example, a document number could be assigned by a user when the document is created and then never be allowed to change. Or, a default number could be generated by the system, but the user could override this number if desired either when the document is created or at a later date.

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.

21-2

Windchill Customizers Guide

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 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.

Customizing Business Logic

21-3

User-Managed Versus System-Managed Identity


An objects identity is user-managed if the user can either assign or modify its identity attributes. It is important to distinguish user-managed from systemmanaged identity because typically not all identity changes that a user might attempt are valid. For example, a part masters identity includes its name and number. WTPartMaster is user-managed because the user can assign and modify a part masters name and number. Because it is user-managed, a constraint is enforced which requires that no two parts can have the same number. If the part number was assigned by the system, however, it would no longer be necessary to enforce the part number uniqueness constraint because the algorithm that the system uses to generate part numbers guarantees unique part numbers. The interfaces wt.fc.Identified and wt.fc.UniquelyIdentified, which work in conjunction with the IdentityService, are implemented by classes that have usermanaged identity in order to apply validation logic and uniqueness constraints when a user makes a change to an objects identity.

A Special CaseRevisionControlled Identity


Classes that extend RevisionControlled are identified by a version and iteration identifier. The version and iteration are assigned by the system, based on the previous version and iteration. However, because a new version is derived from a user-specified old version, possibly not the latest, a user may cause the same system-generated identity to apply to two separate objects. Because of this behavior, RevisionControlled does not fit the description of either a user- or system-managed identity. A uniqueness constraint must be enforced such that two identical versions of the same master cannot be created. However, subclasses of RevisionControlled do not need to implement the Identified interface, as explained next. Checking out a RevisionControlled object, such as a WTDocument, causes the documents iteration number to increase: A.1 to A.2. In this case, it is clear that the system is managing the identity, and it is impossible for the user to create two different iterations with the same number. Creating a new version conceptually creates a new document with an identity of B.1. Again the system is managing the version identity attribute. However, when both version A.2 and B.1 exist, it is possible for a user to attempt to create a new version from A.2 again. If not prevented, this would create two version B objects. Thus, a uniqueness constraint must be applied that prevents two identical versions of the same master from being created. This situation is unique because the system manages the identity attributes, but the user can instruct the system to create the same object twice, even though it does not directly control the assignment of the version letter. Contrast this to a class such as WTChangeRequest2, where each new change request object is assigned the next unique number from an integer sequence for its identity.

21-4

Windchill Customizers Guide

When to Use the IdentityService


Any class that has user-managed identity attributes must implement the Identified or UniquelyIdentified interfaces. This enables the objects identity to be changed with the IdentityService. The IdentityService provides users of a class that implements the Identified interface a means to change the identity attribute values subject to validation logic and uniqueness constraints. Use the following flowchart to help determine whether a class that has identity attributes should implement the Identified interface, the UniquelyIdentified interface, or neither.

Customizing Business Logic

21-5

How to Use the IdentityService Overview


The following figure illustrates the IdentityService.

IdentificationObject is a non-persistent class that holds the values of the identity attributes from a class that implements the Identified or UniquelyIdentified interface. For a particular business class that implements Identified, a subclass of IdentificationObject is modeled that has the same identity attributes as the business class. Instead of directly changing the identity attributes of the business object, the attributes of the IdentificationObject subclass are used to change the identity, and these values are then copied back to the business object, subject to validation logic and uniqueness constraints, when IdentityService.changeIdentity is called. Any class that implements the Identified interface must implement the getIdentificationObject method, which returns an instance of IdentificationObject that holds the current value of the identity attributes.

21-6

Windchill Customizers Guide

The following sequence diagram illustrates how a change orders identity is modified:

Identified
When a class implements the Identified or UniquelyIdentified interface, the identity attributes of the class must be modeled in a special way. Also, a single method on the Identified interface -- getIdentificationObject -- must be implemented. UniquelyIdentified has no methods to implement. wt.change2.WTChangeRequest2 is used to illustrate the step-by-step instructions. See the class diagram named "request" in the wt.change2 package of the Rose model for reference. 1. Add a public constructor that has arguments for each user-assigned identity attribute. WTChangeRequest2 has a constructor that has a single argument for the name attribute. Number is the other identity attribute but, because it is systemassigned, it does not need to be an argument of the constructor. In the initialize method that is called from the generated factory method for this constructor, the name attribute is initialized. Sequential system-assigned attributes, like numbers, should not be initialized in the constructor, but instead in the PersistenceManager PRE_STORE event processing right before the object is saved. This greatly improves the odds that elements in the sequence are not lost if the create action is aborted by the user. That is, system-assigned attributes are initialized only when it is certain that an object will be persisted. 2. Set the WriteAccess model property to "protected" for all identity attributes.

Customizing Business Logic

21-7

This action prevents general access to the setter methods, allowing only the IdentityService to update the identity attributes of an Identified object. Note: There may be cases where it is necessary to create an uninitialized instance of a class by calling the no-arg constructor, followed by calls to the setter methods to initialize the attributes. This is the case with WTPartMaster and WTDocumentMaster. In this situation, the identity attributes must have public WriteAccess instead of protected. To prevent the use of the setter methods after the object has been persisted, use the "Changeable" property. When set to the value "ViaOtherMeans", the Changeable property causes validation code to be generated in the setter method for the attribute, which allows the method to be used only if the object is not persistent. 3. Implement getIdentificationObject (part of the Identified interface) to return a new instance of the subclass of IdentificationObject that has been designed for this particular Identified class. In the case of WTChangeRequest2, there is a subclass of IdentificationObject called WTChangeRequest2Identity. Following is an example:
public IdentificationObject getIdentificationObject() throws WTException { //##begin getIdentificationObject%3536588B01EEg.body preserve=yes return WTChangeRequest2Identity.newWTChangeRequest2Identity( getNumber(), getName()); //##end getIdentificationObject%3536588B01EEg.body } The following section describes the role of IdentificationObject and how to extend it.

IdentificationObject
Throughout these instructions, the example of wt.folder.SubFolderLinkIdentity is used to illustrate each step. See the class diagram named "Identification" in the wt.folder package of the Rose model for reference. 1. Model a subclass of IdentificationObject in the same package. wt.folder.SubFolderLinkIdentity extends IdentificationObject. Notice that the subclass of IdentificationObject is in the same package as the class that implements Identified, namely SubFolderLink. This is a requirement because SubFolderLinkIdentity must call protected setter methods on SubFolderLink to change the value of its identity attributes.

21-8

Windchill Customizers Guide

2. Add public attributes for each user-assigned identity attribute. For every user-assigned identity attribute of the Identified class, add the same attributes to the subclass of IdentificationObject. In the case of SubFolderLinkIdentity, the identity attributes are subFolderName and parentFolderReference. Making the identity attributes public on the IdentificationObject allows any client to assign a new identity to an object through the IdentificationObject setter methods instead of the ones on the Identified object (see the preceding figure on modifying a WTChangeOrder2s identity). 3. Add a protected constructor that has an argument for the Identified object. The constructor is protected because it is intended to be invoked only in the getIdentificationObject method of the corresponding Identified class, in this example, SubFolderLink. Alternatively, the constructor can have an argument for each identity attribute instead of the entire Identified object. 4. Implement the code-generated initialize method to set the identity attributes from the Identified Object. For every modeled constructor, a static factory method is automatically generated that is implemented to call an initialize method. In this initialize method, call the identity attribute getter methods on the Identified object and set them to the IdentificationObjects identity attributes. That is, copy the identity attributes from the Identified object to the IdentificationObject. Following is an example:
protected void initialize( SubFolderLink link ) throws WTException { //##begin initialize%356993D30199.body preserve=yes setParentFolderReference((ObjectReference)link. getRoleAObjectRef()); setSubFolderName(link.getFoldered().getName()); //##end initialize%356993D30199.body }

5. Implement the getIdentity method. The getIdentity method is not used unless the subclass of IdentificationObject is for a UniquelyIdentified class. If your class implements only Identified, getIdentity can return any String representation of the identity attributes.

Customizing Business Logic

21-9

6. Implement the setToObject method. The setToObject method is invoked by the IdentityService to transfer the values of the identity attributes from the IdentificationObject to the Identified object. Following is the implementation of SubFolderLinkIdentity.setToObject:
public void setToObject( Identified obj ) { //##begin setToObject%356993A900B2s.body preserve=yes // All we have to set is the reference because the name // is managed by the SubFolder object. ((SubFolderLink)obj). setRoleAObjectRef(getParentFolderReference()); //##end setToObject%356993A900B2s.body }

This completes the implementation of the IdentificationObject subclass if the corresponding business class implements Identified. If it implements UniquelyIdentified, then the following two additional steps are necessary: 1. Override the getKeyClassName method. This method returns the name of the class that extends SemanticKey, which is used to store the key value that is subject to the uniqueness constraint for the UniquelyIdentified object. For the SubFolderLinkIdentity example, a private, static String constant is modeled and initialized to the value SubFolderLinkConstraint.class.getName(). Then getKeyClassName simply returns this String constant. 2. Ensure that getIdentity returns a String that represents the uniqueness constraint on the UniquelyIdentified object. Because getIdentity is an abstract method in IdentificationObject, every subclass must implement it. However, it is not actually used unless the subclass of IdentificationObject is for a UniquelyIdentified class. In this case, getIdentity is called to set the value of SemanticKey.key. Remember, this is the String that represents the uniqueness constraint on the UniquelyIdentified object. In this example, getIdentity returns the following string:
getParentFolderReference().getObjectId().getStringValue() + "+" + getSubFolderName();

This String is a combination of the parent folder and subfolder name. This indicates the uniqueness constraint on SubFolderLink is that no two subfolders in a given parent folder can have the same name.

21-10

Windchill Customizers Guide

UniquelyIdentified and SemanticKeys


You must implement the UniquelyIdentified interface in cases where a uniqueness constraint on a user-managed identity attribute applies across multiple classes. This is because every class in the model is mapped to a single database table. Because unique database indexes apply to one table at most, some mechanism in the application layer must be used to enforce the uniqueness constraint. This mechanism is the SemanticKey class found in the wt.fc package. The following sequence diagram illustrates how SemanticKey works:

The preceding figure illustrates the general case. Consider a specific example, WTPartMaster. WTPartMaster has two identity attributes: name and number. Number must be unique across all subclasses of WTPartMaster, so we must implement a SemanticKey. WTPartMasterKey extends SemanticKey and WTPartMasterIdentity extends IdentificationObject. The implementation of WTPartMasterIdentity.getKeyClassName returns "wt.part.WTPartMasterKey" and WTPartMasterIdentity.getIdentity returns the part number. So, whenever a WTPartMaster is saved, the value of the part number is stored in the WTPartMasterKey table. Any subclass of WTPartMaster also stores its number in the same SemanticKey table, WTPartMasterKey. Because there is a uniqueness constraint on the key attribute of the WTPartMasterKey class, unique part numbers are guaranteed across WTPartMaster and all its subclasses.

Customizing Business Logic

21-11

Enforcing Uniqueness Constraints with Database Indexes


Windchill supports the creation of unique database indexes through the model properties Unique and CompositeUnique. Unique database indexes are an efficient way to enforce uniqueness constraints for one or more attributes of a single class. If the uniqueness constraint must apply across multiple classes, such as a base class and all its subclasses, database indexes do not help. In this case, SemanticKey class is used. Database indexes are used to enforce uniqueness constraints on both user- and system-managed identity attributes. See the first figure in this chapter, the identified classes flowchart, to help determine when a database index should be used. The Unique property of an attribute creates a unique index on the database column for that attribute. The following example is for wt.folder.Cabinet, which specifies that its name is a Unique attribute. The SQL DDL generated is as follows:
CREATE UNIQUE INDEX Cabinet$name ON Cabinet(name) STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 )

21-12

Windchill Customizers Guide

The CompositeUnique1 and CompositeUnique2 properties of a class create a unique index across multiple database columns. The following example is for wt.enterprise.RevisionControlled, which specifies that the master + version + iteration + checkout state attributes are unique as a whole.

When using the CompositeUnique property, only two unique indexes can currently be specified in the model. Additional attributes can be added to the index in the subclass by adding them after the "+".

Customizing Business Logic

21-13

The following figure is an example of a composite uniqueness constraint for WTPart.

21-14

Windchill Customizers Guide

How to Implement System-Managed Identity


To implement system-managed identity, perform the following steps: 1. Use database sequences for system-assigned number attributes. Typically, system-assigned attributes are generated as a number sequence. Windchill supplies a utility method that provides access to a sequence of number values maintained by the Oracle database:
public String getNextSequence(Class a_class) throws WTException;

Given a modeled class that implements the DatastoreSequence interface, the getNextSequence method returns a number that is represented as a String. The number value returned is incremented each time the getNextSequence method is invoked for the given sequence name. 2. Listen for the PRE_STORE event on the identified object. The service associated with the Identified object in question must listen for a PersistenceManager PRE_STORE event and assign the number value at this time. For example, for WTChangeRequest2, the ChangeService2 implements the following to assign numbers to change requests:
protected void performStartupProcess() throws ManagerException { //##begin performStartupProcess%35D1B483001F.body preserve=yes /* * Listen for a PersistenceManager PRE_STORE event * on a WTChangeRequest2 */ getManagerService().addEventListener( new ServiceEventListenerAdapter() { public void notifyVetoableEvent( Object event ) throws WTException { PersistenceManagerEvent pmEvent = (PersistenceManagerEvent)event; Persistable target = pmEvent.getTarget(); if (target instanceof WTChangeRequest2) { // assign a number WTChangeRequest2Identity idObj = (WTChangeRequest2Identity)target. getIdentificationObject(); idObj.setToObject(target); } } }, PersistenceManagerEvent.generateEventKey( PersistenceManagerEvent.PRE_STORE)); }

Customizing Business Logic

21-15

3. Implement the setToObject method on WTChangeRequest2Identity:


protected void setToObject( Identified obj ) throws WTException { //##begin setToObject%356DC85D038A.body preserve=yes String number = PersistenceHelper.manager.getNextSequence( Class.forName("wt.change2.ChangeRequest2IdentitySequence"); ((WTChangeRequest2)obj).setNumber(number); //##end setToObject%356DC85D038A.body }

4. Create the sequence as a standalone datastore element, by modeling a class that implements wt.fc.DatastoreSequence. Set the datastore schema name, initial seed value, and increment value from the Rose model. Use the generated database script to create the datastore schema object. For more information, see How Rose UML Maps to Database Schema in the System Generation chapter on page 31-41. In this example, ChangeRequest2IdentitySequence implements DatastoreSequence. Following is an example for WTChangeRequest2:

21-16

Windchill Customizers Guide

Customizing Iteration and Version Identifiers


Both iteration and version series can be customized to better represent a companys way of identifying minor and major changes, respectively. The following is a segment of the wt.properties file where properties exist for these kinds of customizations:
# Seriesfactoryassociations' wt.vc.IterationIdentifier=wt.series.IntegerSeries wt.vc.VersionIdentifier=wt.series.HarvardSeries # Series subclassdefaults' wt.series.IntegerSeries.min=1 wt.series.IntegerSeries.max=2147483647 wt.series.IntegerSeries.delta=1 wt.series.MulticharacterSeries.min=A wt.series.MulticharacterSeries.max=Z wt.series.MulticharacterSeries.delta=1 wt.series.MulticharacterSeries.length=3 wt.series.HarvardSeries.depth=16 wt.series.HarvardSeries.level.1=wt.series.MulticharacterSeries wt.series.HarvardSeries.delimiter=.

Iteration identifiers are by default specified as being an integer series where this series contains whole numbers from a minimum to a maximum value. The default minimum is one (1) and the default maximum is the largest possible 32-bit positive integer value as defined by 2**31-1 (2,147,483,647). There is also a default specification of the delta between adjacent numbers, which is one (1) meaning that, if given 10, the next incremented integer value would be 11 by default. Version identifiers are by default specified as being a harvard series. A harvard series is one that is made up of subseries and is typically depicted as a stream of values delimited by a dot (for example, 1.1, 1.3.5, 1.2.1.1, and so on). Version identifiers must be specified as some sort of multilevel series where the harvard series is currently the only option. This is done to represent both in-lined versions and branched versions in one identifier that forms a version tree. In turn, the harvard series subseries are by default specified as being multi character series at level one and then, because there are no other levels specified, the default from there on is what was specified before for all levels. In this case, it would be multi character series for all levels. If level two was specified as an integer series then, starting at the beginning, every two levels would alternate from a multi character to integer series up to the specified depth as seen below.
wt.series.HarvardSeries.depth=16 wt.series.HarvardSeries.level.1=wt.series.MulticharacterSeries wt.series.HarvardSeries.level.2=wt.series.IntegerSeries

Customizing Business Logic

21-17

Multi character series are specified much like integer series where there is a minimum, maximum, and delta. By default, these properties specify A, Z, and 1, respectively. But there also is another property to specify the length of the multi character series. By default, this is three (3), which means that an identifier of this series would have a range from A to ZZZ, where incrementing from Z of a delta of one (1) would be AA, incrementing from AZ would be BA, and incrementing from ZZ would be AAA. Decrementing follows these same rules except in reverse. If a length of one (1) were specified instead of the default of three, this series would range from A to Z given the same other properties. Any character value for the minimum and maximum can be specified for a multi character series. But only integers can be specified for the minimum and maximum values of an integer series. For additional information, see the "Object Initialization Rules" chapter in the Windchill Business Administrators Guide.

21-18

Windchill Customizers Guide

Customizing a Bill of Materials


Overview
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. Both the BOM generation and formatting can be customized as needed. A BOM report is generated using a template processor. The actual BOM information is generated entirely by Visitor objects. These objects are a means of specifying a "callback" operation for each node in a "tree" data structure. For example, a part structure contains Part objects linked together through the "uses" relationship. Starting from a top-level part, the entire part structure is traversed and a "visit" method is called on the Visitor object passing the current part object and the related usage information. This method can be overridden to provide customized BOM computation and formatting.

Customization
The remainder of this section describes an example of a BOM that is provided out-of-the-box with Windchill. Understanding this example provides a basis for implementing other BOM customizations. There are two types of customization for a BOM. BOM computation refers to the work that is done on each item as the structure is traversed. Windchill provides two types of BOM computation: hierarchy and parts list. The second customization is for formatting the output that is displayed to the user. This formatting is dependent on the type of information displayed.

Customizing Business Logic

21-19

The Hierarchy Visitor is an implementation that shows the quantity and unit attributes of the "usage" associations and visually indicates the hierarchical levels. The only computation that is required is to output this information. This class extends the TextOutputVisitor, which provides standard helper methods for outputting localizable messages to an output stream. In addition to providing the implementation for the "visit" method, this class defines the customization points for altering the format of the output. These methods are designed to be called at various points as the output is being generated.
public abstract class BOMHierarchyVisitor extends TextOutputVisitor { // Define methods that should be overridden to allow for // formatting customization protected abstract void preVisitWrite( int a_level ); protected abstract void postVisitWrite( int a_level ); public void preNavigateWrite() { } public void postNavigateWrite() { } }

The visit method performs a basic output of the part identity and usage information. The preVisitWrite() and postVisitWrite() calls are significant because they allow for formatting customization.
public boolean visit( Persistable fromNode, Link link, Persistable toNode, int level, boolean previouslyVisited ) throws WTException { PrintWriter out = getPrintWriter(); preVisitWrite(level); String partIdentity = ((WTPart) toNode).getDisplayIdentity(); if(link == null) { out.print(partIdentity); } else { // Display part and usage information as a // localized message Quantity quantity = ((WTPartUsageLink) link).getQuantity(); Object[] params = { new Double(quantity.getAmount()), quantity.getUnit().getDisplay(), partIdentity }; printLocalizedMessage(partResource.PART_USAGE, params); } postVisitWrite(level); return true; }

21-20

Windchill Customizers Guide

The BOMHierarchyVisitor class is abstract and therefore cannot be used directly. The formatting must be customized by implementing the preVisitWrite() and postVisitWrite() methods in a descendant class. The following class is a customization example for use when the BOM is displayed in an HTML page. It displays the hierarchical level through HTML heading tags. The methods preVisitWrite() and postVisitWrite() wrap the part information in and tags where n is the level number.
public class HtmlHeadingHierarchyVisitor extends BOMHierarchyVisitor { protected void preVisitWrite( int a_level ) { PrintWriter out = getPrintWriter(); out.print("&lt;H"); out.print(a_level + 1); out.print('>'); protected void postVisitWrite( int a_level ) { PrintWriter out = getPrintWriter(); out.print("&lt;/H"); out.print(a_level + 1); out.print('>'); out.flush(); } }

Soft attributes on parts are displayed in the BOM reports automatically using the table view, but soft attributes on part usage link cannot be displayed automatically. The soft 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 JSP file needs to be customized to indicate the specific soft attributes from the part usage link to display. As an example, if a soft attribute "LinkName" was added to part usage link, the values of that attribute can be displayed by 1. Set up a custom table view with that column as one of the selected columns. 2. Add the following to the describeTable section of the JSP:
<describeColumn id="IBA|LinkName" other settings for the column> /> targetObject="link" <any

After the customization is complete, you need only specify that the new customized class should be used when the BOM is generated. By default, the BOM template processors use the application services mechanism to instantiate a Visitor object that is used to generate the BOM. The service can be replaced by changing the appropriate entry in the services.properties file. Change the following entry in the file:

Customizing Business Logic

21-21

wt.services/svc/default/wt.part.BOMHierarchyVisitor/print/ wt.fc.WTObject/0=wt.part.HtmlNumberedHierarchyVisitor/duplicate

to:
wt.services/svc/default/wt.part.BOMHierarchyVisitor/print/ wt.fc.WTObject/0=wt.part.HtmlHeadingHierarchyVisitor/duplicate

Note the use of the "print" value in the "visitor" key in the service entry. Currently, the Windchill client code displays a BOM designed for printing within an HTML page and therefore uses the value "print". This key value is obtained from the URL parameters by the BOM template processor. If the client were customized to provide other types of BOM formats (by specifying different values in the URL), this key could be used for generating different formats. For example, an additional client function could be added for viewing a BOM with embedded graphics. A new value "graphic" could be used that is associated with a customized Visitor that will generate appropriate graphic output. Both types of formatting would then be available to the user.

Current Implementation of Visitors


The information in this section is useful for understanding the implementation of the current out-of-the-box Visitors. The computation of the Parts List BOM (in BOMPartsListVisitor) uses two separate internal data structures to store information about the part structure as it is traversed. An assembly table keeps track of the current quantity and unit for each subassembly part as successive levels are encountered. A component table keeps track of the nonseparable parts (leaf nodes in the structure) that become the parts list. The assembly table information is maintained by multiplying the parent parts quantity and the current parts quantity. For example, if part A uses 3 of part B, which uses 5 of part C, then 15 of part C are required. The component table stores information for the actual parts that make up an assembly. This is used when generating the final report on the parts list. It is possible that a part can be used in separate branches in the part structure. In these cases, the quantity in each branch should be added. To continue the example, if part A uses 1 of part D, which uses 6 of part C, then the total number of part C for the entire part structure is 21 ((3 * 5) + (1 * 6)). A related issue is how to handle processing the quantities with respect to the quantity units. The following rules are applied: If the units are identical, the new unit is the current unit. If either unit is AS_NEEDED, the new unit is AS_NEEDED. If either unit is EACH, use the other unit.

Both the Hierarchy and Parts List Visitor objects are dependent on a depth first traversal of the part structure. The Hierarchy Visitor outputs the structure as it is traversed so the order in which part nodes are visited is significant. The Parts List computation relies on multiplying quantities between levels and storing the result

21-22

Windchill Customizers Guide

internally. If a part were to appear in separate branches of a structure and depth first traversal were not used, then the computed quantity for a subassembly can be overwritten before its component parts use that information.

Customizing Business Logic

21-23

Customizing User Preferences


This section discusses and gives examples of how you customize the out-of-thebox user preference functionality.

Preference Definition
The preference definition contains all of the static information about a preference which is stored in the database. This definition contains a default value and the constraint (as in the IBA constraints) for what is allowed as a value instance. The preference API returns this default value if a preference value (in the form of a preference instance) is not located in the database. Display information used in the Preference Manager UI is also defined in the preference definition as resource bundle entries. The static information in the preference definition includes the following: Name Default Value Display Name Display Description Display Long Description Visibility (Hidden, Site, Org, Container, User, and User Only) The value handler for processing the preference values

Visibility
The preference definition contains a visibility flag to show who can see a given preference in the Preference Manager. HIDDEN- preference would be one that is not visible in the Preference Manager. SITE - preference is on that is visible only to the Site Administrator. ORGANIZATION - preference is one that is visible to the Site and Org Administrators. Each Org could have a separate instance of the value tied to that Org. CONTAINER - preference is one that would be visible to the Site and Org Administrators and the Container Manager. USER - preference is one that would be visible at all levels. USER_ONLY - preference is one that is settable only at the user level.

21-24

Windchill Customizers Guide

Value Handler (type)


The handler defines the type of preference (Boolean, String, Pick from a list, etc.). The handler interface was designed, so that a type of preference is not limited to only a few select types. The handler interface allows for the specification of how a preference value is edited, stored and displayed. All preference value handlers should be extended from the abstract class com.ptc.windchill.enterprise.preference.handler.AbstractPreferenceValueHandle. Some common out-of-the-box handlers in the com.ptc.windchill.enterprise.preference.handler package: BooleanPreferenceValueHandler CustomPreferenceValueHandler NumberPreferenceValueHandler StringPreferenceValueHandler

Preference Instance
The individual values are set within the preference instance. The preference instance ties the chosen context; Site, organization container, application container (such as a projects, programs, products, or libraries) or user to the preference definition with the value set for the context. If a preference instance is not found in a request for a preference, then the default value defined in the preference definition is returned.

Preference Category
The category is just a means of grouping preferences in the tree structure of the Preference Manager. An individual preference definition is contained within a preference category. A preference category can be contained within another category. This allows for a hierarchical view of the preferences. The preference category has no impact on the actual operation of the system, but is used in the administration of the preferences.

Preference Client
The client was added for UWGM to set preference values by Authoring Applications like AutoCAD, CATIA V5, etc. The default client name if not specified is WINCHILL, defined by the constant wt.preference.PreferenceClient.WINDCHILL_CLIENT_NAME.

The Preference Hierarchy


Preference values set at one level are inherited by the application contexts below. For example, preference values set at the site level are inherited by the

Customizing Business Logic

21-25

organization; application contexts within the organization inherit preference values from the organization.

Note: User preferences may be inherited directly from the organization-level, from individual application contexts, or may be unique (settable only at the user level). Preference values can be set for each application context, or for an individual user, unless the preference value is locked at a higher level. For example, if a preference is not locked at the organization level, then it may have one value at the organization level, but individual products or projects within that organization could each specify a different value. Similarly, if a preference is not locked at an organization level, but is available at the user level, then individual users could each set different values for that preference. Preferences can be locked at any level above the individual user. If a preference is locked, then the value cannot be changed for those lower levels. A site or organization administrator can choose to delete all values for a particular preference that may be set at levels below the current context, usually prior to locking the preference. If a preference is not explicitly set for a particular application context, then the value for that preference is inherited from the level above. For example: If a preference is not set for a particular product or project, then the value set for that preference at the organization level is used. If the preference is not set at the organization level, then the value set for that preference at the site level is used. If no preference is set at any level, then the default value defined for that preference is used.

21-26

Windchill Customizers Guide

Calling preference values


Preference values are retrieved for through the preference service API's in the wt.preference package. To retrieve a single preference value the method to call is:
public Object PreferenceHelper.service.getValue( WTContainerRef containerRef, String definitionName, String clientName, WTUser user );

The above method will return the value at the user context if it exists, otherwise the value set at the container context and so on up the preference hierarchy. Other single preference value methods in the wt.preference package include:
public Object getValue( String definitionName, String clientName ); public Object getValue( String definitionName, String clientName, OrgContainer organization );

The first method retrieves value at the Site context, while the second method retrieves the value at the Organization context and if it does not exist, then the inherited value at the Site is returned. Multiple preference values can be retrieved at the same time. This is more efficient in database calls:
public Map<String, Object> getValues(WTContainerRef containerRef, Collection<String> definitionNames, Collection<String> categoryNames, String clientName, WTUser user)

Example:
Map<String,Object> preferenceMap = null; ArrayList<String> categories = new ArrayList<String>(); ArrayList<String> definitionNames = new ArrayList<String>(); definitionNames.add("PREFERENCE_DEFINITION_1"); definitionNames.add("PREFERENCE_DEFINITION_2"); definitionNames.add("PREFERENCE_DEFINITION_3"); definitionNames.add("PREFERENCE_DEFINITION_4");

Map <String, Object> preferenceMap = PreferenceHelper.service.getValues( containerRef, definitionNames, categories, clientName, user);

Adding Preferences
New preference definitions and categories are added using the LoadFromFile utility to load an XML based load file. This can be run with the following command:

Customizing Business Logic

21-27

windchill wt.load.LoadFromFile -d %WT_HOME%/loadFiles/filename

An example XML preference load file which loads various preference definitions and preference categories is the Windchill/loadfiles/preference.foundation.xml load file. Example Preference Definition:
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader>

<csvPreferenceDefinition handler="wt.preference.LoadPreference.createPreferenceDefinition"> <csvname>PREFERENCE_DEFINITION_1</csvname> <csvvisibility>USER</csvvisibility> <csvcategoryName>UNASSIGNED</csvcategoryName> <csvdisplayName>com...PrefsRB:MYPREF_NAME</csvdisplayName> <csvdescription>com...PrefsRB:MYPREF_SHORT_DESC</csvdescription > <csvlongDescription>com...PrefsRB:MYPREF_DESC</csvlongDescripti on> <csvdefaultValue>false</csvdefaultValue>

<csvhandler>wt.preference.handler.BooleanPreferenceValueHandler : </csvhandler> </csvPreferenceDefinition>

<csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.setClientDefinitionLink"> <csvname>PREFERENCE_DEFINITION_1</csvname> <csvclientName>WINDCHILL</csvclientName> </csvLinkPreferenceClientDefinition>

</NmLoader>

Note: The <csvLinkPreferenceClientDefinition> entry is needed if the preference is to be visible in the Preference Manager UI. The <csvdisplayName>, <csvdescription>, <csvlongDescription> are in the form of rbinfo file/key pair separated by a colon : like the following:
wt.preference.preferenceResource:Unassigned

21-28

Windchill Customizers Guide

The preference category specified by <csvcategoryName> needs to exist otherwise the creation of the preference definition will fail. Example Preference Category:
<csvPreferenceCategory handler="wt.preference.LoadPreference.createPreferenceCategory"> <csvname>UNASSIGNED</csvname> <csvparentName></csvparentName> <csvdisplayName>wt.preference.preferenceResource:Unassigned </csvdisplayName> <csvdescription></csvdescription> </csvPreferenceCategory>

Sub-categories can be created by adding an existing category name to the <csvparentName> element.

Customizing Business Logic

21-29

Writing a Servlet Helper to Use URLFactory Functionality


Servlets within Windchill are accessed by requesting a Web resource that exists under a path with the following format: <Web application>/servlet/<your servlet name> The role and arguments of servlets can vary greatly depending on their application. However, if HREFs and URLs are being generated to the servlet, the URLFactory should be used in conjunction with a servlet helper to add the functionality provided by the URLFactory. The GatewayServletHelper class located in wt.httpgw is a good example of how to create HREFs and URLs to the anonymous and authenticated gateway servlets. A preconfigured URLFactory is taken as the first argument of each method, and this URLFactory is used to create the final HREF or URL accordingly within the method. When writing servlet helpers, keep the following points in mind: All methods should have a URLFactory as their first argument. (See the example that follows.) URLFactory may be null or uninitialized. In this case, the method body should instantiate a new URLFactory for the HREF and URL generation. The method name should follow either of the following helper conventions, where <servlet> is a name representing the servlet: build<servlet>HREF( ) build<servlet>URL( )

The method bodies should take arguments and generate a proper resource path (such as, servlet/WindchillAuthGW), then pass this resource path to the URLFactory getHREF and getURL methods for generating the servlet HREF and URL.

The URLFactory in the JSP Environment section in the Additional Topics - Client Customization appendix on page E-7 gives more detailed reference information on URLFactory usage and encoding/decoding techniques to use in JSP development.

21-30

Windchill Customizers Guide

Example URLFactory Usage/Instantiation


Following is a sample file setting up a default URLFactory implementation in an internationalization environment.
<% // // // bcwti Copyright (c) 2001 Parametric Technology Corporation, all rights reserved. ecwti

////////////////////////////////////////////////////////////////////// // This file is intended to give an example of how the URLFactory // and GatewayServletHelper may be used within // the JSP programming environment. To run this file, simply // place the file in the /Windchill/codebase/wtcore/jsp directory. // Extra whitespace as been left in for clarity and ease of reading. /////////////////////////////////////////////////////////////////////// %> <% /*** The WTContextBean is a JavaBean for use in Java Server Pages or Servlets that wish to use Windchill Java client or server APIs ***/ %> <jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request"> <jsp:setProperty name="wtcontext" property="request" value="<%=request%>"/> </jsp:useBean> <% /*** The URLFactory is a JavaBean for use in the generation of HREFs used in Windchill JSP clients ***/ %> <jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" > <% url_factory.setRequestURL(request.getScheme(),request.getHeader("HOST"), request.getRequestURI()); %></jsp:useBean> <% // The response header for the output stream should be set to UTF-8 response.setContentType("text/html; charset=UTF-8"); // Below we also set the content type in the @page tag, since some // servlet engines %><%@ page import="wt.httpgw.*,java.util.HashMap" contentType="text/html; charset=UTF-8" %> <% // Here we want to generate a link to the Windchill home page through // the default authenticated gateway. For this we will utilize the // wt.httpgw.GatewayServletHelper class to generate a HREF which // from the current URLFactory will generate a link to this site. // %> <BR> <A HREF="<%= wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF( url_factory ) %>">Windchill Home</A> <BR> <% // Perhaps you would like a link to your personal cabinet. In order to // do this, you must generate a link through the authenticated gateway // with a class/method and arguments to invoke like below

Customizing Business Logic

21-31

// String URL_PROCESSOR = "wt.enterprise.URLProcessor"; String TEMPLATE_ACTION = "URLTemplateAction"; // URLFactory and GatewayServletHelper uses HashMap for arguments HashMap map = new HashMap( ); map.put( "Action", "Create" ); // adds the action 'create' to the hashmap map.put( "Class", "wt.doc.WTDocument" ); // adds the class to apply the action // to. %> <A HREF="<%= wt.httpgw.GatewayServletHelper.buildAuthenticatedHREF(url_factory, URL_PROCESSOR, TEMPLATE_ACTION, map ) %>">Create a Document</A> <% // // // // // // // // // // // // // // For optimization, any links generated in the fashion described above could be generated reusing the HashMap and Strings already created. The Setup.jsp file located in codebase/wtcore/jsp/wt/portal/Setup.jsp does just this in the generation of the links thus reducing the overhead in String/HashMap object creation. In the FORM below we use the URLFactory to generate a link to the resource wtcore/jsp/sample.jsp. See the Javadoc for method prototypes. The URLFactory is smart enough to see how it is currently configured and return a String link which should work within the current environment. For the example below, since we are running the file from /WEB-APP/wtcore/jsp the link will generate simply "sample.jsp". Optionally we could have called url_factory.getHREF("wtcore/jsp/sample.jsp",request.getQueryString() ) if we wished to retain the current Query string.

%> <FORM ACTION="<%= url_factory.getHREF("wtcore/jsp/sample.jsp") %>" METHOD="POST"> <INPUT TYPE="text" NAME="Sample_Text" VALUE="<%= prev_value %>"> <INPUT TYPE="submit"> </FORM>

Updating a Master Through an Iteration


Introduction
The master-iteration design pattern (described the Windchill Design Patterns chapter on page 34-1) specifies that the Mastered and Iterated classes work together closely. A class that implements Mastered (henceforth called the master) contains all the version-independent information, whereas the Iterated class (henceforth called the iteration) contains the incremental change that an object undergoes. When applying the master-iteration pattern, it is important to consider whether the master and iteration will be treated as a single logical object or as two distinct objects. Specifically, consider whether a client needs to know that a document is actually composed of an iteration and a master. The Windchill reference implementations WTPart and WTDocument define the master attributes on the iteration as derived attributes, thus hiding the existence of the master from clients. For both WTPart and WTDocument, the only attributes

21-32

Windchill Customizers Guide

on the master are number and name. In addition to being master attributes, they are also identifying attributes. This means that they can be modified only by using the IdentityService after the object has been persisted. The Windchill reference implementation does not have an example of a master class with non-identifying attributes. Currently, there is no support for automatically persisting a master if its non-identifying attributes are updated using derived attributes on the iteration. That is, the attribute could be modified by calling its setter on the iteration, but the client would have to persist the master to save the changes. The following is a discussion of different ways master attributes can be exposed on the iteration and how changes to master attributes through the iteration can be persisted.

Read-only and Queryable Master Attributes on the Iteration


It is quite easy and often desirable to view and/or query attributes from the iteration and master together. This capability is supported at the database level by an auto-navigate feature. That is, when an iteration is retrieved from the database, the association between Iterated and Mastered is auto-navigated to retrieve the corresponding master in a single query. To take advantage of auto-navigate, perform the following actions: 1. Add derived attributes on the iteration for each master attribute that you want to be viewed and/or queried along with the iteration. The "DerivedFrom" model property must be as follows: master> attribute_name For example, part number is modeled on WTPart with the following:
DerivedFrom = master>number

2. To make derived attributes read-only, set their WriteAccess to something other than Public.

Updating Master Attributes via the Iteration


The goal of this action is to be able to automatically update the master if any of its attributes have been modified via derived attributes on the iteration. The advantage is that clients have to deal directly with only one object, the iteration. The recommended approach at a high level is to add a boolean "dirty" flag to the iteration class which is set to true if any of the setter methods that update master attributes are invoked. Next, implement a special save method that clients will use to save the iteration instead of using PersistenceHelper.manager.save(Persistable obj). This method is implemented in a lightweight service class so that it runs on the server in the context of a transaction. It is implemented to check if the dirty flag is true; if so, it will save the master as well as the iteration.

Customizing Business Logic

21-33

Updating the Master and Iteration Separately


Updating the master and iteration separately may be appropriate depending on the business rules. For example, for parts that go through a design review life cycle, modifying a master attribute would affect all versions, some of which are in a "released" state that implies they should not be modified. Changing a master attribute is significant because it violates the basic business rule that released parts should not change. For this reason, the master class could have a more restrictive set of access rules, and any changes to it would be against the master object directly, not derived attributes on the iteration. If this approach is taken, the client must update and persist masters and iterations separately. There may still be derived master attributes on the iteration to facilitate querying and/or read-only access of master attributes via the iteration. However, these attributes would not be set via the iteration.

The Identifying Attributes


The identifying attributes that are part of the master are not updated by calling setter methods, but rather by using IdentityService.changeIdentity. The client must know about the master in order to pass the master to the IdentityService. That is, the iteration can not be passed to the IdentityService. When the IdentityService changes the identity, it re-persists the modified master; thus, the client does not have to directly use the PersistenceManager to modify the master. Master identifying attributes can only be set via the iteration before the object is persisted. When the first iteration is saved, the master is automatically created and saved as well. If you want to expose identifying attributes on the iteration, perform the following steps: 1. Add a derived attribute on the iteration for the master identifying attribute by setting the model property "Derived" to the following: master> attribute_name 2. Set the attribute model property "Changeable" to "ViaOtherMeans" on the master. This allows the attribute to be set only until the object is persisted. After it is persisted, the IdentityService is the only way to change the value. 3. Add a protected setIdentificationObject method to the master which directly sets the identifying attributes on the master from the IdentificationObject values. After the master is persisted, the identifying attributes can be changed only by the IdentityService, which invokes the setIdentificationObject method on the master via the IdentificationObject.setToObject method. For additional information, see Identified Business Classes on page 21-2.

21-34

Windchill Customizers Guide

Overriding Accessors for Master Attributes Derived on the Iteration


Code generation is not yet capable of determining which subtype of Mastered, such as WTPartMaster, is applicable in order to invoke the accessor methods specific to a concrete Mastered class. This means that the accessors must be implemented by hand. Following is an example for WTPart:
public String getName() { /##begin getName% [ ]364F678B0148g.body preserve=yes try { return ((WTPartMaster) getMaster()).getName(); } catch (NullPointerException npe) { return null; } /##end getName% [ ]364F678B0148g.body } public void setName( String a_Name ) throws WTPropertyVetoException { //##begin setName% [ ]364F678B0148s.body preserve=yes ((WTPartMaster) getMaster()).setName( a_Name ); /##end setName% [ ]364F678B0148s.body }

Customizing Business Logic

21-35

21-36

Windchill Customizers Guide

22
Customizing Change Management

This chapter describes how to customize change management. Topic Page

Change Management Delegates ........................................................................22-2

22-1

Change Management Delegates


The wt.change2 package has several delegates defined to allow customization. The following is an overview to help you know where to start.

ChooseLifeCycleDelegate
ChooseLifeCycleDelegate is used within StandardChangeService2 by calling the protected method chooseLifeCycle. In the chooseLifeCycle method, the delegate is obtained from the Change2DelegateFactory. The chooseLifeCycle method is not called if the change object is already persisted, because it would already have a life cycle set. In the chooseLifeCycle method, the delegate mechanism is used only if a life cycle has not yet been set.
// In any of the saveChange... methods, such as saveChangeRequest: If changeItem is not persistent { ChangeServiceHelper2.service.chooseLifeCycle (changeItem); } // In chooseLifeCycle if changeItem has no lifecycle { Set the lifecycle using the delegate; }

When saving a change object, Windchill uses the ChooseLifeCycleDelegate mechanism to assign a life cycle if and only if the change object is not yet persistent and a life cycle is not assigned already. This means that the delegate mechanism is effective only when creating a new change object. As a customization, you could allow the user to select a life cycle from a drop-down list in the HTML page and then, because the life cycle would already be set, the delegate would not replace that life cycle. The DefaultChooseLifeCycleDelegate uses a property file entry to get the name of the life cycle that should be used.

ChooseFolderDelegate
ChooseFolderDelegate is used within StandardChangeService2. It is obtained from the Change2DelegateFactory. The Windchill vision of change management is that change issues, requests and orders should be visible in folders so that a user can easily look for issues (or suggestions), requests (issues that are being addressed), and orders (changes that have been made). The investigations, proposals, analysis activities, and change activities are tightly tied to other objects and they are not visible in folders. Because these related objects need the same access control and other attributes of their related object, which is in a folder, Windchill puts them in the same domain as the related object that is in a folder. The ChooseFolderDelegate assigns one ChangeItem to a folder/cabinet based on the folder/cabinet of another ChangeItem.

22-2

Windchill Customizers Guide

The SynchronizedDomainChooseFolderDelegate assigns a CabinetManaged object to the same domain as a CabinetManaged object or a Folderable object. It assigns a Folderable object to the same folder as another Folderable object. It throws an exception when asked to assign a Folderable object based on a CabinetManaged object. In addition, a listener is defined on the change2 service that listens for movement of change issues, request, and orders. It moves their child objects (analysis activities, change activities, change investigations, and change proposals) to the same cabinet into which the parent object was just moved.

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 exactly the string "wt.change2.WTChangeOrder2".

Customizing Change Management

22-3

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

DisplayIdentificationDelegate
DisplayIdentificationDelegate is used within StandardChangeService2. It is obtained from the Change2DelegateFactory. For further information, see the section on implementing new display identification delegates in the identity service description in the System Generation chapter on page 31-1.

22-4

Windchill Customizers Guide

23
Customizing Life Cycle Administration

This chapter describes how to customize the life cycle administration. Topic Page

Customizing the Display of Life Cycle Information.........................................23-2 Defining Customized Life Cycle Transitions....................................................23-3 Setting Up a Customized State-Based Versioning Scheme ..............................23-3

23-1

Customizing the Display of Life Cycle Information


The way life cycle state information is displayed, particularly in life cyclemanaged 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 ")".
HISTORY_LABEL

This entry is used when displaying a link to the Life Cycle History page. Default is "History".

23-2

Windchill Customizers Guide

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 ") ".

Defining Customized Life Cycle Transitions


You can create customized life cycle transitions that you can then define between life cycle states using the Life Cycle Administrator. For example, to create a new transition called "My Reject": 1. Add the following entry to <Windchill>/wtCustom/wt/lifecycle/TransitionRB.rbInfo (create this file if it does not exist):
MY_REJECT.value=Reject MY_REJECT.shortDescription=Reject transition

2. Build the runtime resource bundles for the customized packages by entering the following command from a windchill shell:
ResourceBuild wt.lifecycle.TransitionRB

The new transition will be added to the transitions that are available when you create or update life cycles using the Life Cycle Administrator. The new transition can be accessed programatically. You can invoke the navigate() method to find the valid transitions between states using that new transition, such as in the following code snippet:
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("MY_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 MY_REJECT transitions.

Setting Up a Customized State-Based Versioning Scheme


Setting up a customized state-based versioning scheme consists of the following:

Customizing Life Cycle Administration

23-3

Adding The Series To StateBasedVersioning.xml And Loading The File Making The Newly Added Version Schemes Available In The Lifecycle Administrator Creating A Lifecycle Template Which Uses The New Version Series Setting Up The Object Initialisation Rules How The Revision Scheme Can Be Used

Adding The Series To StateBasedVersioning.xml And Loading The File


1. Make a backup copy of the StateBasedVersioning.xml file, located under <Windchill80>\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 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_8.0>java.wt.series.LoadFileBasedSeries C:\ptc\ Windchill_8.0>loadFiles\pdmlink\StateBasedVersioning.xml -load

4. You will be prompted to log in as a member of the Administrators group.

23-4

Windchill Customizers Guide

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 enumcustomise utility found in <Windchill>\bin, and the file to modify is the Resource Bundle wt.series.SeriesRangeSelectorRB. 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.

Customizing Life Cycle Administration

23-5

Rebuild the resource:

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.

23-6

Windchill Customizers Guide

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 Initialisation Rules


Set up the Object Initialisation 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 initialisation rule for a WTPart.
<AttributeValues objType="wt.part.WTPart"> <!-- set the folder --> <AttrValue id="folder.id" 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.LifeCycleTemplateAttribute 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>

Customizing Life Cycle Administration

23-7

</AttrValue> <!-- set the team template --> <AttrValue id="teamTemplate.id" algorithm="com.ptc.core.foundation.team.server.impl.TeamTemplateAttributeAlgorithm" > <Arg>Default</Arg> </AttrValue> <!-- set the number to a generated number --> <AttrValue id="number" algorithm="com.ptc.windchill.enterprise.revisionControlled.server.impl.NumberGenera 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> <!-- 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 initialisation 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 Initialisation Rules are customized, the following must be considered. Variant Part Creation fails when Part automatic numbering is turned off; Part Object Initialisation 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 Initialisation Rules xml file for the "number" attribute.

23-8

Windchill Customizers Guide

<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.

Customizing Life Cycle Administration

23-9

Note: The version now shows rel_A, as defined in the StateBasedVersioning.xml file in the beginning.

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.

23-10

Windchill Customizers Guide

24
Customizing Workflow Administration

This chapter describes how to customize workflow. Topic Page

Customizing Workflow HTML Templates .......................................................24-2 Customizing Change Management Workflow Process Templates ...................24-6 Customizing Promotion Request Workflow Processes...................................24-13 Customizing Workflow Events on an Object..................................................24-17 Customizing Workflow Task Pages ................................................................24-19

24-1

Customizing Workflow HTML Templates


This section describes how to customize HTML templates for workflow activities. Following are possible ways you could use this capability: To change the layout of the standard workflow activity property pages to add customer logos and so forth. To add read-only displays of process variables. To integrate information (attributes, icon, associations, and so on) of the primary business object of the workflow. To display a summary of process variables, for example, the voting and comments of different reviewers as the basis for a promote decision.

The functionality to perform all of these customizations is available through existing Windchill scripts, as seen in the standard Windchill HTML client. As a result, you can make these customizations without programming Java (possibly only one resource bundle change), but only editing HTML and some entries in a Windchill properties file. For both an overview and detailed information about customizing HTML clients, see the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-1. This section discusses the HTML client only as it applies to workflow.

24-2

Windchill Customizers Guide

To customize a workflow HTML template, perform the following steps: 1. Create a workflow activity that you want to be represented by the customized HTML page with the workflow administrator applet. The action argument of the activities property page URL is specified by the type of workflow task (see the following figure).

For customizations, you can use the predefined HTML templates UserTask1.html through UserTask7.html, or create your own named templates, for example CustomTask.html. If you create your own task template, you must add an entry to the wt.properties file, as shown in the following example, to cause the new task to appear in the list of available tasks:
wt.clients.workflow.tasks.task.1=WfTask wt.clients.workflow.tasks.task.2=WfUpdateContent wt.clients.workflow.tasks.task.3=WfAugment wt.clients.workflow.tasks.task.4=review wt.clients.workflow.tasks.task.5=promote wt.clients.workflow.tasks.task.6=observe wt.clients.workflow.tasks.task.7=submit wt.clients.workflow.tasks.task.8=WfDefineProjects wt.clients.workflow.tasks.task.9=WfChgMgmt wt.clients.workflow.tasks.task.10=UserTask1 wt.clients.workflow.tasks.task.11=UserTask2 wt.clients.workflow.tasks.task.12=UserTask3 wt.clients.workflow.tasks.task.13=UserTask4

Customizing Workflow Administration

24-3

wt.clients.workflow.tasks.task.14=UserTask5 wt.clients.workflow.tasks.task.15=UserTask6 wt.clients.workflow.tasks.task.16=UserTask7 wt.clients.workflow.tasks.task.17=CustomTask

The default behavior of workflow task processing recognizes these tasks by their template name, for example, CustomTask. If you want to change the display name of your task, you should add entries to the wt.clients.workflow.tasks.TasksRB.rbInfo file as follows:
CustomTask.value="Customized Task Name" CustomTask.constant=MYCUSTOMIZEDTASK

The string "Customized Task Name" is displayed in the drop-down list and must be localized. The string "CustomTask" is the value of the action argument in the URL requests of the HTML page for a workflow activity of that type. 2. Add or modify the appropriate entries in the service.properties and htmltemplate.properties files. If you add an entry in the resource bundle, you must add a line similar to the following in the service.properties file:
wt.services/svc/default/wt.enterprise.TemplateProcessor/ CustomTask/java.lang.Object/ 0=wt.workflow.worklist.WfTaskProcessor/ duplicate

You must also add a line similar to the following in the htmltemplate.properties file:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/ CustomTask/java.lang.Object/0= customizations.workflow.templates.CustomTask

3. Create or modify the HTML template file (customizations.workflow.templates.CustomTask). For examples, see the standard HTML template files listed in the htmltemplate.properties file. The Windchill scripts you can use are defined primarily by the wt.workflow.worklist.WFTaskProcessor and the wt.enterprise.BasicTemplateProcessor (see the Javadoc for further information).

24-4

Windchill Customizers Guide

The following are examples of useful functionality from the more commonly used Windchill scripts: From wt.workflow.worklist.WFTaskProcessor: To print workflow variables, use the following scripts:

activityVariable variable=<Yourvariablename> rows=# columns=# processVariable variable=<Yourvariablename> rows=# columns=#

To print information about the Process, Activity, and PrimaryBusinessObject in the same page, use the following script:

setContextObject context=process | activity| primaryBusinessObject

This script does not print any HTML code but switches the ContextObject of the TemplateProcessor. This means the scripts that follow this script in the HTML page can generate information about the new ContextObject (for example, attribute names and values of the primaryBusinessObject or a table of associated objects). From wt.enterprise.BasicTemplateProcessor: To create a link to another dynamically generated page, use the following script (see the Javadoc for further information):

objectActionLink action="action" [label="label"] labelPropertyName="labelPropertyName" ]

To display the label and value of attributes of a Windchill object, enter the following scripts:

objectPropertyName propertyName="propertyName" objectPropertyValue propertyName="propertyName"

Attributes can be "name", "number", "checkoutInfo", "location", and so on. To display a subtemplate (for example, to display a usedBy-table), enter the following script:

processSubTemplate action="action" [SubTemplate depending name/value pairs]

Most of the time you will have to add entries in the properties files to create new actions and new related HTML template files that hold only a part of an HTML page (for example, a single table).

Customizing Workflow Administration

24-5

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 Change Issue Process Change Issue Process Change Issue Process

Robot

Sync on Request Association Listen for Request Disassociation Sync on Request Complete

24-6

Windchill Customizers 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 change issue has been immediately disassociated with the change request. If so, the workflow cycles back to 1a; otherwise, it continues to the sync robot at 2b. 3a) This conditional router checks the state of the associated change request. If it is in state Completed, the workflow continues to 3b (the end of the process). If it is in state Cancelled, the workflow loops back to a point near the beginning of the process. Otherwise, the workflow continues to the sync robot at 3b.

Customizing Workflow Administration

24-7

2b) The Listen for Request Disassociation sync robot listens for the event ISSUE_UNFORMALIZED on the primaryBusinessObject, signaling the change issue has been disassociated from its change request. This causes the sync robot at 3b () to terminate, and the workflow to loop back to the conditional at 1a.

3b) The Sync on Request Complete robot waits until the state of the associated change request changes. If the state is Completed, the workflow continues to 3b (the end of the process). If it is in state Cancelled, the workflow loops back to a point near the beginning of the process. Otherwise, the sync 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 Change Analysis Process Change Proposal Process Change Order Process Change Activity Process

Sync on Request Submit Sync on Request Submit Sync on Request Submit Sync on Request Submit Sync on Request Submit

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).

24-8

Windchill Customizers Guide

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.

Customizing Workflow Administration

24-9

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 Change Request Process 2 Change Request Process 2 Change Investigation Process Change Proposal Process Change Order Process

Sync on Investigation Sync on Proposal Sync on Change Orders Sync on Analysis Activities Sync on Activities 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.

24-10

Windchill Customizers Guide

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.

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.

Customizing Workflow Administration

24-11

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.

24-12

Windchill Customizers Guide

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

Customizing Workflow Administration

24-13

Promotion Request Review Process

Key Customization Points


You must 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

24-14

Windchill Customizers Guide

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"; } 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.

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.

Customizing Workflow Administration

24-15

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.

24-16

Windchill Customizers 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>/codebase/wt/workflow/robots/synchEventResource.rbInfo:
*/wt.workflow.engine.WfCustomEvent/MY_EVENT.value=MY_EVENT

2. Add the following entries to <Windchill>/codebase/wt/workflow/engine/WfCustomEventType.rbInfo:


MY_EVENT.value = MY_EVENT MY_EVENT.constant = MY_EVENT

3. Rebuild the client JARs (see Rebuilding Client JARs in the Managing Customizations chapter on page 5-18). 4. Clear the Java Plug-in cache on your client machines. 5. Restart the Method Server. 6. 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 Administrators Guide.

Customizing Workflow Administration

24-17

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(); 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.

24-18

Windchill Customizers Guide

Customizing Workflow Task Pages


The new Workflow Task pages need to be designed such that they may be easily customized by the customer. Rendering custom workflow activity variables Rendering PBO UI Components Auto Create Change Notice customization Auto Create Change Notice customization Implementing customized Task Page JSP

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, the user will need to specify either a commadelimited 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 may only be applied to java.lang.String activity variables, and width (only) may 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) will be used, when none is specified. For example, a list of variable names may 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" will display all visible activity variables except for those named "special_instructions", "instructions", or "primaryBusinessObject". The customizer will be 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 will render all_activity_variables. In addition, the Change Management template will also include 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}"/>

Customizing Workflow Administration

24-19

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 will get rendered twice. Once the customizer has described and retrieved the property model (via the workItemInfo.tag), they will then 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.) Render Examples:
<tags:taskPanelValue propertyModel="${propertyModel}" attrs="variable_name"/> <tags:taskPanelValue propertyModel="${propertyModel}" attrs="special_instructions"/> <tags:taskPanelValue propertyModel="${propertyModel}" attrs="all_activity_variables"/>

Rendering PBO UI Components


The info page of a Primary Business Object (PBO) may be included in its entirety (as is already done the in the out-of-the-box Change Management task pages) using the infoPageLink tag file:
<tags:infoPageLink>

A customer may also choose to customize the task form template (i.e., the customized JSP) to only display individual components of the PBO. For example, they might want to include just the top attributes, affected data, affected end items, attachments, attribute detail (including soft or modeled), or related change items. The tag tablePageLink can be used to display one or more tables that are defined together in one custom jsp. The parameter path is the jsp that will be included. The tablePageLink tag can only be used once on a page to render one jsp file and it cannot be used on the same page as infoPageLink.
<tags:tablePageLink path="/netmarkets/jsp/change/affectedEndItemsTable.jsp"/>

24-20

Windchill Customizers Guide

The following table lists the paths that can be used for tablePageLink for a specific object.
PBO Component Path Available Function

Affected Data

/netmarkets/jsp/change/affectedDat aTable.jsp

Change RequestWTChangeRequest2 Change Issue or VarianceChangeIssue Change RequestWTChangeRequest2 Change Issue or VarianceChangeIssue Change TaskWTChangeActivity2 Change TaskWTChangeActivity2 Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion Notice PromotionNotice Change RequestWTChangeRequest2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue

Affected End Items

/netmarkets/jsp/change/affectedEnd ItemsTable.jsp

Affected Items Affected and Resulting Items Attributes and Attachments

/netmarkets/jsp/changeTask/affecte dItemsTable.jsp /netmarkets/jsp/changeTask/affecte dAndResultingItems.jsp /netmarkets/jsp/object/attributes.jsp (no attachments for CA)

Annotations

/netmarkets/jsp/annotation/annotati onChangeTable.jsp

Customizing Workflow Administration

24-21

PBO Component

Path

Available Function

Baselines

/netmarkets/jsp/object/relatedBaseli nes.jsp

Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change Issue or VarianceChangeIssue Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change Issue or VarianceChangeIssue Promotion Notice PromotionNotice Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion Notice PromotionNotice Promotion Notice PromotionNotice

Contexts

/netmarkets/jsp/object/relatedConte xts.jsp

Discussion

/netmarkets/jsp/forum/discuss.jsp

Maturity History

/netmarkets/jsp/history/maturityHis tory.jsp

Promotion Items

/netmarkets/jsp/promotionRequest/ promotionItemsTable.jsp

24-22

Windchill Customizers Guide

PBO Component

Path

Available Function

Reassignment Related Changes /netmarkets/jsp/change/relatedChan ges.jsp Resulting Items Routing/Process /netmarkets/jsp/changeTask/resulti ngItemsTable.jsp /netmarkets/jsp/workflow/processH istory.jsp Subscriptions /netmarkets/jsp/subscription/object Subscriptions.jsp Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change Issue or VarianceChangeIssue Change TaskWTChangeActivity2 Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion Notice PromotionNotice Change RequestWTChangeRequest2 Change Notice WTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion Notice PromotionNotice

Customizing Workflow Administration

24-23

The following table lists the tag files that can be used to include tables. If there is a tablePageLink or infoPageLink these tags must precede it.
PBO Component Syntax for including on JSP

Promotion Notice Table

If the PBO is a PromotionNotice, the customizer may include the promotion objects table as follows:
<workItem:setPrimaryBusinessObject/> <workItem:promotionObjects/>

Notebook Table Discussion Table Routing History Table

<workItem:notebook displayType="Table"/> <workItem:discussion displayType="Table"/>

To display routing history for all activities:


<tags:routingStatus dispProcess="All"/>

To display routing history for just the current activity:


<tags:routingStatus/>

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 Table To display the reassignment history table as embedded and expanded in the JSP:
<tags:reassignHistory showRH="Table"/>

To display the reassignment history table as a link:


<tags:reassignHistory showRH="Link"/>

Auto Create Change Notice customization


The customizer may also re-implement 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 ChangeManagementservice-properties.xconf:

24-24

Windchill Customizers Guide

<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>

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, will be available to the customer as an example page for customization. This JSP will list 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 (e.g., display as a link and as an embedded table).

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 just 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's 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.

Customizing Workflow Administration

24-25

Clicking on 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 will be 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 will be generated using the mapping mechanism as follows:
<ContainerName>_<PBOType>_<ActivityType>_<Template Name>.jsp

Note: It's 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 will be raised.

24-26

Windchill Customizers Guide

25
Customizing Workgroup Managers

This chapter describes how to customize workgroup manager. Topic Page

Customizing and Administering Pro/ENGINEER Wildfire .............................25-2

25-1

Customizing and Administering Pro/ENGINEER Wildfire


See the "Customizing and Administering Pro/ENGINEER Wildfire" chapter in the Using Pro/ENGINEER Wildfire with Windchill guide for information. This chapter presents customization and administration information and recommendations for using Pro/ENGINEER Wildfire integrated with Windchill PDMLink and Windchill ProjectLink. The primary audience is Pro/ENGINEER and Windchill system administrators; however, much of the information can be useful to end users as well. The topics presented include Pro/ENGINEER configuration information (environment variables and config.pro options) that applies to the interaction with Windchill, and Windchill server-side preferences, as well as specific information on parameter mapping, parameter customization, customizing object naming, automated part creation, supporting custom parts, and customizing the user interface. In addition, recommendations for system configuration and performance tuning are offered. The final section lists and describes Windchill preferences that are especially relevant to the interaction with Pro/ENGINEER.

25-2

Windchill Customizers Guide

26
Customizing Windchill Visualization Services

This chapter describes how to customize Windchill Visualization Services. Topic Page

Custom Publishing ............................................................................................26-2

26-1

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.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Java Development

26-2

Windchill Customizers Guide

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 Additional Resources section on page 26-17 includes references to many or all of these subjects.

Solution Elements

Element Publisher.class

Type Class file

Description Contains api for doPublish needed for invoking publishing from code. Runtime Location: <Windchill>\ codebase\com\ptc\wvs\common\ui

PublisherAction.class

Class file

Used to create the optional actionString to be passed to the doPublish method in Publisher. See JavaDoc for details. Runtime Location: <Windchill>\ codebase\com\ptc\wvs\common\ui

VisualizationHelper.class

Class file

Contains helper apis such as findRepresentable and getRepresentation often needed in custom code. Runtime Location: <Windchill>\ codebase\com\ptc\wvs\common\ui

ScheduleJobs.class

Class file

Contains getCurrentContainer method needed when writing custom schedule jobs. Runtime Location: <Windchill>\codebase\com\ptc\wvs\ server\schedule

wvs.properties

Properties file

Contains specific properties used with the Windchill Visualization Service. Runtime Location: <Windchill>\ codebase

Procedure Invoking Publishing from Custom Code/Workflow


This section details how to use the following supported APIs and classes:

Customizing Windchill Visualization Services

26-3

doPublish from Publisher class see Simple Publish on page 26-4 PublisherAction class for advanced use of doPublish see Advanced Publish on page 26-5

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 its 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. 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, My Description, Publisher.EPM, null, 0);

26-4

Windchill Customizers Guide

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 ProductView 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(); }

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,

Customizing Windchill Visualization Services

26-5

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.newObjectReference(mydoc).toString(); PublisherAction pa = new PublisherAction(PublisherAction.DOCUMENTFILE, doc3.doc); Publisher pub = new Publisher(); boolean result = pub.doPublish(true, true, objRef, (ConfigSpec)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.

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 26-6 getRepresentation and getRepresentations from VisualizationHelper class see getRepresentation on page 26-7

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 arent 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 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

26-6

Windchill Customizers Guide

are no actively associated parts, it simply returns the object you passed in. The method signature is shown below:
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)

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)

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 cant 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:

Customizing Windchill Visualization Services

26-7

Creating a custom schedule job step-by-step and using supported api getCurrentContainer from ScheduleJobs class see Custom Schedule Job Fundamentals on page 26-8 Incorporating the use of doPublish from the Publisher class in your custom schedule job see An Advanced Technique for Custom Schedule Jobs on page 26-10

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 myCustomJob();

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 <Property <Property <Property <Property default="MyCustomJob" name="myJob.description"/> default="ext.wvs.CustomJobs" name=" myJob.class"/> default="myCustomJob" name=" myJob.method"/> default="true" name=" myJob.enableOnContainers"/> default="myJob" name="schedulejobs<N>"/>

Line 1 (<Property default="MyCustomJob" name="myJob.description"/>) is what you see identify your custom job.

in the Scheduler UI to

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. 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 4 (<Property default="true" name=" myJob.enableOnContainers"/>) defines whether

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.

26-8

Windchill Customizers Guide

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) { 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; 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; }

Customizing Windchill Visualization Services

26-9

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 section (see page 26-8) 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 the Procedure Invoking Publishing from Custom Code/Workflow section (see page 26-3) with the Custom Schedule Job Fundamentals section (see page 26-8) can open up a lot of flexibility for schedule jobs. 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);

26-10

Windchill Customizers Guide

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); } 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 the Custom Schedule Job Fundamentals section (see page 26-8), but notice the use of the doPublish method shown in bold. This

Customizing Windchill Visualization Services

26-11

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 the Procedure Invoking Publishing from Custom Code/Workflow section (see page 26-3) 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 26-12 publish.service.filterdocumentpublishmethod see Filter Publishing for WTDocument Check-in or Upload on page 26-13 Incorporating the use of doPublish from the Publisher class in your custom hook code see An Advanced Technique for Custom Check-in Based Publishing on page 26-14

Filter Publishing for EPMDocument Check-in

Once publishing is configured for an Authoring Application (i.e. Pro/ENGINEER) 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)

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.

26-12

Windchill Customizers Guide

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)

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.

Customizing Windchill Visualization Services

26-13

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 WTDocuments 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 the Filter Publishing for EPMDocument Check-in section (see page 26-12) and the Filter Publishing for WTDocument Check-in or Upload section (see page 26-13) 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 the Procedure Invoking Publishing from Custom Code/Workflow section (see page 26-3) with the concepts in the Filter Publishing for EPMDocument Check-in (see page 26-12) and Filter Publishing for WTDocument Check-in or Upload (see page 26-13) sections 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);

26-14

Windchill Customizers Guide

return Boolean.FALSE; }

This is the same example used in the Filter Publishing for EPMDocument Checkin section (see page 26-12), 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 the Procedure Invoking Publishing from Custom Code/Workflow (see page 26-3) 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 26-15 Incorporate the use of doPublish from the Publisher class in your custom hook see An Advanced Technique for General Publishing on page 26-16

Filtering All Publishing

In addition to the filters specifically for EPMDocuments and WTDocuments described in the Procedure Customizing Check-in Based Publishing section (see page 26-12), Windchill Visualization Services has a more general hook that is called for 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"/>

Customizing Windchill Visualization Services

26-15

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; }

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 the Procedure Invoking Publishing from Custom Code/Workflow section (see page 26-3) with the Filtering All Publishing section (see page 26-15) 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);

26-16

Windchill Customizers Guide

} 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.

Limitations Customization Boundaries


PTC does not support the customizations of the out-of-the-box CadConvert classes (a.k.a. Publishers), the Worker Agent (f.k.a. CAD 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 the Procedure Creating Custom Schedule Jobs section (see page 26-7) 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 10s or 100s of thousands of results.

Custom Check-in Filtering Performance


Keep in mind with using the check-in filter techniques shown in the Procedure Customizing Check-in Based Publishing section (see page 26-12) 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 Administrators Guide wvs.properties.xconf file in your <Windchill>\codebase directory.

Customizing Windchill Visualization Services

26-17

Related Package/Class Javadoc


com.ptc.wvs.common.ui com.ptc.wvs.server.schedule

Other Related Windchill Documentation


Windchill Business Administrators Guide Configuration Guide Visualization Services Object Adapters

26-18

Windchill Customizers Guide

27
Report Generation
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.

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 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. Topic Page

Overview ...........................................................................................................27-2 Basic Report Example .......................................................................................27-2 Import and Export of Report Templates..........................................................27-11 Customization Details .....................................................................................27-15 Cognos Presentation Customization................................................................27-38 Reporting Info*Engine Task Data Source Customization ..............................27-44 Report Loading................................................................................................27-50 ReportTemplate Data Source Customization ..................................................27-59 Reporting Input Page Customization ..............................................................27-63 Report Localization Customization.................................................................27-68 Report Selection List Customization...............................................................27-74

27-1

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


In this example, a new report is created. The report will list all the objects in a specific cabinet and contain information similar to that displayed when browsing folders. The difference is that this report will show a flattened view as opposed to a hierarchical view. The results displayed in this example reflect demo data that has been loaded. This section includes the following topics: Query Report Parameters

Query
The following steps show how to create the initial query for the report: 1. Create a new report template object and specify the query using the Query Builder user interface, as follows. (For detailed usage instructions, use the Query Builder online help.) a. From Report Manager, click the New button. The Query Builder interface appears (see figure below). b. To add classes for the query, click the Add button on the From tab. Select the Foldered and Cabinet classes. These classes will be used as the basis for the query.

27-2

Windchill Customizers Guide

c. Select the name attribute of these classes by clicking the Add button on the Select tab.

Report Generation

27-3

d. Every foldered object contains a reference to its cabinet. Add a reference join between the foldered object and its associated cabinet by selecting Query > Create Join. In the Create Join dialog box, select these classes and the Cabinet reference association, then click the OK button.

e. Add criteria for filtering the results to only a single cabinet. On the Criteria tab, set the following values, as shown in the following figure:
Field Value

Alias Attribute Operator Value

Cabinet Name = System

27-4

Windchill Customizers Guide

f.

Preview the data to see if the query has been constructed properly by selecting Query > Preview. A figure similar to the following appears.

g. Save the report in Windchill by selecting File > Save.

Report Generation

27-5

2. Execute this report as follows. a. Select Report > Generate. (The Generate Report action is also available when viewing the properties for a report template object.) b. From the report generation form, click Standard, HTML (with sorting), as the output format and click the Generate button.

27-6

Windchill Customizers Guide

Report Parameters
The initial report includes criteria for filtering the results based on cabinet name. In this example, the name is System. For most reports, it is desirable to have parameters that can be specified at execution time. This is accomplished using parameters in the criteria, as shown in the following steps: 1. Edit the Foldered report template to change the criteria to use a parameter, as follows: a. From Report Manager, select the Foldered report and then click the Update button to launch Query Builder. b. On the Criteria tab, change the value of the Type field from "Constant" to "Parameter" and specify a parameter name in the Name field, in this case, "Cabinet Name".

c. Save the report template.

Report Generation

27-7

2. Execute the report, as follows: a. Select Report > Generate. The report generation form now specifies the parameter name, Cabinet Name. b. Enter a valid cabinet name in this field, in this case, System, and click the Generate button. If this field is left empty, the associated criteria is dropped. In this example, if the Cabinet Name field was left empty, the query would return all Foldered objects in any cabinet.

27-8

Windchill Customizers Guide

Another way to specify values dynamically is to use report parameter macros. Macros specify values that are derived by the system at report execution time. An example of a macro is CURRENT_USER_NAME. This macro returns the name of the current user and is useful for showing information related to the user running a report. Macros can be specified for constants and parameters within the Query Builder user interface. You can also enter macro names in the report generation form. The following are predefined macros:
Name Description Type

CURRENT_USER_NAME CURRENT_TIME

Name attribute of the current authenticated user. Current system time. The time is formatted as a Java string using SimpleDateFormat and the method server timezone (specified by wt.method.timezone).

String String

Report Generation

27-9

The following steps show how to put a macro in the report generation form: 1. Edit the Foldered report template to change the criteria to use a macro for the parameter default as follows: a. Select the Foldered report and then click the Update button to launch Query Builder. b. On the Criteria tab, change the value of the Default Value field from "System" to "CURRENT_USER_NAME" using the drop-down list.

c. Save the report template. 2. Execute the report by selecting Report > Generate. The report generation form now specifies the macro and the results show foldered items only in the current users personal cabinet. If demo data has been loaded, several example reports are available within the Windchill folder System/Reports. These sample reports provide examples of the types of reports that are possible. The following section contains more information on loading these sample reports.

27-10

Windchill Customizers Guide

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. 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 element Description

csvfolder

Required. This entry is the location of the report templates in Windchill Explorer. If the specified folder does not exist, one is created. Required. Optional. 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. 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.

csvname csvdescription csvxml

csvxsltype

Report Generation

27-11

csvReportTemplate element

Description

csvservice

If the XSLT designation is DEL, this column is required. The formats currently available are as follows: 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. If the XSLT designation is URL, this column is required and should contain a URL pointing to a customized XSLT stylesheet. 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. Optional. This entry specifies an input page for the Report. Optional. This entry specifies a resource bundle for the Report.

csvurl1

csvurl2

csvinputPage csvresourceBundle

27-12

Windchill Customizers Guide

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 absolute 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. 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.

Report Generation

27-13

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, default 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 container 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

27-14

Windchill Customizers Guide

Customization Details
After a report exists, there are a number of ways to customize various aspects of the report. This section gives detailed information on the following items: Customizing the Query Customizing the Report Format Customizing the Report Generation Client Customizing the Report Generation URL Customizing Macros Customizing Query Builder Types

Customizing the Query


Customizing the query involves editing the query using the Query Builder user interface. An existing query is opened, edited, and then saved. The new query can then be used immediately in reports. The following steps show how to add additional attributes of the foldered object to the query results: 1. Open the existing Foldered report template object using the Report Manager Update button.

Report Generation

27-15

2. From the Select tab, click the Add button. Select the Location attribute and, under Persist Info, select the Last Updated attribute. (To add multiple attributes, hold the CTRL key while selecting them.)

3. Re-order the columns as necessary. 4. Preview the data to make sure the query is correct. 5. Save the query. The existing query is then overwritten. 6. Execute the report.

Customizing the Report Format


Several report 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.

27-16

Windchill Customizers Guide

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:1
http://www.w3.org/TR/REC-CSS1

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. 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:2
http://www.w3.org/TR/xslt

For additional information about XSLT, refer to the What is XSLT? link and the Resources area currently available at the following URL:3
http://www.xml.com

1. 2. 3.

If you have difficulty with this URL, try the site URL www.w3.org. If you have difficulty with this URL, try the site URL www.w3.org. If you have difficulty with this URL, try the site URL www.xslinfo.com.

Report Generation

27-17

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 Stylesheet

Standard Format Name

Description

identity.xsl

XML

Performs the identity transformation on the XML query results; that is, it outputs the XML input. Produces comma-separatedvalues format (useful for reading into spreadsheets, and so forth). Produces tab-separated-values format (useful for reading into spreadsheets, and so forth). Produces a simple HTML format. Unlike the other HTML formats provided, this format does no extra formatting on numeric columns. Similar to simpleHtmlFormat.xsl except that sorting is provided through hyperlinks on the column headers. Similar to simpleHtmlFormat.xsl except that vertically duplicated cells are merged under certain conditions. This is a timeconsuming transformation compared to the others provided.

csvFormat.xsl

CSV (Comma Separated Variable)

tsvFormat.xsl

TSV (Tab Separated Variable)

simpleHtmlFormat.xsl

HTML

htmlWithSorting.xsl

HTML (with sorting)

htmlWithMerging.xsl

HTML (with merging)

27-18

Windchill Customizers Guide

XSLT Stylesheet

Standard Format Name

Description

sortedHtmlAsXML.xsl

Produces the same results as 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. Merges cells in HTML (which must be 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. Microsoft Word 2000 HTML (Landscape) Produces a simple HTML format containing Microsoft Word 2000 metadata. 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. The result has landscape page orientation. Same as msw2000ls.xsl except the result has portrait page orientation.

mergeHTMLCells.xsl

msw2000ls.xsl

msw2000p.xsl

Microsoft Word 2000 HTML (Portrait)

Report Generation

27-19

XSLT Stylesheet

Standard Format Name

Description

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 postprocess 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/post procmap/application/xslfo+xm l 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.

excel97WebQuery.xsl

Produces a version of Excel Web Query (.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-excelweb-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.

27-20

Windchill Customizers Guide

XSLT Stylesheet

Standard Format Name

Description

excel2000WebQuery.xsl

Produces a version of Excel Web Query (.iqy) format compatible only with the Excel version currently supported with Windchill. (For details about which third party 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 llineChart.xsl pieChart.xsl scatterChart.xsl

Produce various types of charts corresponding to their names. The first result column is assumed to contain labels and the rest are assumed to contain chart 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/vie wer/install/main.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/post procmap/image/svg+xml /wt/query/report/template/post procmap/svgRasterizer/rasterF ormat

Report Generation

27-21

XSLT Stylesheet

Standard Format Name

Description

includes/linker.xsl

Provides an XSLT template, 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. The shared implementation behind excel97WebQuery.xsl and excel2000WebQuery.xsl. This stylesheet 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/excelWebQueryBase. xsl

27-22

Windchill Customizers Guide

XSLT Stylesheet

Standard Format Name

Description

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.ChartCreat er" in this file with the name of the custom Chartable implementation. The shared implementation behind 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. The shared implementation behind htmlWithSorting.xsl and sortedHtmlAsXML.xsl. This stylesheet is intended solely for inclusion from other stylesheets. Provides an XSLT named template (that is, 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/msw2000.xsl

includes/htmlWith SortingBase.xsl

includes/localize String.xsl

Report Generation

27-23

XSLT Stylesheet

Standard Format Name

Description

includes/urlEncode.xsl

Provides an XSLT named template for 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.

27-24

Windchill Customizers Guide

XML Resource Bundles


One aspect of the provided XSLT stylesheets (which is shared with those for the Windchill Product Configurator) 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. 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.coms annotated XML specification, currently available at the following URL:4
http://www.xml.com/pub/axml/axmlintro.html

The W3C unannotated, original version of the XML specification is currently available at the following URL:5
http://www.w3.org/TR/REC-xml

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.

4. 5.

If you have difficulty with this URL, try the site URL www.xml.com. If you have difficulty with this URL, try the site URL www.w3.org.

Report Generation

27-25

New Formats
Besides modifying existing XSLT, you can also author entirely new XSLT stylesheets. The XSLT standard is still relatively new, however, and therefore editors that accurately display the actual appearance are not yet widely available. You can, however, author new stylesheets without any such tools 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 Wordbased HTML formats were created); or export an Adobe Illustrator drawing as SVG.6 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.

6.

The use of Apache Batik, as described in the various chart.xsl stylesheets (see the table in the section on Stylesheets Provided earlier in this chapter), provides an alternative means of producing SVG with minimal knowledge of XSLT.

27-26

Windchill Customizers Guide

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> <fullName>Users 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>

Report Generation

27-27

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. 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.

27-28

Windchill Customizers Guide

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. The request parameters used. Fully defines the details of the report template query which was made (see <Windchill codebase>/wt/query/qml/qml.dtd for further details). The query parameters used when executing the query. The column headers and types, and the rows of data.

auxData qml

actualParameters result

Report Generation

27-29

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. 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.ReportSAXTr ansform and should be removed. The format of these entries is that of the Windchilll application services delegation mechanism.For more information see the Customizing service.properties topic in the Developing Server Logic chapter on page 35-24. If localization of the additional entries is required, edit the Java resource bundle wt.query.template.TemplateResource.

Customizing the Report Generation Client


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 the Customizing HTML Clients Using the Windchill JSP Framework chapter on page 10-1. 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). Reports that use soft types (that is, types created using the Type Manager) should 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).

27-30

Windchill Customizers Guide

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

For additional capabilities beyond those provided through this API, you can use the standard JAXP (Java API for XML Processing) APIs, which are part of Java 2 v1.4, 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

27-31

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. 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() );

27-32

Windchill Customizers Guide

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.

Customizing the Report Generation URL


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 forms 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 parameters default value is used. In addition, several other URL parameters, described in the following table, can be used.

Report Generation

27-33

URL Parameter Name

Description

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. Specifies the format type: formatDelegate or formatCustom. This parameter is used only if the report template object has no XSL specification. Specifies the delegate name to obtain an XSL stylesheet from Windchill codebase. The delegate name must match 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". 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 format URL parameter has a value of "formatCustom".

format

delegateName

xsl1

27-34

Windchill Customizers Guide

URL Parameter Name

Description

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.

Customizing Macros
Customizing macros uses the standard Windchill application services delegation mechanism (for further information, see the Customizing service.properties topic in the Developing Server Logic chapter on page 35-24). This customization example creates a new macro to automatically compute a cutoff time. A new query is created that uses this macro and generates a report containing objects that have been modified within the last three days. Note that this example assumes you are familiar with Rational Rose and Windchill code generation, and have completed the previous customization examples. 1. Create a new implementation of the MacroExpressionProcessor interface using Rational Rose and Windchill code generation 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. Generate the code for this class.

Report Generation

27-35

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.
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 new DateExpression(time);

e. Fill in the implementation of the getValue( ) method. This value is the actual Date value as computed in the preceding step. 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

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. c. Add criteria. On the Criteria tab, set the following values as shown in the following table:

Field

Value

Class Attribute Operator Value

Foldered thePersistInfo.modifyStamp > TIME CUTOFF Note that the time cutoff macro now appears in the drop-down list.

d. Save the query. 4. Execute the report.

27-36

Windchill Customizers Guide

Customizing Query Builder Types


Query Builder uses 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 modeled interfaces that do not implement this interface, yet have subclasses that implement a Persistable interface and can be used in queries. An example in the Windchill model 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 (for further information, see the Customizing service.properties topic in the Developing Server Logic chapter on page 35-24). 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.

Report Generation

27-37

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>/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 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 the Reporting Data Source customization best practice documentation in the ReportTemplate Data Source Customization on page 27-59 for more details.

27-38

Windchill Customizers 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

27-39

Solution Elements

Element

Type

Description

<MyDataSource> Cognos Data Source <MyReport> Cognos Report

Cognos Object

The Cognos object that is used to query data from Windchill. The Cognos object for a report that contains the definition of the query and specifies the presentation formatting. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object.

Cognos Object

<MyReport> Windchill Report

Windchill Object

Procedures
This section contains detailed information about the following customization procedures:
Creating a Report

Creating a Report Creating a Report in a non-Site context Deleting 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.

27-40

Windchill Customizers Guide

8. Expose your report to Windchill. Launch Java Console from installed Windchill shortcuts. There are two ways to do this: Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. From the Operations tab, click exposeReports. Select the Edit Table button in Windchill Site/Reports to refresh the page.

9. View the <MyReport> Report in Windchill. The object will be displayed in the Site > Reports tab. 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 the Home > Reports tab 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

27-41

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 the "Product: <MyProduct> > Reports" tab.
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 subfolder) and select the Delete action. 2. Then, use the Windchill UI to locate <MyReport> and select the Delete action. Note: The Reports tab table supports a multiple row delete action if the Reports tab 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. Cognos Reports are subject to the Cognos servers 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

27-42

Windchill Customizers Guide

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 Business 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>/cognos8/documentation/help_docs.html)

Related Windchill Documentation Windchill Business Administration Guide Windchill System Administration Guide

Related Websites
http://support.cognos.com/support

Report Generation

27-43

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 subdirectory <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 Users 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.
Prerequisite knowledge

To achieve this objective, you need to have an understanding of the following: Info*Engine Users Guide

27-44

Windchill Customizers Guide


Solution Elements

The Windchill APIs related to the Windchill business objects that will be used in the Info*Engine task JConsole User Interface Cognos User Interface

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>

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

Report Generation

27-45

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 Users 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

6. Create and Install a package for <MyTask>. See Advanced User Topics > Packages in the Info*Engine Users Guide.

27-46

Windchill Customizers Guide

7. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > 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. 3. In step 5 of the Creating an Info*Engine Task Data Source procedure above, the .delegateInfo entry for typeId should specify myPackage.MyReportTask.

Report Generation

27-47

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.

Additional Resources
Related Best Practices

Reporting - ReportTemplate Data Source Customization Reporting Cognos Presentation Customization

Related Package/Class Javadoc

Reporting module

27-48

Windchill Customizers Guide

com.ptc.windchill.enterprise.report

Related Customization Documentation

None

Other Related Windchill Documentation


Related Websites

Info*Engine Users Guide (Prerequisite) Info*Engine Administration and Implementation Guide Windchill System Administrators Guide

http://support.cognos.com/support

Report Generation

27-49

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 reports 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>/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 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>. 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.

27-50

Windchill Customizers Guide

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:


Solution Elements

Info*Engine Users Guide JConsole User Interface Cognos User Interface ReportManager User Interface Windchill Data Loading

Element

Type

Description

<MyTask>

Info*Engine Task

The Info*Engine task for retrieving and manipulating Windchill data. The Windchill object that specifies a query for retrieving Windchill data. The XML file that specifies a query associated with a Windchill ReportTemplate. The XML file that specifies data loading directives associated with a Windchill ReportTemplate. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object.

<MyReportTemplate> Windchill ReportTemplate <MyReportTemplateQML> Windchill ReportTemplate Query Definition <MyReportTemplateLoad> Windchill Data Load Specification <MyReport> Windchill Report

Windchill Object

XML File

XML File

Windchill Object

Report Generation

27-51

Element

Type

Description

<MyReportLoad> Windchill Data Load Specification

XML File

The XML file that specifies data loading directives associated with a Windchill Report. The Cognos object for a report that contains the definition of the query and specifies the presentation formatting. The XML file that specifies the query and presentation associated with a Cognos Report. The Properties file that specifies attributes associated with a Cognos Report.

<MyCognosReport> Cognos Report

Cognos Object

<MyCognosReportXML> Cognos Report Query and Presentation Definition <MyCognosReportAttributes> Cognos Report Attributes

XML File

Properties File

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 Users Guide. 4. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. 5. Make connection to Tomcat JVM instance. 6. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. 7. 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. 9. Find <MyTask> Data Source under Windchill > Report Tasks > com.ptc.windchill.enterprise.report.ReportTask in the Insertable Objects window under the Source tab.

27-52

Windchill Customizers Guide

Procedure Loading a ReportTemplate Data Source

1. Create the file, <WindchillHome>/loadFiles/reports/custom/<MyReportTemplateQML>.xml using the ReportManager 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 ReportManager in the Site context. 5. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. 6. Make connection to Tomcat JVM instance. 7. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > 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> 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.

Report Generation

27-53

<?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 tab 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/<MyCognosReportAttri butes>.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= #resourceBundle=

5. Load <MyCognosReport> using the following command.


windchill com.ptc.windchill.cognos.CognosProxy loadreports <WindchillHome>/loadFiles/cognosReports/custom

27-54

Windchill Customizers Guide

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 procedure Procedure Loading an Info*Engine Task Data Source 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 procedure Procedure Loading a ReportTemplate Data Source 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 procedure Procedure Loading a Windchill Report Object 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.
Procedure Specifying Windchill Report Object Attributes

In the primary procedure Procedure Loading a Windchill Report Object 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 Element Description

csvname csvcontainerPath

Required. This entry specifies the Reports name. Optional. This entry specifies a container where the report should be stored. If no value is specified, the site container is used by default. Optional. This entry specifies a description of the Report.

csvdescription

Report Generation

27-55

csvReport Element

Description

csvinputPage csvresourceBundle csvuiContext

Optional. This entry specifies an input page for the Report. Optional. This entry specifies a resource bundle for the Report. Optional. This entry specifies the UI context mask to be used to control where the Report is displayed in the Windchill UI. Optional. This entry specifies whether the Report is ready for use for end users. If no value is specified, the default value is false. 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. 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. Optional. This entry specifies the ReportTemplate name if 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. Optional. This entry specifies the ReportTemplate name if 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.

csvreadyForUse

csvsoapClass

csvsoapMethod

csvreportTemplateNa me

csvreportTemplateCon tainerPath

Procedure Loading Multiple Cognos Reports

In the primary procedure above, Procedure Loading a Cognos Report, a single Cognos Report is loaded.

27-56

Windchill Customizers Guide

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 procedure Procedure Loading a Cognos Report 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 Reports type. The valid values are report, query, and reportTemplate. If not value is specified, then the default value is "report". Required. This entry specifies the Reports name. Optional. This entry specifies a description of the Report. 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.

defaultName defaultDescription resourceBundle

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.

Additional Resources
Reporting Info*Engine Task Data Source Customization on page 27-44 ReportTemplate Data Source Customization on page 27-59

Report Generation

27-57

Cognos Presentation Customization on page 27-38

Related Package/Class Javadoc

Foundation module wt.query.template wt.query.qml

Reporting module com.ptc.windchill.enterprise.report

Other Related Windchill Documentation


Related Websites

Info*Engine Users Guide Windchill Data Loading Reference and Best Practices Guide Info*Engine Administration and Implementation Guide Windchill System Administrators Guide ReportManager online help

http://support.cognos.com/support

27-58

Windchill Customizers 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 ReportManager 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.

Solution
Use ReportManager 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 Generation

27-59


Solution Elements

ReportManager 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

Element

Type

Description

<MyReportTemplate> Windchill ReportTemplate

Windchill Object

The Windchill object that specifies a query for retrieving Windchill data.

Procedure Creating a ReportTemplate Data Source

1. Navigate to the Windchill Site > Utilities and launch the Report Manager utility. 2. From the Report Manager 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. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > 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.

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.

27-60

Windchill Customizers Guide

1. Assume you have ReportTemplate create access in the organization <MyOrg>. 2. In step 1, navigate to the Utilities tab under <MyOrg> instead of the Site Utilities tab. 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 ReportManager 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:
windchill wt.load.LoadFromFile d <WindchillHome>/loadXMLFiles/DemoReports.xml CONT_PATH /

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 27-44 Cognos Presentation Customization on page 27-38

Report Generation

27-61

Related Package/Class Javadoc

Foundation module wt.query.template wt.query.qml

Reporting module com.ptc.windchill.enterprise.report

Other Related Windchill Documentation


Related Websites

ReportManager online help (Prerequisite) Query Builder online help (Prerequisite) Windchill System Administrators Guide

http://support.cognos.com/support

27-62

Windchill Customizers 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>/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 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

27-63

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> <MyReport> Windchill Report

JSP File Windchill Object

The custom JSP page for specifying report input parameter values. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object.

Procedure Specifying a Windchilll JSP Input Page


1. Create a Windchill JSP page, <WindchillHome>/codebase/wtcore/jsp/<MyInputPagePackage>/<MyInputP age>.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> <% String paramName = param1; String defaultInputValue = default1;

27-64

Windchill Customizers Guide

%> 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 tab, 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 tab 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 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.

Report Generation

27-65

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 reports Data Source. The following is an example for specifying this.
<input type="hidden" name="paramA" value="valueA"/> <input 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 reports Data Source. The following is an example for specifying this.
<% request.setAttribute("parametersToOmit", Arrays.asList("param1")); %>

Limitations
None.

27-66

Windchill Customizers Guide

Sample Code Examples of Usage in Windchill Code


All of the out-of-the-box reports use Windchill JSP input pages.

Related Websites
http://support.cognos.com/support

Report Generation

27-67

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. 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.

27-68

Windchill Customizers Guide

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 ReportManager User Interface

Solution Elements

Element

Type

Description

<MyTask> <MyTaskResource> <MyReportTemplate> Windchill ReportTemplate <MyReportTemplateResource > <MyReport> Windchill Report

Info*Engine Task Resource Bundle Info Properties File Windchill Object Resource Bundle Info Properties File Windchill Object

The Info*Engine task for retrieving and manipulating Windchill data. The resource bundle info file used to localize Info*Engine task text items. The Windchill object that specifies a query for retrieving Windchill data. The resource bundle info file used to localize ReportTemplate text items. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object. The resource bundle info file used to localize Report text items. The Cognos object for a report that contains the definition of the query and specifies the presentation formatting.

<MyReportResource> <MyCognosReport> Cognos Report

Resource Bundle Info Properties File Cognos Object

Report Generation

27-69

Element

Type

Description

<MyCognosReportResource>

Resource Bundle Info Properties File

The resource bundle info 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. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, "Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > 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 Manager" utility. From the "Report Manager" UI, select <MyReportTemplate>, and click "Update" to launch QueryBuilder. 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. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, "Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > 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

27-70

Windchill Customizers Guide

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" tab, 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 and Procedure - Localizing a ReportTemplate Data Source), 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.

Customization Points Procedure - Localizing Cognos Report Static Text


When the above Procedure - Localizing a Cognos Report 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/<MyCognosReportXM L>.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

Report Generation

27-71

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/<MyCognosReportAttri butes>.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.

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 Package/Class Javadoc


Foundation module wt.query.template Reporting module com.ptc.windchill.enterprise.report

Related Customization Documentation


Internationalization and Localization on page 39-1

27-72

Windchill Customizers Guide

Other Related Windchill Documentation


Info*Engine User's Guide Info*Engine Administration and Implementation Guide Windchill System Administrators Guide ReportManager online help

Related Websites
http://support.cognos.com/support

Report Generation

27-73

Report Selection List Customization


Several part related reports can be launched from the parts information page by clicking the corresponding report item from the "Related Reports" drop-down list. Previously, this list of these reports and the order in which the reports were displayed in the list could not be customized. The report list infrastructure has been enhanced to allow the following customizations: Customizing the order of the reports in the list Removing one or more reports from the list Adding new custom reports to the report list at any place in the list

Scope/Applicability/Assumptions
The processes described in this section are applicable to the following report types: Part Part Configuration Part Instance

This section describes the process for customizing the report selection list. It does not include information on how to author a report or load a report into a third party reporting system. For any custom reports, it is assumed that they have been authored and that a JSP file exists for each custom report that needs to be hooked up to the existing report list. It is assumed that the person doing the customization has access to make the updated to <WindchillCodebase> directory.

Solution
The following section describes the process of customizing the report selection list in detail.

Solution Elements

Element service.properties

Type properties

Description Configuration point for mapping new <CustomDelegate> to ProductStructureReportListDelegate interface Run time Location: <Windchill>\codebase\service.properties

27-74

Windchill Customizers Guide

Element <CustomDelegate>.java <customReport>.jsp partReportResource.rbInfo

Type java jsp Resource bundle

Description Implement the methods to create the Related Reports drop-down list. Used to gather some of the parameters that needs to generate a report or pass on to another report generator. Optional. Used to define the localized names for reports Runtime location: <Windchill>/codebase/com/ptc/windchill/enterprise/part/ structure

Overview
1. Implement and compile the custom delegate that defines the list of reports, including any custom reports to be displayed in the Related Reports drop down in the Product Structure Browser. 2. Author the Custom Report JSP file (and other related artifacts) corresponding to the custom report(s) into the <Windchill>/codebase. 3. Add and build the localization entries for the custom report(s) and build the localization resources. 4. Register the custom delegate by replacing the out of the box with the custom delegate. 5. Restart Windchill for your changes to take effect.

Implement and compile the custom delegate


To customize the report list for a part, part instance, or part configuration, you need to implement a custom delegate. There needs to be a separate custom delegate for part reports, part instance reports, and part configuration reports. The custom delegate must extend from AbstractProductStructureReportListDelegate and must implement the required method generateReportSelection. This is the method that contains the logic to generate the report list. AbstractProductStructureReportListDelegate has several helper methods (specific to part report list, part instance report list and part configuration report list) that can be used by this logic. Refer to the Javadoc for AbstractProductStructureReportListDelegate for details on the helper methods.
Sample Code: Adding a new custom part report at the end of the existing part report list

If you want to add a new custom part report at the end of the existing (out of the box) part report list. Assume that the new custom report has a JSP file netmarkets/jsp/part/custom/myCustomReport.jsp.

Report Generation

27-75

import com.ptc.windchill.enterprise.part.structure.AbstractProductStructu reReportListDelegate import com.ptc.windchill.enterprise.part.structure.partReportResource public class ProductStructureCustomPartReportListDelegate extends AbstractProductStructureReportListDelegate { public void generateReportSelection() { // Generate out of the box report list super. generateOutOfTheBoxReportList(); // Append Custom Report at the bottom // partReportResource.CUSTOM_REPORT_LABEL is resource label for the custom report // name and is defined later in the document super.generateCustomReport (partReportResource.CUSTOM_REPORT_LABEL, " netmarkets/jsp/part/custom/myCustomReport.jsp "); } }

Sample Code: Remove existing part reports from the report list

The following example shows the code to remove some of the existing part reports from the list.
import com.ptc.windchill.enterprise.part.structure.AbstractProductStructu reReportListDelegate public class ProductStructureCustomPartReportListDelegate extends AbstractProductStructureReportListDelegate { public void generateReportSelection() { // Selectively add only the reports of interest // Single-Level BOM super.generateSingleLevelBOM(); // Single-Level BOM with Notes super.generateNoteReport(); // Single-Level Consolidated BOM super.generateSingleLevelConsolidatedBom(); // Multi-Level Components List super.generateMultiLevelComponentList(); // HTML Multi-Level BOM super.generateMultilevelBOM(); // Multi-Level BOM Compare

27-76

Windchill Customizers Guide

super.generatePLMMultilevelBomCompareQuery(); // Multi-Level BOM with Replacements super.generateMultiLevelBOMWithReplacement(); // Multi-Level Where Used super.generateMultilevelWhereUsed(); }

Author the Custom Report JSP file

The JSP file has the following information available as HTTP request parameters.
Parameter Name hostName sessionId oid Description Windchill installed machine IP address Windchill servlet session ID Context Object Reference of the persisted primary content item (part, or part configuration or part instance) Version Reference of the context part. Only exists if the report was invoked from part info page. Version Reference of the context part instance. Only exists if the report was invoked from part instance info page. Value String (Usually an IP address) String String Example: OR:wt.part.WTPart.:11045 String VR:wt.part.WTPart.:34023 String Example: VR:wt.part.WTProductInstance2:580 54 String Example: VR:wt.part.WTProductConfiguration :32168 true or false

part

part_instance

part_configuration

Version Reference of the context part configuration. Only exists if the report was invoked from part configuration info page. A Boolean indicating whether to apply configuration specification to the top level object criteria A Boolean indicating whether to use Latest Configuration Specification for unresolved dependents Base64 encoded configuration specification criteria.

applyCSToTop

applyDCSToUnresolved

true or false

encodedConfigSpec

String

In case your reports require the access to the encoded configuration specification, you can use ProductStructureReportSelectorHelper.decodeConfigSpec(encodedConfigSpec) to decode the configuration specification. ProductStructureReportSelectorHelper

Report Generation

27-77

can be found in the runtime location: <Windchill>/codebase/com/ptc/windchill/enterprise/part/structure.


Example <customReport>.jsp

This is an example of how to access the JSP parameters.


<% String hostName = request.getRemoteHost(); String sessionId = session.getId(); String oid = (String)request.getParameter("oid") ; String applyCSToTop = (String)request.getParameter("applyCSToTop") ; String part = (String)request.getParameter("part") ; String encodedConfigSpec = (String)request.getParameter( "encodedConfigSpec" ); String applyDCSToUnresolved = (String)request.getParameter("applyDCSToUnresolved") ; %> <table cellpadding="0" cellspacing="0"> <tr><td> <table width ="100%" cellpadding="0" cellspacing="0"> <THEAD><b>My Custom Report<br></b></THEAD> <table width ="100%" cellpadding="10" cellspacing="1" border="1"> <tr> <td align = "left" valign="top"><font size="-1"><b>Parameter Name</b></font></td> <td align = "left" valign="top"><font size="-1"><b>Parameter Value</b></font></td> </tr> <tr> <td align = "left" valign="top"><font size="1">hostName</font></td> <td align = "left" valign="top"><font size="-1"><%=hostName%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="1">sessionId</font></td> <td align = "left" valign="top"><font size="-1"><%=sessionId%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="-1">oid</font></td> <td align = "left" valign="top"><font size="-1"><%=oid%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="-1">part</font></td> <td align = "left" valign="top"><font size="-1"><%=part%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="1">applyCSToTop</font></td>

27-78

Windchill Customizers Guide

<td align = "left" valign="top"><font size="-1"><%=applyCSToTop%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="1">applyDCSToUnresolved</font></td> <td align = "left" valign="top"><font size="1"><%=applyDCSToUnresolved%> </font></td> </tr> <tr> <td align = "left" valign="top"><font size="1">encodedConfigSpec</font></td> <td align = "left" valign="top"><font size="1"><%=encodedConfigSpec%> </font></td> </tr> </table> </tr> </table>

Sample Report Output

This is an example of the output generated by this JSP.


Parameter Name hostName sessionId oid part applyCSToTop applyDCSToUnresolved encodedConfigSpec Parameter Value 132.253.8.149 D180CB2067B751629C8BA557A355D11D wt.part.WTPart:78035 VR:wt.part.WTPart:68117 false false rO0ABXNyABh3dC5wYXJ0LldUUGFydENvbmZpZ1NwZWMAAAAAA AAAAQQAAHhyABR3dC5lbnRlcnByaXNlLlNpbXBsZQAAAAAAAAA BBAAAeHIADnd0LmZjLldUT2JqZWN0AAAAAAAAAAEEAAB4cLWF MlThpvDmcNMGeSFFACwBAQ . Add and build the localization entries

1. To have the localized name for your custom report, add a new resource entry in the <WindchillCodebase>/com/ptc/windchill/enterprise/part/structure/partReport Resource.rbInfo file. The localized report name can be used in the Related Report drop-down list, or as the title in your custom report. For more information see the Resource Info (.rbInfo) Files section on page 37-7 in the Internationalization and Localization chapter. For example:
CUSTOM_REPORT_LABEL.value=My Custom Report

Report Generation

27-79

CUSTOM_REPORT_LABEL.constant=CUSTOM_REPORT_LABEL CUSTOM_REPORT_LABEL.comment=Label for Pick a Custom Report drop down item

2. Build the resource bundle by executing the following command from a windchill shell:
ResourceBuild com.ptc.windchill.enterprise.part.structure.partReportResource

Register the custom delegate

Register the newly implemented custom delegate into <WindchillCodebase>/service.properties. The service delegate mechanism uses Java property files to specify the delegates that are used for each service. The main property file is service.properties and located in /Windchill/codebase/. For more information, see the Property Files section on page 2-9 in the The Windchill Development Environment chapter. For a Part report, execute the following command from within <Windchill> directory in Windchill shell:
xconfmanager -s wt.services/svc/default/com.ptc.windchill.enterprise.part.struc ture.ProductStructureReportListDelegate/reportSelector/wt.part. WTPart/0=<Qualified Path>.<CustomDelegate>/duplicate -t service.properties -p

For a Part Instance report, execute the following command from within <Windchill> directory in Windchill shell:
xconfmanager -s wt.services/svc/default/com.ptc.windchill.enterprise.part.struc ture.ProductStructureReportListDelegate/reportSelector/wt.part. WTProductInstance2/0=<Qualified Path>.<CustomDelegate>/duplicate -t service.properties -p

For a Part Configuration report, execute the following command from within <Windchill> directory in Windchill shell:
xconfmanager -s wt.services/svc/default/com.ptc.windchill.enterprise.part.struc ture.ProductStructureReportListDelegate/reportSelector/wt.part. WTProductConfiguration/0=<Qualified Path>.<CustomDelegate>/duplicate -t service.properties -p

Restart Windchill

You must restart the following for the changes to take effect: Apache Tomcat ServerManager Method Server

27-80

Windchill Customizers Guide

28
Customizing Event Audits
This chapter describes how the Windchill Auditing Framework is implemented and explains how to extend the auditing framework to allow additional events to be audited. Topic Page

Introduction .......................................................................................................28-2 Overview of the Audit Event Framework .........................................................28-3 Capturing New Events.....................................................................................28-10

28-1

Introduction
The auditing framework provides a mechanism to enable event-based logging that provides a historical record of who did what that caused changes in the Windchill database. The security auditing feature also provides a mechanism to retain historical records of security related events, such as privilege changes, team changes, and denial of access. Security audit reporting is helpful to customers in highly regulated industries that need to identify events that may have resulted in a potential security breach. The following list provides possible application uses that can be recorded: Who accessed the application? Who viewed or downloaded an object? Who changed this object? Who granted access to a specific user?

The Windchill Auditing Framework is a Windchill service that captures events generated through normal application use, using a collection of classes and configuration files that a customer modifies to indicate which specific events are to be recorded in the audit log. Out-of-the-box, the auditing framework is enabled at the global level. However, the only events that are enabled are License Usage Reporting and Organization Usage. Any other specific events that you want recorded in the audit log must be enabled on an individual basis.

28-2

Windchill Customizers Guide

Overview of the Audit Event Framework


The auditing configuration file (<Windchill>/codebase/registry/auditing/configAudit.xml by default), defines event/object pairs which need to be audited. Based on its configuration, the auditing service registers itself as a listener for each auditable event which may be generated by other Windchill services. Auditing only registers itself once per event regardless of how many objects are being audited for that event. The auditing service's listener is called when an event for which the auditing service has registered is emitted by a Windchill service. After determining that the event's target object is being audited, the auditing service determines which call handler, or audit recorder, is responsible for processing the event. The auditing recorder stores the event information in one or more tables. Common event information is stored in the AuditRecord table by the default auditing recorder. Some events have additional information which must be audited, using eventspecific tables and recorders. Audit reports are generated from the auditing data stored by the recorders. Audit reports are currently not customizable. The figure below shows a conceptual view of the Windchill Auditing Framework.

Windchill Auditing Framework

Customizing Event Audits

28-3

ProjectAuditEvent Class
The ProjectAuditEvent class represents the basic auditing information being stored for a single event. The ProjectAuditEvent class contains the following information:
Attribute Name eventKey Description Every AuditRecord corresponds to a Windchill event (wt.events.KeyedEvent). This attribute is the Windchill event key. This is the localized value of the external label for the event represented by this AuditRecord. It is translated into the server's locale when the AuditRecord is recorded in the database Time of the event. Organization the current user belongs to at the time the event was emitted. The name of the target object of the event. A reference to the target object of the event. Name of the user that is the current principal when the event happened. Identifier of the object that is the target of the event. IP address of the client machine used when the event was emitted. Type of the object that is the target of the event. Numeric ID of the control branch of the type of the target of the event. Identifier of the object that is the target of the event. Number of the object that is the target of the event. Cage code of the object that is the target of the event. Numeric ID of the control branch of the object that is the target of the event. Numeric ID of the working copy branch of the object that is the target of the event. Version ID of the object that is the target of the event.

eventLabel

eventTime userOrgName targetName targetReference userName userID IPAddress targetType targetTypeBranchID targetID targetNumber cageCode branchID workingBranchID versionID

28-4

Windchill Customizers Guide

Attribute Name masterID orgContainerID orgContainerName appContainerID appContainerName appContainerTypeBra nchID folderPath domainPath targetIdentity lifecycleState transactionDescription

Description Identifier of the master of the object that is the target of the event. Identifier of the organization that hosts the application container that owns the object that is the target of the event. Name of the organization that hosts the application container that owns the object that is the target of the event. Identifier of the application container that owns the object that is the target of the event. Name of the application container that owns the object that is the target of the event. Numeric ID of the type of the application container that owns the object that is the target of the event. Folder path of the object that is the target of the event. Domain path of the object that is the target of the event. Identity of the object that is the target of the event. Lifecycle state of the object that is the target of the event. Transaction description associated with the transaction from which the event was emitted.

The information contained in the AuditRecord class is sufficient for most events. In certain situations, however, the Windchill Auditing Framework is required to capture additional information specific to the event generated. The event-specific information is stored in an event-specific table and is managed by an eventspecific object. For example, when a user is added to or removed from a group, it is important to note which user is involved and not just that the group membership was modified. The class ModifyGroupEventInfo holds the additional information as a reference to the user being added or removed. If multiple users were added or removed in a

Customizing Event Audits

28-5

single operation, all ModifyGroupEventInfo instances point to a single AuditRecord instance. This is shown in the figure below.

Default and specific event information

28-6

Windchill Customizers Guide

Audit Recorders
For each class which manages event data stored in the database, a corresponding audit recorder exists which is responsible for mapping the appropriate event information to the members of the class. The AuditRecord class, representing the base information stored for all events, is created and persisted by wt.audit.configaudit.DefaultAuditEventRecorder. Each class representing event-specific information also has a corresponding audit recorder. For example, wt.audit.configaudit.ModifyGroupEventRecorder extends the default recorder and creates the ModifyGroupEventInfo instances.

Example Audit Recorder Data Model

Windchill Auditing Framework Configuration


The configAudit.xml configuration file identifies which objects are being audited for which event and what audit recorder to use. The top-level <EventConfiguration> contains one or more <KeyEntry> and <ConfigEntry> elements. The <KeyEntry> elements identify which events should be treated as multi-object events (available only as of 8.0). EventConfiguration dtd (part 1)
<!ELEMENT EventConfiguration (KeyEntry*, ConfigEntry*)> <!ATTLIST EventConfiguration enabled (true | false) #REQUIRED > <!ELEMENT KeyEntry EMPTY> <!ATTLIST KeyEntry eventKey CDATA #REQUIRED multiObject (true | false) #REQUIRED >

At the global level, the enabled attribute for <EventConfiguration> determines whether the Windchill Auditing Framework is loaded and initialized. If enabled="false", no auditing occurs and rest of the configuration file is not processed. To enable the Windchill Auditing Framework, set the enabled attribute to true as shown below. Any changes to this configuration file will require a method server restart in order to take effect.

Customizing Event Audits

28-7

Enabling the Windchill Auditing Framework


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE EventConfiguration SYSTEM "configAudit.dtd"> <EventConfiguration enabled="true">

The <ConfigEntry> element identifies the events to be audited for a specific class. The class attribute identifies a fully qualified class name to be audited. Within the <ConfigEntry> element there are additional elements defining the specific events being monitored for the class and which audit recorder persists the event information. Originally, these sub-elements were specific to an event type; PersistenceManagerEventEntry for PersistenceManagerEvent, AccessControlEventEntry for AccessControlEvent, etc. New in X-05, the KeyedEventEntry element allows the event class to be explicitly defined and should be used exclusively going forward. ConfigEntry dtd (part 2)
<!ELEMENT ConfigEntry (KeyedEventEntry | WIPEventEntry | WfEngineEventEntry | PersistenceManagerEventEntry | ActionItemEventEntry | ProjectServiceEventEntry | AccessControlEventEntry | ProjectManagementEventEntry | RenameEventEntry | CustomEventEntry | GroupEventEntry | ForumEventEntry | VCEventEntry)*> <!ATTLIST ConfigEntry class CDATA #REQUIRED enabled (true | false) #REQUIRED > <!ELEMENT KeyedEventEntry EMPTY> <!ATTLIST KeyedEventEntry eventKey CDATA #REQUIRED enabled (true | false) #REQUIRED handler CDATA "wt.audit.configaudit.DefaultAuditEventRecorder">

The enabled attribute for each <ConfigEntry> element determines whether a specific Windchill class, as defined by the class attribute, is to be audited. To enable auditing for a specific class, set the enabled attribute to true as shown in the example below. It is important to note that auditing is only enabled for this class if auditing is also enabled at all parent levels. Also, any changes to this configuration file will require a method server restart in order to take effect. Enabling class-level auditing
<ConfigEntry class="wt.org.WTGroup" enabled="true"> <KeyedEventEntry eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHAN GE" enabled="true" handler="wt.audit.configaudit.ModifyGroupEventRecorder"/> </ConfigEntry>

As described above, each <KeyedEventEntry> element maps an event to an audit recorder. The eventKey identifies the fully-qualified classname for the event

28-8

Windchill Customizers Guide

being audited. The handler attribute identifies the fully-qualified classname for the audit recorder. If omitted, the default audit recorder is used. The enabled attribute for each <KeyedEventEntry> element determines whether a specific event (defined by the eventKey attribute) for a specific class (defined in the <ConfigEntry> parent element) is to be audited. To enable auditing for a specific event, set the enabled attribute to true as shown in the example below. Once again, auditing is only enabled for this event if auditing is also enabled at all parent levels and any changes to this configuration file will require a method server restart in order to take effect. Enabling event-level auditing
<KeyedEventEntry eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHANGE" enabled="false" handler="wt.audit.configaudit.ModifyGroupEventRecorder"/>

Customizing Event Audits

28-9

Capturing New Events


In many situations, the event auditing defined out-of-the-box meets the customer's need and the only customization required is enabling or disabling auditing, as appropriate. However, out-of-the-box auditing requirements continue to expand and certain customers require auditing customizations. Auditing may be extended in two ways to meet the additional requirements: Auditing additional events and capturing default information about the event. Auditing additional events and capturing event-specific information.

Capturing default information about a new event.


When additional events to be audited are identified, often capturing default information is sufficient to meet the auditing requirements. In this case, the DefaultAuditEventRecorder can be used and the additional auditing can be implemented without any coding changes. This type of customization will only require changes to the auditing configuration file.

Extending Auditing For Class


If the class to be audited is already being audited for other events, the configuration file can have an additional <KeyedEventEntry> element added defining the new event. Extending the auditing for a class
<ConfigEntry class="wt.org.WTGroup" enabled="true"> <KeyedEventEntry eventKey="*/wt.org.OrganizationServicesEvent/MEMBERSHIP_CHANGE" enabled="true" handler="wt.audit.configaudit.ModifyGroupEventRecorder"/> <KeyedEventEntry eventKey="*/<event_class>/<event_type>" enabled="true" handler="wt.audit.configaudit.DefaultAuditEventRecorder"/> </ConfigEntry>

Adding New Auditing For Class


If the class to be audited is not currently being audited, the configuration file can have a new <ConfigEntry> element for the new class and event. Adding new auditing for a class
<ConfigEntry class="<audit_class>" enabled="true"> <KeyedEventEntry eventKey="*/<event_class>/<event_type>" enabled="true" handler="wt.audit.configaudit.DefaultAuditEventRecorder"/> </ConfigEntry>

28-10

Windchill Customizers Guide

Capturing new event-specific auditing information.


Auditing for certain events requires event-specific information to be captured in addition to the default information identified above, which requires coding changes. There are three changes which need to occur: Create a new event info class Create a new event recorder Modify configuration file

Create New Event Info Class


To store the event-specific information, a new "event info" class is created. This is basically a modeling exercise, creating a new class which implements the Externalizable interface and extends the wt.audit.eventinfo.AbstractEventInfo abstract class. The Windchill attribute for tablespace must be overridden and set to WCAUDIT, the Oracle tablespace in which all auditing tables are created. The figure below shows the model for wt.audit.eventinfo.ModifyGroupEventInfo, which is currently implemented.

Modeling a new event info class

Create New Event Recorder


The new recorder extends the wt.audit.configaudit.DefaultAuditEventRecorder class. The recorder needs to override one or both of the persistMultiObjectEvent() or persistEvent() methods, depending on whether the event is handling one or multiple objects with a single event. The steps are similar for both: Start a new transaction Call the parent's method to capture the default event information Store the event-specific information for each target object

Customizing Event Audits

28-11

The following examples show an implementation of persistMultiObjectEvent() and an implementation of persistEvent(). For multiple objects, notice the optimization to create a collection of event-specific event info classes and to pass the collection to the persistence layer. Example: persistMultiObjectEvent method
protected WTCollection persistMultiObjectEvent( KeyedEvent anEvent ) throws WTException { Transaction trx = new Transaction(); try { trx.start(); WTCollection auditRecordCol = super.persistMultiObjectEvent(anEvent); int numObjs = auditRecordCol.size(); WTCollection eventInfoCol = new WTArrayList(numObjs); for (Iterator i = auditRecordCol.persistableIterator(); i.hasNext(); ) { AuditRecord record = (AuditRecord)i.next(); Persistable target = record.getTargetReference().getObject(); <event_info_class> eventInfo = <event_info_class>.new<event_info_class>(); // Set event and target specific attributes here eventInfo.setAttribute1(target.getAttribute1()); eventInfo.setAttribute2(target.getAttribute2()); // These two attributes are always required eventInfo.setDomainRef(record.getDomainRef()); eventInfo.setRecord(record); eventInfoCol.add(eventInfo); } PersistentObjectManager.getPom().insert(eventInfoCol, null, null); trx.commit(); trx = null; return recordCol; } catch (WTPropertyVetoException pve) { throw new WTException (pve); } finally { if(trx != null) { trx.rollback(); }

28-12

Windchill Customizers Guide

} }

Example: persistEvent method


protected AuditRecord persistEvent( KeyedEvent anEvent ) throws WTException { Transaction trx = new Transaction(); try { trx.start(); //Store the base data. AuditRecord record = super.persistEvent(anEvent); Persistable target = (Persistable)anEvent.getEventTarget(); if (anEvent instanceof <event_class>) { <event_class> newEvent = (<event_class>)anEvent; <event_info_class> eventInfo = <event_info_class>.new<event_info_class>(); // Set event and target specific attributes here eventInfo.setAttribute1(newEvent.getAttribute1()); eventInfo.setAttribute2(target.getAttribute2()); // These two attributes are always required eventInfo.setDomainRef(record.getDomainRef()); eventInfo.setRecord(record); PersistentObjectManager.getPom().insert(eventInfo, null, null); } trx.commit(); trx = null; return record; } catch (WTPropertyVetoException pve) { throw new WTException(pve); } finally { if (trx != null) { trx.rollback(); } } }

Customizing Event Audits

28-13

28-14

Windchill Customizers Guide

29
Customizing Communication Tools

Windchill provides tools that enable your team to communicate and collaborate effectively, such as support for meetings, subscriptions, and discussion forums. This chapter describes how to customize communication tools, where such customization is supported in Windchill. Topic Page

Customizing Meetings.......................................................................................29-2 Customizing Action Items (Windchill ProjectLink Only) ................................29-3

29-1

Customizing Meetings
Windchill PDMLink, and Windchill ProjectLink provide the ability to customize the authentication scheme used for Webex meetings. A delegate object, implementing the WebexUserInfoDelegate interface, is used to create the account name and password. To perform this type of customization, you need to write a class that implements the interface WebexUserInfoDelegate and substitute that for the default delegate provided out of the box with Windchill. 1. Write your customized WebexUserInfoDelegate. Write a class that implements the wt.meeting.WebexUserInfoDelegate interface. See your installed Javadoc for details on the WebexUserInfoDelegate API. Any class that implements this interface must conform with all Webex requirements. For example, names, email addresses, and passwords must conform to the Webex requirements listed in the Webex API documentation. If storing any information is required to make this work, that is also the responsibility of the implementor. 2. Include the compiled class in the Windchill codebase in the same way that you include other customizations. 3. To make Windchill actually use the new delegate, modify the service delegate mapping according to the procedure described in the Customizing service.properties topic in the Developing Server Logic chapter on page 35-24. In service.properties, the out of the box entry for WebexUserInfoDelegate is as follows:
wt.services/svc/default/wt.meeting.WebexUserInfoDelegate/default/java.lang.Object/0 =wt.meeting.DefaultWebexUserInfoDelegate/singleton

In your new mapping, replace


wt.meeting.DefaultWebexUserInfoDelegate

with your customized

delegate.

Sample code for WebexUserInfoDelegate


A code sample is provided with Windchill to assist you in creating your own class that implements the WebexUserInfoDelegate interface. The code can be found in <Windchill>/src/wt/meeting/DefaultWebexUserInfoDelegate.java. Caution: While the sample code includes an implementation of the DefaultWebexUserInfoDelegate class used by Windchill, this is provided for example purposes and as a possible template on which to base your implementation. When using it as such, be aware that this sample code is not necessarily up-to-date.

29-2

Windchill Customizers Guide

Customizing Action Items (Windchill ProjectLink Only)


In Windchill ProjectLink, action items have, in addition to standard attributes, several customizable attributes. These attributes cover a variety of formats such as date, percentage, number with decimals, and string. Some customizable attributes are exposed in the user interface out-of-the-box. You can expose or hide any of these attributes, reorder them, or designate whether they are required by modifying attributeConfig.xml in the code base. You can also create or modify the attribute display names through the associated resource bundle. These attributes are all modeled attributes to ensure the best performance and scalability. Note: When searching for action items on the Advanced Search page, all attributes are available, including those not currently exposed in the user interface. The following table describes the customizable action item attributes:

Name

Exposed in UI by Default

Description

Action Plan Actual Effort Comments Contacts Contingency Cost Cost Impact Customers Date Design Cost Estimated Effort Impact Location Percent Phase Prevention

No Yes Yes No No No Yes No No No Yes Yes No No No No

String 4000 characters Integer number of hours String 4000 characters String 4000 characters String 4000 characters Monetary real number Monetary real number String 4000 characters Date Monetary real number Integer number of hours String 4000 characters String 4000 characters % String 200 characters String 4000 characters

Customizing Communication Tools

29-3

Name

Exposed in UI by Default

Description

Probability Production Cost Quantity Rank Resources Risk

Yes No No Yes Yes Yes

String 200 characters Monetary real number Integer Integer String 4000 characters Enumerated value (same as for activities) Unavailable Very High High Medium Low Very Low

Risk Description Risk Type Schedule Impact Size Suppliers Supporting Information Time Tooling Cost

Yes Yes No No No No No No

String 4000 characters String 200 characters + or days Real number String 4000 characters String 4000 characters hh:mm Monetary real number

Exposing or Hiding Customizable Attributes


To expose or hide a customizable attribute in the user interface: 1. Open the attributeConfig.xml file located at <Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the location where Windchill Services is installed. 2. Modify the appropriate <attribute> element. Use the resourceKey to locate the attribute you want to expose or hide, and set the enabled= value to true (to expose) or false (to hide).

29-4

Windchill Customizers Guide

The following example from the attributeConfig.xml file 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 located at <Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the location where Windchill Services is installed. 2. Modify the appropriate <attribute> elements. Use the resourceKey to locate the attributes you want to reorder, and assign values to the order attribute of each in the numeric order in which you want the attributes to display.

Designating Customizable Attributes as Required


To designate a customizable attribute as required: 1. Open the attributeConfig.xml file located at <Windchill>/codebase/wt/meeting/actionitem, where <Windchill> is the location where Windchill Services is installed. 2. Modify the appropriate <attribute> elements. Use the resourceKey to locate the attribute you want to designate as required, and set the required= value to true.

Changing the Display Names of Customizable Attributes


To change the display name of a customizable attribute, please refer to the Changing Displayed Text Found in RBINFO Files section in the Managing Customizations chapter on page 5-9.

Customizing Communication Tools

29-5

29-6

Windchill Customizers Guide

IV
Services and Infrastructure Section

Chapter

Page

Windchill Services ............................................................................... 30-1 System Generation ............................................................................... 31-1 Customizing Modeled Elements .......................................................... 32-1 Enumerated Types................................................................................ 33-1 Windchill Design Patterns ................................................................... 34-1 Developing Server Logic ..................................................................... 35-1 The Enterprise Layer............................................................................ 36-1 Persistence Management...................................................................... 37-1 Advanced Query Capabilities .............................................................. 38-1 Internationalization and Localization................................................... 39-1 Customizing Archive, Purge, and Restore ........................................... 40-1 Import Export Framework ................................................................... 41-1 Evolvable Classes ................................................................................ 42-1 Creating Large Objects (LOBs) ........................................................... 43-1 Customizing Data Formats................................................................... 44-1

30
Windchill Services
This chapter describes the various Windchill services. Topic Page

Windchill Packages ...........................................................................................30-2 Engineering Factor Services..............................................................................30-2

30-1

Windchill Packages
Windchills functionality that is, its services and utilities is generally separated into Java packages. These packages are available in the wt and com.ptc directories within the Windchill codebase directory. You can use these packages as you build new applications and customize existing applications. Model files are provided so you can extend some of the classes in the models and then generate code for them. This section lists a subset of the packages available for use in customizations and gives an overview of their functionality. Some of the packages are described in further detail in other chapters of this guide, or in the accompanying Javadoc for the package.
access

Functionality for access control; used to define access policies (that is, define rules for what principals have access to what information). See the wt.access class entry in your installed Windchill Javadoc for more information.
admin

Functionality to create administrative domains and policies. See the wt.admin class entry in your installed Windchill Javadoc for more information.
content

Functionality for handling content data (attaching files and URLs to content holders, such as documents and change objects) and associating business information metadata (such as the author) with content. See the wt.content class entry in your installed Windchill Javadoc for more information.
content replication

Functionality for increasing the speed at which users can access data. Data is stored on more rapidly accessible external vaults known as replica vaults. Base packages cannot be extended or modified in any way. Additional information about content replication is discussed in the Windchill System Administrators Guide.
effectivity

Functionality to assert that a PDM object is effective under certain conditions. See the wt.eff and wt.effectivy class entry in your installed Windchill Javadoc for more information.
epm

The engineering service (wt.epm package) provides functionality to create and manage CAD model related objects. See the wt.epm and subpackages entry in your installed Windchill Javadoc for more information.
federation

The federation service (wt.federation package) provides functionality to create and manage proxy objects of remote systems and perform utility functions supporting the federation system. See the wt.federation class entry in your installed Windchill Javadoc for more information.

30-2

Windchill Customizers Guide

folder

Functionality to put information into folders and cabinets for navigational purposes. See the wt.folder class entry in your installed Windchill Javadoc for more information.
fv

Functionality to define and execute the vaulting algorithm for content items. See the wt.fv class entry in your installed Windchill Javadoc for more information.
identity

Functionality to display the identity of business objects; that is, their type and identifier (for example, a type of part and an identifier of part number). See the wt.identity class entry in your installed Windchill Javadoc for more information.
Import and Export

Windchill Import and Export can assist you in moving complete Windchill content and metadata to and from Windchill sites and Windchill ProjectLink portals by placing the data in Jar files. See the wt.ixb subpackages entry in your installed Windchill Javadoc for more information.
index

Functionality to index metadata and content data, controlling how information is put into search indexes. See the wt.index class entry in your installed Windchill Javadoc for more information.
lifecycle

Functionality to define and use life cycles. See the wt.lifecycle class entry in your installed Windchill Javadoc for more information.
locks

Functionality to lock and unlock objects. See the wt.locks class entry in your installed Windchill Javadoc for more information.
notify

Functionality to define rules and create subscriptions such that when certain events occur to certain objects, E-mail notification is sent. See the wt.notify class entry in your installed Windchill Javadoc for more information.
org

Organization services; functionality to create users and groups (generically called principals). See the wt.org class entry in your installed Windchill Javadoc for more information.
ownership

Functionality to define ownership of an object. See the wt.ownership class entry in your installed Windchill Javadoc for more information.
project

Functionality to create projects, associate projects to business objects, and resolve roles to principals.

Windchill Services

30-3

queue

Functionality to define and manage queues. Queues are used to persistently record deferred processes. Because queued processes are persistently stored, they are guaranteed to execute at a later time. See the wt.queue class entry in your installed Windchill Javadoc for more information.
session

Functionality to define and manage user sessions. See the wt.session class entry in your installed Windchill Javadoc for more information.
vc

Version control; functionality to handle versions of objects. Version control services described in this chapter include baselines, configuration specifications, version structuring, version viewing, and work in progress. See the wt.vc subpackages entry in your installed Windchill Javadoc for more information.
workflow

Functionality to create and manage workflow definitions, initiate and manage process instances, and distribute work items to users and groups. See the wt.workflow and subpackages entry in your installed Windchill Javadoc for more information.

30-4

Windchill Customizers Guide

Engineering Factor Services


The EPM classes implement a programming model designed to perform the following activities: Allow the loading of CAD models (including information about family tables) into a Windchill database Relate the CAD models to parts in the enterprise Support the propagation of changes made to the models into the enterprise parts

EPM provides Windchill knower and doer classes that allow the engineer to express the structure of a CAD model and to load the CAD files into the Windchill database. EPM also provides background services that ensure data consistency in the database. Windchill supports the concept of a build operation, which allows a graph of dependencies in one set of objects (called target objects) to be maintained automatically as a by-product of changes to another set of objects (called source objects). EPM implements a build operation specific to creating part objects from describing CAD documents. For more information, see the appropriate Javadoc.

Handling CAD Models


CAD models are represented in EPM by EPMDocument objects. If the CAD model has an associated family table, each line in the family table is represented by EPMDocument. This section describes EPMDocuments and its associated links in more detail.EPMDocument
EPMDocument Model

An EPMDocument can represent a component or an assembly, using other EPMDocuments as components. (This concept is described further in the section on Handling Model Structure later in this section.) As shown in the following model, EPMDocument implements a number of Windchill interfaces that allow it to be used in various Windchill services:
RevisionControlled

Allows the EPMDocument to be checked in and out


Baselineable

Allows the EPMDocument to be stored in a baseline


FormatContentHolder

Allows the EPMDocument to have content


DocumentVersion

Allows the EPMDocument to be treated as a document by the Windchill Explorer

Windchill Services

30-5

BuildSource

Allows the EPMDocument to be used by the Windchill build mechanism to maintain a part structure
SupportingDataHolder

Allows the EPMDocument to have EPMSupportingData. An EPMSupportingDataHolder can hold arbitrary Java objects, each tagged with a name and an owner application name. This allows an application to store application-specific data with the EPMDocument without having to extend the Windchill schema.
EffectivityManageable

Allows the EPMDocument to be assigned an effectivity.


GraphicallyRepresentable

Allows the EPMDocument to have generated graphic representations that can be viewed and marked up in a view tool.

EPMDocument Model

30-6

Windchill Customizers Guide

Because the EPMDocument is RevisionControlled, a corresponding EPMDocumentMaster exists, which also implements Windchill interfaces:
UniquelyIdentified

Allows the EPMDocument name to serve as a unique identifier


DocumentMaster

Provides a version independent reference to an EPMDocument.


Storing content on EPMDocument

EPMDocument is a Windchill ContentHolder (as shown in the figure above) and, thus can contain data files, URLs, or both. This allows the engineer to upload the actual Pro/ENGINEER model file (for example, the .ASM file) and maintain it in the Windchill database. An EPMDocument can contain a number of ContentItems. This allows EPM to store alternate representations of the CAD model (produced by the topology bus, for example) in the same document. Content is maintained using the normal Windchill ContentService.
Creating an EPMDocument

An EPMDocument must be created via the factory method newEPMDocument: EPMDocument doc = EPMDocument.newEPMDocument ( <number >, <name >, <EPMAuthoringAppType authoring App >, <EPMDocumentType docType>, <CADName>); The number of the document must be unique within the Windchill database. The ownerApplication is an EnumeratedType indicating the application that intends to manage changes to the document. The concept of owner application is no 2 set via a call to EPMContextHelper.setApplication (EPMApplicationType appType), where EPMApplicationType is an EnumeratedType. Set the "current application" for use by checking code. This value is cached on the client-side, but is also sent (via the EPMContextManager) to the server-side SessionContext. Once setApplication () has been called, all objects created will be tagged with the specified application. For Pro/ENGINEER authored CADDocuments, CADName needs to be specified. EPM Services ensure that CADName is unique in a Windchill database.

Handling Family Instances


If the CAD model has an associated family table, each line in the family table is represented by a separate EPMDocument. As shown below, relations between these EPMDocuments are handled by two types of links viz. EPMContainedIn and EPMVariantLink. The EPM ContainedIn relation is an Object to Object link that associates two EPM Documents where one holds an object that is physically contained in the other, such as a family instance and the Pro/ENGINEER model that holds the family table.

Windchill Services

30-7

EPM Variant Link is an Iteration to Master link that denotes that an EPM Document is a variant of another EPM Document.

30-8

Windchill Customizers Guide

Handling Model Structure EPMDependencyLink


When an EPMDocument represents an assembly, it uses other EPMDocuments via EPMMemberLinks. It can also reference other EPMDocuments via EPMReferenceLinks; reference links are non-structural, but are used to include objects that provide scenery, or constraints. Both EPMMemberLinks and EPMReferenceLinks are types of EPMDependencyLink (shown in the following figure), which is used to represent the concept of one EPMDocument depending on another.

Windchill Services

30-9

The EPMDependencyLink represents a relation between two EPMDocuments. EPMStructureService can be used to read the EPMDependencyLinks between EPMDocuments. A number of interfaces similar to the following are available:
public QueryResult navigateUses( EPMDocument document, QuerySpec querySpec ) throws WTException;

EPMMemberLink
The EPMMemberLink represents the use of one model by another. It includes data such as quantity and positioning, as shown in the following figure.

EPMReferenceLink
The EPMReferenceLink represents reference to an object by a model. While an EPMMemberLink can use only another EPMDocument, any Iterated object can be referred to (for example, a specification in Microsoft Word). The relationship between an EPMDocument containing a drawing and the EPMDocument containing the model is represented using an EPMReferenceLink. The direction of this link should be such that the drawing describes the model. The model never describes the drawing.

30-10

Windchill Customizers Guide

The Relationship Between CAD Models and WTParts


Please note that the Build Model will change in future releases. To prepare for this change, many of the classes and methods from the build package have been deprecated. These classes and methods will be replaced. Please refer to the Javadoc to see the deprecated classes and methods. Windchill defines a build process, which is used to publish usage links and attributes (see the following figure).

Build Model

You cannot associate an EPMBuildRule to an EPMDocument that has an effectivity assigned to it. To create an EPMBuildRule, you must first have created the WTPart and EPMDocument that you intend to relate. In addition, the WTPart, but not the EPMDocument, must be either checked out or in your personal folder. Currently, only one subtype of EPMBuildRule is implemented EPMBuildLinksRule. This rule allows for the publication of usage links to the part structure (see the following figure).

Windchill Services

30-11

Build Rule To create the rule, you must use the factory method defined on the class: EPMBuildLinksRule rule = EPMBuildLinksRule.newEPMBuildLinksRule ( <document >, <part); Once this has been done, you can use the Windchill build process to publish the document structure to the part structure. This can be done in either of two ways: By building the EPMDocument: BuildHelper.service.buildTarget (<document >,<config spec >); By building the WTPart: BuildHelper.service.buildTargetsForSource (<part >,<config spec >); If you are building a vaulted WTPart, the build process creates a new iteration of the WTPart. If the WTPart is either checked out or in your personal folder, no new iteration is created; instead, the usage links on the latest iteration are changed to reflect the results of the build.

30-12

Windchill Customizers Guide

31
System Generation
When you have finished modeling, the next step is system generation. Using Windchill extensions to Roses original functionality, Windchill generation tools generate Java code, Info files containing class metadata used by the runtime environment, and database DDL from the models you create. This chapter describes how to use the system generation tool and how the classes you model in UML (in Rose) correspond to the code that is generated. Topic Page

Overview of System Generation .......................................................................31-2 How Rose UML Maps to Java Classes .............................................................31-3 Implicit Persistable Associations Stored with Foreign ID References............31-21 Extending the EnumeratedType class .............................................................31-36 How Rose UML Maps to Info Objects ...........................................................31-39 How Rose UML Maps to Database Schema ...................................................31-41 How Rose UML Maps to Localizable Resource Info Files ............................31-47 Using the Windchill System Generation Tool ................................................31-50 Using Windchill System Generation in a Build Environment ........................31-54 Deploying Modeled Customizations ...............................................................31-60

31-1

Overview of System Generation


The figure below shows the system generation process.

System Generation Overview

Using the models in the Rational Rose repository, the Windchill export tool produces mData files. The system generation tools then use the mData files to produce Java code, Info files (metadata used by the runtime environment), and database schema. mData files have a non-proprietary file format so that, in the future, different modeling tools can be used without rewriting portions of the system generation tool. The following sections describe how the Rose UML is mapped to each of the types of output (Java code, Info files, and database schema). The final section of this chapter describes how to run the system generation tool.

31-2

Windchill Customizers Guide

How Rose UML Maps to Java Classes


You control aspects of system generation by specifying values within Rose for the following model elements: Classes Operations Attributes Associations and their roles Generalize relationships Dependency relationships

The following sections, which describe how each of these elements are mapped to Java, also include the specifications you must set for each kind of element to ensure the correct code is generated. Within the Rose dialogs where you set these values, there are other tabs and fields. Any tabs or fields not described in this manual are either ignored by the system generation tools or have preferred default values. The figure below shows a sample specification dialog in Rose. To access this dialog, double click on an item in a diagram; or select a diagram item, then select Open Specification from the right click pop-up menu. Rose displays a specification that corresponds to the item you selected. The documentation for

System Generation

31-3

code generated items is placed in the generated source code in the format of Javadoc style comments.

Rose Specification Dialog

Mapping Modeled Classes to Java


Classes modeled in Rose will be generated as Java classes or interfaces. An interface will be generated when the class is modeled with the Interface stereotype. The figure below shows a class modeled in Rose that is mapped to Java.

Model of a Class

31-4

Windchill Customizers Guide

Copyright Statement
Rose provides for a default copyright, and also for a copyright to be specified for a particular package. This copyright statement is generated into the Java source code for each class.

Package Statement
The package statement corresponds to the Rose UML package that owns the class. For example,
// Example of a generated package statement package example;

Import Statements
Java import statements are generated based on references made to other classes through the following model elements: Class and Interfaces inherited by the class. Dependencies modeled for the class. Non-Persistable Association types. Attribute types declared by the class. Argument type s specified by the methods of the class. Return value types specified by the methods of the class. Exceptions thrown by the methods of the class.

For example,
// Examples of a generated import statements import example.MyAddress; import example.MySize; import java.lang.String; import java.sql.Date; import java.util.Vector; import wt.fc.Item; import wt.pds.PersistentRetrieveIfc; import wt.pds.PersistentStoreIfc; import wt.pom.DatastoreException; import wt.util.WTException; import wt.util.WTPropertyVetoException; //##begin user.imports preserve=yes //##end user.imports

The generated import statements depend on input from the classRegistry.properties file (discussed later in this chapter) that contains a list of classes and their associated packages.

System Generation

31-5

The user.imports section is provided as a safe place for the developer to enter additional imports to support the implementation of the class. This section is preserved during subsequent generations of the class. To better support use of Integrated Development Environments (IDEs), the generator also preserves imports found outside of the user.imports block. If the (trimmed) text of the import line doesn't begin with the word "import", it won't be preserved. Anything within a preserve=yes block is ignored. When it finds unmanaged import statements, it moves them into the user.imports preserve block and adds a comment to indicate how it got there.
//##begin user.imports preserve=yes import unmodeled.UnmodeledOne; // Preserved unmodeled dependency //##end user.imports

The negative side-effect to this change is that imports previously generated from model dependencies will not be automatically removed when the dependency is removed from the model. For instance, if a class changed from using Vector to using List, both classes would continue to be imported. Developers need to purge unused import statements as they notice them.

Class Documentation
Any documentation that is entered in Rose will be generated into the class in the form of Javadoc style comments. For example,
//##begin MyItem% [ ]34F19D1A00B3.doc preserve=no /** * An example class to demonstrate system generation * * @version 1.0 **/ //##end MyItem% [ ]34F19D1A00B3.doc

Class Declaration
A class is declared as modeled and will extend and implement all of the classes that were modeled as having a generalization relationship. If a class is modeled to extend a class that was not modeled as Extendable, via the Windchill SupportedAPI property, the generator will not allow it to be generated until that modeled generalization is removed.The class can be modeled as concrete, abstract, or as an interface. For example,
// Example of a class declaration public class MyItem extends Item implements Externalizable{ // Example of an abstract class declaration public abstract class Item extends WTObject { // Example of an interface declaration public interface Persistable extends ObjectMappable {

31-6

Windchill Customizers Guide

Class Body
Some constants are generated into the body of each class. The following are examples of generated class constants:
// Constants used by the class private static final String RESOURCE = "example.exampleResource"; private static final String CLASSNAME = MyItem.class.getName();

The RESOURCE constant identifies the resource bundle the class is to use for localizable messages. The CLASSNAME constant provides an easily accessible, programmatic reference to the name of the class. The rest of the class body contains the generated results of elements modeled as features of the class and as relationships between classes. These include operations, attributes, associations, and generalizations. The details of these will be covered in subsequent sections.

Rose Class Specification


On the General tab, set the following values: Name specifies the name of the corresponding Java class. Stereotype: For a class, leave blank. For a final class, select Final. For an abstract class, select Abstract. For an interface, select Interface. For a remote interface, select RemoteInterface (see explanation which follows).

Export Control should be set to Public or Implementation. Implementation classes are visible only to other classes within the same package. Documentation specifies a description for the element. The documentation will be generated into the Java code, as Javadoc style comments. Type is ignored by the code generator.

On the Windchill tab, set the following values: Note: Some specification dialogs provide multiple property sets. Every specification provides a "default" set. The class specification also provides "EnumeratedType" and "System" sets, The EnumeratedType set contains the properties that apply to an EnumeratedType class. The System set contains the

System Generation

31-7

properties that apply to non business domain class. Property sets may provide different default values for the same property. SupportedAPI should be set to communicate to users the degree to which the class will be supported. <Default> to ignore the Supported API concept. Private if the class will not be supported at all. Public if use of the class is supported. Extendable if extension of the class is supported. Deprecated if the class is obsolete and support is being phased out. (This setting is superseded by the Deprecated property.)

Deprecated should be set when the element is obsolete. <Default> indicates the class is not deprecated, unless, for backward compatibility, SupportedAPI is set to Deprecated. deprecated if the class is obsolete and support is being phased out.

Java Properties Generate should be set to False if the system generation tools should ignore this modeled class. CodeGenerationName specifies the name of the class that will be generated. Leave it blank to have the generated name be the same as the name of the modeled class. Serializable indicates if the generated class will implement the Serializable or Externalizable interface. Default evaluates to Externalizable, if possible; otherwise, Serializable. Externalizable (basic), can be used to generate simple Externalization support that does not include support for reading old versions.For a class that will have instances serialized into BLOB columns in the database, set the property to Evolvable. (For further information, see appendix D, Evolvable Classes.) To have the class implement neither interface, set the property to None. PrimitiveType indicates which primitive value-type a class can be decomposed into. StaticInitBeforeFields indicates whether the static initializer will be placed before the field declarations. GenAttributeLabels indicates whether label constants will be generated for the modeled attributes and roles of the class. If True, they will be

31-8

Windchill Customizers Guide

generated. If Default, they will be generated for classes that implement ObjectMappable and for interfaces. ExplicitOrder (EnumeratedType set only) indicates whether the modeled EnumeratedType options will be explicitly order in the resource info (rbInfo) file. By default, a locale specific, alphabetical order will be determined at run-time.

Datastore Properties PackageName is the package name to use for the class. TableName is the database table name to use for the class. RemoveEventParticipant specifies if the persistence layer is required to dispatch Remove events for this class. Remove events include "REMOVE" and "CLEANUP_LINK". Default will be determined to be True for any Persistable class. CompositeIndexN indicates the columns for composite index on the table. CompositeUniqueN indicates the columns for composite unique index on the table. ColumnType indicates the relational storage type for the value-type. By default a mapping, based on the primitive type, is used. Specify a ColumnType of Sequence if the value of the attribute is to be set using a generated sequence number.

Oracle Properties TableSpaceName is the tablespace to use for storage option of the table. TableSize indicates if the relative size required for the objects that will be stored (the actual storage values are mapped from the size via property file settings). IndexTableSpaceName is the tablespace to use for the storage option of the indices of the table.

UI Properties StandardIcon is the file name of the standard icon for the class. OpenIcon is the file name of the open icon for the class. Localizable indicates if the class will have a localizable display name stored in the resource bundle for the package.

The rest of the dialog is ignored by the code generator.

System Generation

31-9

Mapping Operations to Java


The figure below shows an operation modeled in Rose that is mapped to a method in Java.

Model of Operations

The following code is generated for this example.


public class MyItem extends Item implements Serializable { //##begin operation1% [ ]34F19DCB01D0.doc preserve=no /** * The example operation. * * @param arg1 The Date argument * @return StringThe String return value **/ //##end operation1% [ ]34F19DCB01D0.doc public String operation1( Date arg1 ) { //##begin operation1% [ ]34F19DCB01D0.body preserve=yes return null; //##end operation1% [ ]34F19DCB01D0.body } }

Operations modeled in Rose are mapped as Java methods of the generated class. For operations that are not modeled as abstract, stubs are created in the generated class where you add your own code. All documentation, keywords, parameters, and return types that are modeled in Rose are generated into Java classes. Information about operations that you can specify in Rose is detailed below. The begin and end markers that are generated into editable files denote the sections that you can edit. These sections are preserved as is during subsequent generations of the files. Some sections are marked with preserve=no. This is true for all Javadoc comment sections and some code sections, where some implementation is generated into an editable file. The "no" value for preserve indicates that the section is a generated default, which you may choose to edit. If you do edit any of these sections, you must change the preserve value from "no" to "yes"; otherwise, it will not be preserved. If MyItem were an interface, only the operation declaration would be generated into MyItem, because a Java interface can contain no implementation. To the degree possible, the implementation aspects of interface operations will be

31-10

Windchill Customizers Guide

generated into concrete subclasses. See the Implementing Interfaces section for details.

Rose Operation Specification


On the General tab, set the following values: Name specifies the name of the resulting Java method. Return class specifies the type of the methods return value. Export control should be set to Public, Protected, or Implementation. Public methods are external API to the class. Protected methods are customization points that extending classes can choose to override. Private methods need not be part of the business model. Developers can implement them in their classes as needed. Documentation specifies a description for the element. The documentation will be generated into the Java code, as Javadoc style comments.

On the Detail tab, set the following values: Argument Name specifies the name of an argument in the method. Argument Type specifies the argument type. Exceptions specifies the exceptions thrown by the method. The rest of the dialog is ignored by the code generator.

On the Windchill tab, set the following values: SupportedAPI should be set to communicate to users the degree to which the operation will be supported. Private if the operation will not be supported at all. Public if use of the operation is supported. Deprecated if the operation is obsolete and support is being phased out. (This setting is superseded by the Deprecated property.)

Deprecated should be set when the element is obsolete. <Default> indicates the operation is not deprecated, unless, for backward compatibility, SupportedAPI is set to Deprecated. deprecated if the operation is obsolete and support is being phased out.

Java Properties Abstract should be set to True to make the resulting method abstract. Static should be set to True to make the resulting method static. Final should be set to True to make the resulting method final.

System Generation

31-11

Native should be set to True to make the resulting method a native method. Synchronized should be set to True to make the resulting method a synchronized method. RemoteInvocation should be set to True to make the resulting method executable only at the server. This setting is not needed for classes that implement a RemoteInterface.

Mapping Attributes to Java Attribute Implementation


The external Java representation of a class attribute modeled in Rose consists of a getter operation, a setter operation, and an identifying label. The export visibility of the getter and setter operations is based on the export visibility of the modeled attribute in Rose. The internal Java implementation of the class attribute is always a private field. This field is accessed strictly through getter and setter operations. Encapsulating the attribute as a private field provides several benefits: The class controls the integrity of the attribute by monitoring changes to the attribute. The class can support subscribe/notify functionality that allows listeners to monitor the state of the attribute. Access through getter and setter operations provides the opportunity to synchronize access to the attribute. The following model shows the class MyItem, with attributes a1, a2, and a3, which extends the class Item.

Model of Attributes

31-12

Windchill Customizers Guide

Attribute Label Constants


String field constants are generated as attribute labels so you can use them in APIs that require an attribute name, such as queries. Thus, the Java compiler can detect typographical errors.
// Examples of attribute name public static final String A1 public static final String A2 public static final String A3 constants = "a1"; = "a2"; = "a3";

Field Declarations
All attributes modeled in Rose are implemented as private fields of the Java class. For example,
// Examples of attribute declarations private String a1; private Date a2; private Xyz a3;

The accessor methods to these attributes are public or protected, depending on the export control as defined in the model. Examples of accessor methods follow.

Accessor Methods
Public and protected accessor methods are generated in the Java class. For example,
// Example of a "getter" method public String getA1() { return a1; } // Example of a "setter" method public void setA1( String theA1 ) throws WTPropertyVetoException { a1 = theA1; }

Accessor methods are code-generated from the attributes modeled on the business class in the Rose model. They need not be modeled on classes in the UML model. These accessor methods follow the Java beans naming convention. Attributes that were modeled as public get public accessor methods. Attributes that were modeled as protected get protected accessor methods. The system generation tool generates accessors that enforce attribute validation based on attribute properties specified in the model. If the constrain property (a Rose specification) is set to true for an attribute modeled in Rose, the setter method is declared to throw a wt.util.WTPropertyVetoException, which is derived from java.beans.PropertyVetoException. This exception is thrown if the setter method has determined that a value being set in the attribute is invalid. Developers can change the default accessor methods by writing code in the preserve region.

System Generation

31-13

Validation code will be generated if the attribute is modeled with a lower or upper bound, as unchangeable, or as a required attribute. Each of these properties appear, in Rose, on the Windchill tab for the attribute. Validation code will also be generated if the attribute is modeled with a constrained type. That is, the attribute is redefining an attribute, in the hierarchy, to be of a sub-type of the original definition. If a validation method is generated, the setter code will invoke it. If validation were generated for the "a1" attribute, the method would be "validateA1". If MyItem were an interface, only the accessor declarations and the label constant would be generated into MyItem, because a Java interface can contain no implementation. To the degree possible, the implementation aspects of interface attributes will be generated into concrete subclasses. See the Implementing Interfaces section for details.

Rose Attribute Specification


On the General tab, set the following values: Name specifies the names of the generated attribute. Type specifies the attributes class. Initial value specifies the initial value for the attribute. Export control should be set to Public, Protected, or Implementation. If you want private methods, declare them in your source code. Documentation specifies a description for the element. The documentation will be generated into the Java code, as Javadoc style comments.

On the Detail tab, set the following values: Static should be selected if the attribute is to be generated as a static field. Derived should be selected if the generated private field is not desired. Also see the DerivedFrom property below. The rest of the dialog is ignored by the code generator.

On the Windchill tab, set the following values: In addition to the default property set, attributes have two predefined sets. First, named "constant", which can be used for constant attributes. Second, named "constantEnumeratedType", which can be used for constant attributes on EnumeratedTypes. While these property sets can be used to quickly set the Windchill properties for these constant attributes, the Static property still needs to be selected on the detail tab. Abstract should be set to True if the implementation of a field for the attribute will be deferred to a subclass. Accessor methods generated for this attribute will be abstract.

31-14

Windchill Customizers Guide

DerivedFrom should be specified if this attribute is derived from another modeled element. The value will specify a traversal path to the source. For example, homeAddress.city indicates that this class has a non-first-class aggregation named homeAddress which contains an attribute named city. To specify that an attributes derivation traversal goes through an ObjectReference, a different delimiter is used. For example, homeAddress>city indicates that this class has an opposite-side role on a first-class association named homeAddress which contains an attribute named city. StringCase should be set to LowerCase to force the value to lowercase. It should be set to UpperCase to force the value to uppercase. The enforcement of this constraint will be generated into the setter method for the attribute. LowerLimit constrains the valid values for the type. For String types, it specifies the minimum length of the String. For numeric types, it specifies the minimum value of the attribute. Date and Time types are not currently supported by this property. The constraint is enforced in the validation that is generated for the setter. UpperLimit constrains the valid values for the type. For String types, it specifies the maximum length of the String. For numeric types, it specifies the maximum value of the attribute. Date and Time types are not currently supported by this property. The constraint is enforced in the validation that is generated for the setter. Required should be set to True if the database will not allow a null value in the column that persists the attributes value, and the setter validation will not allow the attributes value to be set to null. Changeable should be set to Frozen if the value cannot be changed once it has been persisted. It should be set to ViaOtherMeans if the normal setter method is not allowed to change the value once it has been persisted. (For example, ViaOtherMeans is used for those attributes that are part of the identity of the class which must be changed through the identity service.) WriteAccess should be set if the access of the setter should be different than that of the getter that will be generated. SupportedAPI should be set to communicate to users the degree to which the attribute will be supported. <Default> to ignore the Supported API concept. Private if the attribute will not be supported at all. Public if use of the attribute is supported. Deprecated if the attribute is obsolete and support is being phased out. (This setting is superseded by the Deprecated property.) Deprecated should be set when the element is obsolete.

System Generation

31-15

<Default> indicates the attribute is not deprecated, unless, for backward compatibility, SupportedAPI is set to Deprecated. deprecated if the attribute is obsolete and support is being phased out.

Java Properties Final should be set to True if the resulting field should be final. Transient should be set to True if the resulting field should be transient. Volatile should be set to True if the resulting field should be volatile. Persistent should be set to True if the field that holds the value will be persisted to the database. GenerateAccessors should be set to False if no accessors are to be generated. Constrain should be set to True if the resulting setter method should declare that it throws a WTPropertyVetoException. GetExceptions specifies exceptions that will be declared as thrown by the generated getter. SetExceptions specifies exceptions that will be declared as thrown by the generated setter. BeforeStaticInitializer should be set to True if field declaration should be placed prior to the static initializer.

Datastore Properties ColumnName is the class attribute to column name mapping. Default is the attribute name. ColumnType is used to indicate the relational storage type for the valuetype. By default a mapping, based on the attribute type, will be used. Index specifies whether an index is created for this attribute. Unique specifies whether a unique index is created for this attribute. Updatable specifies whether the column can be updated using standard persistence mechanisms.

Oracle Properties TableSpaceName is the tablespace to use for storage option of the table. TableSize indicates the relative size required for the objects that will be stored (the actual storage values are mapped from the size via property file settings).

31-16

Windchill Customizers Guide

UI Properties Localizable indicates if the attribute will have a localizable display name stored in the resource bundle for the package. Display (constantEnumeratedType set only) specifies the localizable display name for the attribute, if the attribute is a constant for an EnumeratedType. DefaultValue (constantEnumeratedType set only) should be set to True if the attribute is the default option for the EnumeratedType. Only one attribute can be set to True. The rest of the dialog is ignored by the code generator.

A constant attribute is one that is specified as static and final.

Mapping Associations to Java Non-Persistable Associations


The following model shows associations with non-persistable objects (MyAddress and NameValue).

Associations between Non-Persistable Objects

The following code is generated from this example:


public class MyItem extends Item { private String a1; private Date a2; private Xyz a3; private MyAddress work; private Vector list; // contains a set of NameValue objects // This class also contains the constants and the accessor // methods for a1, a2, a3, work and list. }

System Generation

31-17

The implementation of a non-persistable association is the same as the implementation of a modeled attribute. That is, it will be implemented with a private field, a constant label, and accessor methods. If classes modeled in Rose extend the class Item, these classes are automatically both ObjectMappable and Persistable. But in this example, an object called MyAddress is modeled that is a composite aggregation. This means that the instance MyAddress never exists on its own. It exists only as a part of another instance. In this case, the code generator creates a field in MyItem using the name of the composite aggregation, that is, the name of the navigable role on the association (in this example, work). Note that although modeling it as a composite aggregation communicates the ownership, the role must be navigable to accomplish the generated implementation. If the associations cardinality is greater than one, the attribute is represented as a Java Vector. For example, the class NameValue is also a composite aggregation and it contains multiple name and value strings. Because the total number that could occur is not known during system generation, the code generator creates a Vector field with the name of the composite aggregation (in this example, list). In this example, the field is a list of names and values. The generated class also contains public accessor methods for all the attributes. Note also that if the roles cardinality is optional, but the class being aggregated contains required elements, the aggregated class will be treated as required. The system generator must enforce this coordination of required attributes because of the way the PDS (Persistent Data Service) enforces required attributes. The PDS accomplishes the enforcement through the NOT NULL column feature of SQL databases. Because a column within the structure will be generated as NOT NULL, the structure as a whole cannot be nullable. If MyItem were an interface, only the accessor declarations, and the label constant would be generated into MyItem, because a Java interface can contain no implementation. To the degree possible, the implementation aspects of interface associations will be generated into concrete subclasses. See the Implementing Interfaces section for details.

31-18

Windchill Customizers Guide

Implicit Persistable Associations


The following model shows an association between persistable objects where the association has no attributes.

An Association with No Attributes between Persistable Objects The following code is generated from this example:
public final class LinkA extends ObjectToObjectLink implements Externalizable { // role name constants public static final String MY_ITEM_ROLE = "theMyItem"; public static final String YOURS_ROLE = "theYours"; public MyItem getMyItem() { // getter return (MyItem)getRoleAObject(); } public void setMyItem( MyItem theMyItem ) // setter throws WTPropertyVetoException { setRoleAObject( theMyItem ); } // two-arg factory for link classes public static LinkA newLinkA( MyItem theMyItem, Yours theYours ) throws WTException { LinkA instance = new LinkA(); instance.initialize( theMyItem, theYours ); return instance; } }

System Generation

31-19

In this case, the code generator creates persistable Java classes that extend the ObjectToObjectLink class and are capable of maintaining a persistent association. Code-generated accessor methods return the role A and role B objects of the link. This means that the developer need not be concerned with which object is the role A object and which is the role B object. Code-generated factory methods for Link classes take at least two arguments: the role A object and the role B object. The factory methods are a result of the Link interface extending the NetFactor interface. A full explanation of factory methods is included in the section on Implementing the NetFactor Interface.

31-20

Windchill Customizers Guide

Implicit Persistable Associations Stored with Foreign ID References


The following model shows an association between persistable objects where the association has no attributes.

A Persistable Association Stored with a Foreign ID Reference

The link class is generated for LinkC, just as it was for LinkA, in the preceding example. In addition, the following code is generated in the class that plays the role opposite the role that has a cardinality of one.
public class OneMore implements Persistable, Externalizable { public static final String A1 = "myItem>a1"; public static final String MY_ITEM_REFERENCE = "myItemReference"; private ObjectReference myItemReference; public String getA1() { try { return getMyItem().getA1(); } catch (NullPointerException npe) { return null; } } public void setA1( String a_A1 ) throws WTPropertyVetoException { getMyItem().setA1( a_A1 ); } public MyItem getMyItem() { if ( myItemReference == null ) return null; return (MyItem)myItemReference.getObject(); } public ObjectReference getMyItemReference() { return myItemReference; } public void setMyItemReference( ObjectReference a_MyItemReference ) throws WTPropertyVetoException {

System Generation

31-21

myItemReferenceValidate( a_MyItemReference ); // throws exception if not valid myItemReference = a_MyItemReference; } }

In this case, since the association is persisted via a foreign id in the table for OneMore rather than in a separate link table, the OneMore class will hold a reference to myItem and will get myItemReference accessors generated. In addition to the getter and setter that are generated for the reference, a convenience getter is generated for the myItem object. Although these additional accessors are created for developer convenience, the LinkC class that is generated for the association can be operated on in the same manner as a link class that is stored in a separate link table. This provides a common API for manipulating links, regardless of how the database storage is implemented. The example also had a derived attribute modeled for the OneMore class. The DerivedFrom property for the attribute was defined as myItem>a1, which caused the A1 label constant and accessors to be generated for the a1derived attribute. (If this were a non-persistable association, the syntax for the derived attribute source would be myItem.a1.) Care should be taken in using this feature with persistable associations since allowing the generation and use of a derived setter will cause a state change in a different persistable object (myItem) which may not be obvious to the developer who is using your class (OneMore). The generation of the setter can be turned off while retaining the generation of the getter by setting the attributes WriteAccess property to Private.

Explicit Persistable Associations


The following model shows an association between persistable objects where the association has attributes.

An Association with Attributes between Persistable Objects

31-22

Windchill Customizers Guide

The following code is generated from this example:


public class LinkB extends ObjectToObjectLink implements Externalizable { . . . /* everything that the implicit link has, plus normal class generation for attributes, operations, etc. */ }

If an association has attributes associated with it, the code generator creates a Java class that has all of the attributes for the association and the accessor. The name of the generated Java class is the name of the attributing class. The generated Java class extends the ObjectToObjectLink class if the attributing class does not extend another class in the model. If the attributing class extends another class in the model, the Java class extends that class. (The class being extended must be a subclass of Link.)

Rose Association Specification


For the tabs that specify role information, there is a Role A tab and a Role B tab. Both work essentially the same with the only differences being whether role A or role B is referred to. On the General tab, set the following values: Name specifies the name association that is the name of the resulting Link class. If blank, it defaults to a role A/role B concatenation. Role A specifies the role A name. If blank, it defaults to the name of the role A class (in this case, the class name is prefixed with "the" to avoid a naming conflict). The popup menu for associations provides an alternative means for specifying role A. Role B specifies the role B name. If blank, it defaults to the name of the role B class (in this case, the class name is prefixed with "the" to avoid a naming conflict). The popup menu for associations provides an alternative means for specifying role B. The rest of the dialog is ignored by the code generator.

On the Detail tab, set the following value: Derived should be set to True to indicate that the implementation of the association will be derived, as determined by the developer. The rest of the dialog is ignored by the code generator.

On the Windchill tab, set the following values: Java Properties Generate should be set to False if the system generation tools should not generate a Java class for this modeled association.

System Generation

31-23

SuperClass is the name of the link class that the class generated for the association should extend. SuperClass should be defined when a class that contains a ForeignKey association is a sub-class and the sub-class's ForeignKey class referential integrity properties (i.e. Owner, Cascade) should be inherited from the parent's ForeignKey class.

SupportedAPI should be set to communicate to users the degree to which the association class will be supported. Private if the association class will not be supported at all. Public if use of the class is supported. Extendable if extension of the class is supported. Deprecated if the class is obsolete and support is being phased out. (This setting is superceded by the Deprecated property.)

Deprecated should be set when the element is obsolete. <Default> indicates the class is not deprecated, unless, for backward compatibility, SupportedAPI is set to Deprecated. -deprecated if the class is obsolete and support is being phased out.

Datastore Properties PackageName is the package name to use. TableName is the database table name to use. Storage indicates if the association will be stored in a link table or as a foreign ID reference in the table for one of the role classes. Default evaluates to ForeignKey if there is a role with single cardinality and the class opposite that role resides in the same package as the association; otherwise, evaluates to LinkTable. RemoveEventParticipant specifies if the persistence layer is required to dispatch Remove events for this implicit Link class. Remove events include "REMOVE" and "CLEANUP_LINK". Default will be determined to be True for any Persistable class.

Oracle Properties TableSpaceName is the tablespace to use for storage option of the table. TableSize indicates if the relative size required for the objects that will be stored (the actual storage values are mapped from the size via property file settings). IndexTableSpaceName is the tablespace to use for the storage option of the indices of the table.

The rest of the dialog is ignored by the code generator.

31-24

Windchill Customizers Guide

On the Role <A/B> General tab, set the following values: Role specifies the name of the role. (See Role A (or B) description for General tab above.) Export control should be set to Public, Protected, or Implementation. If you want private attributes, declare them in your source code. Documentation specifies a description for the element. The documentation will be generated into the Java code, as Javadoc style comments.

On the Role <A/B> Detail tab, set the following values: Role specifies the name of the role. (See Role A (or B) description for General tab above.) Cardinality specifies the cardinality of the role. The popup menu for associations provides an alternative means for specifying cardinality. Navigable should be selected if the role B (or role A) object should get a method for accessing the role A (or role B) object. The popup menu for associations provides an alternative means for specifying navigability. Navigable is ignored for Persistable associations. Aggregate should be selected if the association is an aggregate. The popup menu for associations provides an alternative means for specifying aggregation. By value should be selected if the aggregate is a composite aggregation. The popup menu for associations provides an alternative means for specifying composite aggregation. The rest of the dialog is ignored by the code generator.

On the Windchill<A/B> tab, set the following values (ignored for Persistable associations): Abstract should be set to True if the implementation of a field for the role will be deferred to a subclass. Access methods generated for this role will be abstract. StringCase should be set to LowerCase to force the value to lowercase. It should be set to UpperCase to force the value to uppercase. The enforcement of this constraint will be generated into the setter method for the attribute. LowerLimit constrains the valid values for the type. For String types, it specifies the minimum length of the String. For numeric types, it specifies the minimum value of the role. Date and Time types are not currently supported by this property. The constraint is enforced in the validation that is generated for the setter. UpperLimit constrains the valid values for the type. For String types, it specifies the maximum length of the String. For numeric types, it specifies the maximum value of the role. Date and Time types are not currently supported

System Generation

31-25

by this property. The constraint is enforced in the validation that is generated for the setter. Changeable should be set to Frozen if the value cannot be changed once it has been persisted. It should be set to ViaOtherMeans if the normal setter method is not allowed to change the value once it has been persisted. WriteAccess should be set if the access of the setter should be different than that of the getter that will be generated. Dependency should be set to True if the opposite-side role class is dependent on this role. SupportedAPI should be set to communicate to users the degree to which the role will be supported. Private if the role will not be supported at all. Public if use of the role is supported. Deprecated if the role is obsolete and support is being phased out. (This setting is superceded by the Deprecated property.)

Deprecated should be set when the element is obsolete. <Default> indicates the role is not deprecated, unless, for backward compatibility, SupportedAPI is set to Deprecated. deprecated if the role is obsolete and support is being phased out.

Java Properties Final should be set to True if the resulting field should be final. Transient should be set to True if the resulting field should be transient. Volatile should be set to True if the resulting field should be volatile. Constrain should be set to True if the resulting setter method should declare that it throws a WTPropertyVetoException. ReferenceType specifies the class of ObjectReference that will be used for first-class associations that are stored as with a ForeignKey and thereby make use of a held ObjectReference. By default, the generic ObjectReference will be used. AutoNavigate should be set to True if the object playing this role should be automatically retrieved (instantiated) from the database whenever the object on the other side is retrieved. Update operations are not impacted by this property. This feature is dependent on the association being implemented as a ForeignKeyLink. Persistent should be set to True if the field that holds the value will be persisted to the database.

31-26

Windchill Customizers Guide

GetExceptions specifies exceptions that will be declared as thrown by the generated getter. SetExceptions specifies exceptions that will be declared as thrown by the generated setter. ContainerClass specifies that class of container to use for roles of unbounded multiplicity (cardinality). Default container is Vector. InitialValue specifies the value to which the field will be initialized upon declaration. DelegatedInterface specifies that the object playing the role is a delegate that supplies an implementation for the specified interface. All the methods necessary to fulfill (implement) the interface will be generated as methods that forward to the role object. BeforeStaticInitializer should be set to True if field declaration should be placed prior to the static initializer.

Datastore Properties ColumnName is the class attribute to column name mapping. Default is the attribute name. ColumnType is used to indicate the relational storage type for the valuetype. By default a mapping, based on the attribute type, will be used. Index specifies whether an index is created for this attribute. Unique specifies whether a unique index is created for this attribute. Updatable specifies whether the column can be updated using standard persistence mechanisms. Owner specifies if this role is an owner of the association. Owner means when the is role is deleted, the association will be deleted also. Both roles can be an owner. Default will be determined to be True for any role. Cascade specifies if association deletion should cascade to the role object. Default will be determined to be False for any role.

Oracle Properties TableSpaceName is the tablespace to use for storage option of the table. TableSize indicates if the relative size required for the objects that will be stored (the actual storage values are mapped from the size via property file settings).

System Generation

31-27

UI Properties Localizable indicates if the role will have a localizable display name stored in the resource bundle for the package.

The rest of the dialog is ignored by the code generator.

Implementing Interfaces
In Rose, an interface is modeled as a class that has the stereotype <<Interface>>.

Model of Implementing an Interface

In this example, MyItem, which is concrete, is said to implement the interface named Timelineable, which aggregates Timeline. The following code is generated for this example.
public class MyItem extends Item implements Timelineable, Externalizable { private Timeline timeline; public Timeline getTimeline() { return timeline; } public void setTimeline( Timeline a_Timeline ) throws WTPropertyVetoException { timelineValidate( a_Timeline ); // may throw exception if not valid timeline = a_Timeline; } private void timelineValidate( Timeline a_Timeline ) throws WTPropertyVetoException { if ( a_Timeline == null ) { // required attribute check Object[] args = { new wt.introspection.PropertyDisplayName( CLASSNAME, "timeline" ) }; throw new WTPropertyVetoException( "wt.fc.fcResource", wt.fc.fcResource.REQUIRED_ATTRIBUTE, args,

31-28

Windchill Customizers Guide

new java.beans.PropertyChangeEvent( this, "timeline", timeline, a_Timeline ) ); } } // The constant label is generated into the // Timelineable interface }

In general, system generation causes the following actions: Classes in the model that extend an interface cause an implements clause to be created on the class declaration of the generated class. Stubs for the operations of the interface are created in the generated class if the inheriting class is concrete. This is where you insert your implementation code. (This applies even for protected methods modeled on an interface, which will not appear on the generated interface since an interface can have only public features.) Non-constant attributes modeled on the interface cause private fields to be created on the generated classes that implement the interface, along with generated accessor methods. Associations with non-persistable classes are handled similar to modeled attributes, where the API is generated on the interface and the implementation is generated into the concrete subclasses.

Implementing the NetFactor Interface


The vast majority of business classes provided with Windchill applications and foundation components implement the NetFactor interface, either directly or indirectly. Implementing this interface, in fact, indicates that a class is a business class participating in the Windchill architecture.

Factory operations
To give flexibility to the system architecture, Windchill uses a factory design pattern for the construction of Java objects. A constructor signature is one where the operation name matches the name of the class and has no return type. Object constructors are modeled in Rose but are not generated directly in Java code. Instead of constructors, Windchill generates factory operations that are used to construct objects. Using factory operations instead of constructors provides the opportunity to vary the class of the returned object. When constructors are used to create an object, the class of the returned object must match exactly the class requested. However, when factories are used, the class of the returned object will be polymorphically compatible with the requested class but need not match the requested class exactly. This allows the return of objects whose class may vary depending on the context.

System Generation

31-29

When a constructor is specified in a Rose model, two operations are generated in the Java code: a public factory operation and a protected initialization operation. The factory operation is called directly by the application to create a Java instance. The factory method calls the initialize operation to put the instance into an initial state. Note that for optimization reasons, an initialize method is generated only when one having the same signature is not provided by a superclass. You can manually supply an override initialize method if you wish. If the modeled class (directly or indirectly) inherits from NetFactor, this is a cue to the code generator to generate factory and initialize methods in the Java class. The following modeled class has a constructor that takes an argument of a string.

Factory Operation for an Item

The following code is generated for this example (documentation omitted).


public class MyItem extends Item { public static MyItem newMyItem( String arg1 ) throws WTException { //##begin newMyItem% [ ]34F1E6BF02D9f.body preserve=no MyItem instance = new MyItem(); instance.initialize( arg1 ); return instance; //##end newMyItem% [ ]34F1E6BF02D9f.body } protected void initialize( String arg1 ) throws WTException { //##begin initialize% [ ]34F1E6BF02D9.body preserve=yes //##end initialize% [ ]34F1E6BF02D9.body } }

A factory method instantiates and initializes business objects. It invokes the constructor of the implementation class and then invokes an initialize method with the same parameters as the factory method. The code generator also generates the correct method stubs so you can implement the initialize method. This method is responsible for setting the initial state of a new object. Factory methods have the form: public static <class> new <class> (args)

31-30

Windchill Customizers Guide

throws WTException The factory method has the same name as the class in the Rose model plus the prefix "new" (for example, newMyItem). If no constructor is modeled for a class, the generator assumes a default, no-arg constructor. For link classes, the default factory method includes a reference to the two objects being related by the link. For details on link class generation, see the Persistable Associations section.

Conceptual class name accessor


Every class that inherits from NetFactor implements a getConceptualClassname instance method:
public String getConceptualClassname() { return CLASSNAME; }

This method returns the fully-qualified conceptual class name of the object. Because the instantiated object may really be an instance of some other implementation class, getConceptualClassname is a useful method to find the business class in an object. You should not use object.getClass().getName() to determine the class name for software objects in the Windchill system because it may not return the name of the conceptual class.

Info object accessor


Every class that inherits from NetFactor has an info object generated for it. The code generator therefore ensures that each NetFactor instance supports the getClassInfo method. This method is generated into the top class in each hierarchy. For example:
public ClassInfo getClassInfo() throws WTIntrospectionException { return WTIntrospector. getClassInfo( getConceptualClassname() ); }

This method returns the ClassInfo instance that contains the metadata from the installed model.

Implementing the ObjectMappable interface


The database methods readExternal and writeExternal are code-generated for any class that was modeled to implement the ObjectMappable interface. The readExternal method reads the objects state from the database. The writeExternal method writes the objects state to the database. The class defers to its superclasses to read (or write) the state for the persistent attributes that those classes declared. The class defers to its structured attribute

System Generation

31-31

classes, such as Address, to read (or write) the state for the persistent attributes that those classes declared with the readObject and writeObject methods. Because the class defers the reading of some of the fields from the database to its superclass, the types of structured attributes are hard-coded into the super class. The exception to this rule of hard-coded types is for ObjectReferences that are generated for roles of Persistable associations. The Persistent Data Service (PDS) does a runtime look-up in the introspection information to see if the ReferenceType for the role was redefined at a lower level in the class hierarchy. If so, the PDS uses that type. But even if the type is redefined, its persistent structure must be compatible with the type that was used by the super class, because the column definitions defined by a super class cannot be changed by a subclass. The PersistentRetrieveIfc argument for readExternal contains the state for the object being read. The PersistentStoreIfc argument for writeExternal receives the state of the object being written. Examples of the readExternal and writeExternal methods follow:
// Example of a database writeExternal method public void writeExternal( PersistentStoreIfc output ) throws SQLException, DatastoreException { super.writeExternal( output ); output.setString( "a1", a1 ); output.setDate( "a2", a2 ); output.setObject( "a3", a3 ); output.writeObject( "work", work, wt.tools.generation.example.MyAddress.class, true ); output.setObject( "list", list ); output.setString( "size", size == null - null : size.toString() ); output.writeObject( "timeline", timeline, wt.tools.generation.example.Timeline.class, true ); } // Example of a database readExternal method public void readExternal( PersistentRetrieveIfc input ) throws SQLException, DatastoreException { super.readExternal( input ); a1 = a2 = a3 = work input.getString( "a1" ); input.getDate( "a2" ); (Xyz)input.getObject( "a3" ); = (wt.tools.generation.example.MyAddress)input.readObject( "work", work, wt.tools.generation.example.MyAddress.class, true ); list = (Vector)input.getObject( "list" ); size = MySize.toMySize( input.getString( "size" ) ); timeline = (wt.tools.generation.example.Timeline) input.readObject("timeline", timeline, wt.tools.generation.example.Timeline.class, true ); }

31-32

Windchill Customizers Guide

Implementing the Persistable interface


The equals and hashCode methods are generated for non-interface subclasses of Persistable. Any customized code with non-modeled equals or hashCode methods will need to change the method's preserve flag in order to implement a non-default equals or hashCode. Caution: Certain core Windchill operations may depend upon these methods being ObjectIdentifier-based. Changes to the default implementation should be done with care, if at all. Examples of the equals and hashCode methods follow:
// Example of an equals method public boolean equals( Object obj ) { //##begin equals%equals.body preserve=no // WARNING: Do not change return wt.fc.PersistenceHelper.equals(this,obj); //##end equals%equals.body } // Example of a hashCode method public int hashCode() { //##begin hashCode%hashCode.body preserve=no // WARNING: Do not change return wt.fc.PersistenceHelper.hashCode(this); //##end hashCode%hashCode.body }

Implementing the Externalizable interface


A core feature of Java is the capability of streaming objects. This feature is used for purposes such as persisting objects or passing Java objects by value on RMI calls. There are two ways to support externalization: by using the tagging interface Serializable or by using the interface Externalizable. When possible, Windchill classes implement the more efficient Externalizable interface. Sometimes it is not convenient to implement Externalizable and the less efficient Serializable is used instead. A class is generated to implement Externalizable, by default, if it meets the criteria for Externalization. The criteria are as follows: Must have a public, no-argument constructor. Any parent class must be Externalizable.

A property in Rose allows you to override the default determination. This property, named Serializable, is in the Java Properties on the Windchill tab for the class. With this property, you can force the class to Serializable, Externalizable, or neither.

System Generation

31-33

The Evolvable option has been added to this property to better manage which classes can be serialized into BLOB columns in the database. This option was added in conjunction with a change to the generated Externalization stream format. Because of this change to the stream format, much externalization code is generated to maintain backward compatibility. In a future release, only the readExternal and writeExternal methods will be generated for classes that implement Externalizable but not Evolvable. Until the backward compatibility is removed, new classes can be forced to generate simplified externalization code by selecting the "Externalizable (basic)" option. The evolvable aspects of externalization will not be shown below. For details on when to use Evolvable and how to manage Evolvable classes, see Evolvable Classes on page 42-1.

The serialVersionUID constant


The serialVersionUID is used to determine compatibility of classes when reading them from an input stream. The mechanisms that perform the serialization and externalization compute a serialVersionUID value at runtime when a class has not explicitly defined the value to something other than zero. When the code generator is generating externalization for a class, it sets the serialVersionUID to 1 since compatibility is managed in the externalization methods (as shown in the following section). This value must remain unchanged to enable the hooks for reading old versions to be used. The following is an example of defining the value for the constant:
static final long serialVersionUID = 1;

Externalization methods
In the generated externalization methods, all non-transient, non-static fields that were modeled will be handled. The externalization is generated in a manner that provides hooks for reading in previous versions of the class, unless "basic" externalization is generated. Code generation detects when the externalizable signature of a class changes, and changes its internal version UID accordingly. You have the ability to take control of the externalization code, but it is not recommended because it requires careful management of the externalizable signature of the class. Examples of the externalization methods follow:
// 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( output.writeObject( output.writeObject( output.writeObject( a1 ); a2 ); a3 ); list );

31-34

Windchill Customizers Guide

output.writeObject( (size == null ? null : size.getStringValue()) ); output.writeObject( theOneMoreReference ); output.writeObject( timeline ); output.writeObject( work ); //##end writeExternal%writeExternal.body }

// Example of a readExternal method public void readExternal( ObjectInput input ) throws IOException, ClassNotFoundException { //##begin readExternal%readExternal.body preserve=no long readSerialVersionUID = input.readLong(); consume UID //

if ( readSerialVersionUID == EXTERNALIZATION_VERSION_UID ) { // if current version UID super.readExternal( input ); handle super class //

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.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(); } else throw new java.io.InvalidClassException( CLASSNAME, "Local class not compatible:" + " stream classdesc externalizationVersionUID=" + readSerialVersionUID + " local class externalizationVersionUID=" + EXTERNALIZATION_VERSION_UID ); //##end readExternal%readExternal.body }

System Generation

31-35

Extending the EnumeratedType class


The EnumeratedType class is a wrapper for a string whose valid values are constrained to a defined set. A type, or class, can be created to define a specific set of values by extending the EnumeratedType class. The following model provides an example of creating an enumerated type. MySize also shows the modeling of constants that reference certain values of the sets valid values.

Extending EnumeratedTypes

An example of the generated enumerated type follows:


public class MySize extends EnumeratedType { // define the name of the resource bundle private static final String CLASS_RESOURCE = MySizeRB; // initialization of programmatic constants public static final MySize SMALL = toMySize( "sm" ); public static final MySize MEDIUM = toMySize( "med" ); public static final MySize LARGE = toMySize( "lrg" ); // Obtain a MySize value from an internal value public static MySize toMySize( String a_value ) // Obtain the default MySize "value" public static MySize getMySizeDefault() // Obtain the set of valid MySize "values" public static MySize[] getMySizeSet() // Obtain the set of valid MySize "values" (polymorphic) public EnumeratedType[] getValueSet() }

There should be no need for a developer to change any of the implementation of a generated enumerated type, but they are generated with preserve markers to allow for developer enhancements, if the need should arise. Note that the Windchill tab on Rose specification dialogs for classes and attributes provides property set sheets specific to EnumeratedType usage. These properties are detailed in the model elements sections above. For more information on working with enumerated types, see the Enumerated Types chapter on page 33-1.

31-36

Windchill Customizers Guide

Stereotyping an interface as remote


When you model a service, you model interfaces and remote interfaces (see Developing Server Logic chapter on page 35-1 for more information). The <<RemoteInterface>> stereotype causes the code generator to generate a forwarder class that clients can use to invoke the method on the server. A forwarder class has the same name as the remote interface in the Rose model plus the suffix "Fwd" (for example, TimelineServiceFwd). The following is a model of a business service, stereotyped as a RemoteInterface.

Business Service Model

The following is an example of a generated remote forwarder:


public class TimelineServiceFwd implements wt.method.RemoteAccess, TimelineService, Serializable { // constant that enables the object to know where it is static final boolean SERVER = RemoteMethodServer.ServerFlag; // identifies what type of service to forward to public Class getTypeClass() { return example.TimelineService.class; } public void begin( Date beginDate ) throws WTException { if (SERVER) // invoke the service else { // remote call to the server } } public void end( Date endDate ) throws WTException }

System Generation

31-37

Services contain the complete business logic and are expected to run only on the method server, but forwarders go back and forth between the server and the client. From the client, they invoke the business service methods running on the server. At runtime, the forwarder binds to a service which is determined by the registration of services that is done in the wt.properties file. The forwarder classes are completely generated and provide no preserve markers for developer editing.

31-38

Windchill Customizers Guide

How Rose UML Maps to Info Objects


Introspection is part of the Java Beans specification. It is a standard method for providing metadata information about an object, such as its attributes and the methods it supports. Windchill extends that concept with Info objects. Info objects contain class information from the Rose UML model that is needed by the runtime system. One Info object is generated for each modeled class that implements NetFactor, each modeled EnumeratedType subclass, and for each modeled interface. The system generation tool creates Info objects by capturing a subset of the class information stored in the Rose repository as serialized resource files that are read by the runtime system. Info objects contain information for the following elements: Classes and interfaces Descendents (that is, a list of subclasses, which allows you to determine what classes are inherited from a specific class) Link membership Property descriptors for attributes Column descriptors containing attribute mapping information Database table, package, and other parameters

Links (When you have a link, you can also create a link between objects that are subtypes of the role A and role B objects. Therefore, you need to know which are valid and how many there can be.) Role A and role B names Valid role A and role B classes Role A and role B cardinality

Attributes of classes Standard JavaBeans PropertyDescriptor with extended information Derived flag Persistent flag Updateable flag Query name (name of its column descriptor) StringCase (if a String type is forced to either uppercase or lowercase) Required flag Upper limit Method that returns set of valid values

System Generation

31-39

ConstrainedType (if type overridden in subclass) DefinedAs (class and attribute name as originally modeled) ModeledPersistentType (modeled column type)

For a complete description of the introspection information that is provided, see the wt.introspection package entry in your installed Windchill Javadoc. Windchill provides a utility to print the content of a serialized Info object. You can run the utility as follows: InfoReport <fully.qualified.classname> The resulting report is in a file named <qualified.classname >.out, which is located in the directory specified by the wt.temp property in wt.properties. To print the info contents for each class of an entire package, you can run the utility as follows: InfoReport <fully.qualified.*> Windchill also provides a utility that will verify the environment as it relates to introspection information. That is, it will verify the existence and ability to load all classes and serialized info objects that are referenced in the registry files. The utility simply writes its output to the console, with reported problems being preceded by three asterisks (***). To verify the entire registry (the complete environment), enter the following command: executeTool wt.introspection.VerifyEnvironment registry To verify a single package, enter the following command: executeTool wt.introspection.VerifyEnvironment <fully.qualified.*>

31-40

Windchill Customizers Guide

How Rose UML Maps to Database Schema


Table 8-1 shows the possible Rose Types and the associated JDBC specification standard SQL types and datastore SQL types (both Oralce and SQLServer). Table 8-2 shows how common Java types map to Rose Types. This table also shows other allowable Rose Types for the given Java type. In the table below, the fully qualified classnames for Types and WTTypes are java.sql.Types and wt.introspection.WTTypes, respectively.

System Generation

31-41

Table 8-1: Possible Rose Types and the associated JDBC specification standard SQL types and datastore SQL types
Rose Type JDBC Type Oracle Type SQL Server Type

INTEGER BIGINT SMALLINT TINYINT REAL DOUBLE BIT CHAR VARCHAR

Types.INTEGER Types.BIGINT Types.SMALLINT Types.TINYINT Types.REAL Types.DOUBLE Types.BIT Types.CHAR Types.VARCHAR

NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER(1) CHAR(3) VARCHAR(length) where length is the UpperLimit value (default=200). The length value may also be multiplied by the wt.db.maxBytesPerChar value for multi-byte configurations NUMBER DATE BLOB VARCHAR (4000) VARCHAR (4000) BLOB Two columns are generated. The encoded object is stored in the VARCHAR column if it fits, otherwise the BLOB column is used.

INT BIGINT SMALLINT TINYINT FLOAT(24) FLOAT(35) TINYINT NCHAR(1) NVARCHAR(length) where length is the UpperLimit value (default=200).

NUMERIC DATE BLOB SMALLBLOB INLINEBLOB

Types.NUMERIC Types.DATE Types.BLOB WTTypes.SMALLBLOB WTTypes.INLINEBLOB

DECIMAL(28) DATETIME IMAGE VARCHAR (4000) VARCHAR (4000) IMAGE Two columns are generated. The encoded object is stored in the VARCHAR column if it fits, otherwise the IMAGE column is used. BIGINT

SEQUENCE

WTTypes.NUMERIC

NUMBER

31-42

Windchill Customizers Guide

Table 8-2 : How common Java types map to Rose Types


Java Type java.lang.Integer(int) java.lang.Long (long) java.lang.Short (short) java.lang.Byte (byte) java.lang.Float (float) java.lang.Double (double) java.lang.Boolean (boolean) java.lang.Char (char) Default Mapping INTEGER BIGINT SMALLINT TINYINT REAL DOUBLE BIT CHAR JDBC Type Types.INTEGER Types.BIGINT Types.SMALLINT Types.TINYINT Types.REAL Types.DOUBLE Types.BIT Types.CHAR BLOB java.lang.String java.math.BigDecimal java.sql.Date java.sql.Time java.sql.Timestamp java.sql.Blob wt.fc.LobLocator VARCHAR NUMERIC DATE DATE DATE BLOB BLOB Types.VARCHAR Types.NUMERIC Types.DATE Types.TIME Types.TIMESTAMP Types.BLOB Types.BLOB SEQUENCE Allowable Mappings

INLINEBLOB

SMALLBLOB
All other types BLOB Types.BLOB

INLINEBLOB

System Generation

31-43

Java to SQL Mapping


Each persistable class maps to a database table. Each persistent attribute in the class is mapped to a column name in the table. Structured attributes, like the Address class shown earlier, are decomposed into their simple attributes. Attributes are stored as lobs when no SQL-supported mapping is found, or if the cardinality is greater than one (because SQL cannot allocate space for an indefinite number of columns and rows). Tables contain all the attributes they inherit from classes above them. Because a class must be persistable to be in the database, all tables contain the persistInfo attributes, including the object identifier. The figure below shows a representation (not the actual columns) of the table that is generated for the modeled class.

Mapping a Model to the Database

MyItem is persistable because it extends Item, which extends WTObject, which implements the Persistable interface. Therefore, a table is created in the database for the objects in MyItem. The first element shown in the table, Attributes of superclasses, represents the persistent attributes (from persistInfo) that MyItem inherits from its superclasses. Each of the attributes would be mapped to a separate column in the actual table. One of those columns would be the object identifier. Attribute a1 is a String, so column A1 is a VARCHAR (NVCHAR for SQLServer). Attribute a2 is a Date (actually a java.sql.Date), so column A2 is a DATE (DATETIME for SQLServer). Attribute a3 has no SQL mapping support but is serializable so the value for a3 is stored in column A3 as a BLOB (IMAGE for SQL Server).

31-44

Windchill Customizers Guide

MyItem has a one-to-one composite aggregation relationship with Address, so the attributes of the Address class are mapped to the MyItem table. Windchill uses a naming algorithm to map attributes of an embedded structured attribute to table column names. To list the mapping, use the InfoReport utility mentioned in the section on how Rose UML maps to Info objects, earlier in this chapter. MyItem has a one-to-many composite aggregation relationship with NameValue, so NameValue is stored as a BLOB. By default, the class name is mapped to the table name. You can specify a different name with the Rose specification table name property. Caution: Each class must be mapped to its own unique table name. If the table name of a customized class conflicts with that of an out-of-the-box class or another customized class, then it must be changed using the Rose specification table name property. Similarly, you should change the table name to avoid matching a datastore reserved word used in your database (such as VIEW). Some additional properties can be specified to influence storage options. The storage for tables, indexes, and blob data is referred to as a tablespace in Oracle and a filegroup in SQLServer. The Windchill datastore term for both of these is tablespace. By default, all Windchill tables and indexes are created in the Windchill users default tablespace. Data for the table can be stored elsewhere by specifying a TableSpaceName. If an IndexTableSpaceName is specified, it is used to store the indexes for the table. The TableSize (TINY, SMALL, MEDIUM, LARGE, or HUGE) is used together with the associated properties in the tools properties1 to specify storage parameters for tablespace. The default storage mechanism for BLOB attributes is to store them in their own tablespace. The name of the tablespace is a configurable property in the tools properties. The default name is BLOBS. For further information, see the section on creating large objects in the Creating Large Objects (LOBs) chapter on page 43-1. By default, generated SQL files explicitly reference two different tablespaces, blobs and indx. All blob data storage is allocated in the blobs tablespace and all index storage is allocated in the indx tablespace. The storage for all other schema objects (e.g., tables) is not specified, so their storage is allocated in the default tablespace configured in the datastore. The default values for all of these tablespaces can be overridden in user.properties using the properties, wt.generation.sql.BLOBTablespaceName, wt.generation.sql.indexTablespaceName, wt.generation.sql.defaultTablespaceName, and wt.generation.sql.auditTablespaceName.In addition, the table and index tablespaces for a given table can be overridden using the Class Specification, Windchill tab, tablespace fields.

1.

See the tools.properties file and user.properties file descriptions in the The Windchill Development Environment chapter on page 2-13.

System Generation

31-45

Each attribute of the table also has properties which can be specified for the DDL generation, such as whether to allow NULLS or whether to index the attribute. If more complex indexing is required, then the Rose Class specification Windchill index properties should be used. There are several index entries available for specifying composite indices. Composite unique indices are also supported. See the Rose Windchill Help documentation for more information. Typically indices are generated into the associated table creation script. However, a utility, IndexGenerator, is also available that generates scripts containing only indices. For complex DDL statements associated with a class that cannot be handled by the SQL generation support, the user additions script feature is available. It is recommended that this feature only be used if absolutely necessary. When the Rose modeling DDL generation features are used, this information can also be used by the upgrade tools to ensure that the DDL is migrated properly. Every generated sql script contains a line at the end to execute the statements in an associated sql file. If the <tablename>_UserAdditions script is located in the same directory as the table script, then this line is not commented out of the script that creates the table. For a many-to-one aggregation implemented via a foreign key, the autoNavigate property can be used. When the autoNavigate property is set to true, the runtime query APIs treat the columns on the base table along with the columns of the aggregated table in much the same was as a database view. The two tables are implicitly joined via the foreign key. There are two types of modeled sequence data types. For attribute-based sequences, you can make the attribute type Long and select SEQUENCE from the WT_Oracle tab for the column type. This causes the DDL generation to create a sequence (if it does not already exist) with a name that consists of the attributeName and the suffix "_seq". When an object that uses an attribute-based sequence is created and persisted in the datastore, the sequence value is incremented and used for that attribute's value. Sequences can also be created as standalone datastore elements. A sequence will be generated for any class that extends wt.fc.DatastoreSequence. The datastore schema name, initial seed value, and increment value can all be set from the Rose model. You can use PersistenceManager.getNextSequence() to obtain the next available sequence number. This method returns a String, so you would either use the value as a String or convert it to whatever you need. All the database scripts necessary for a given java package are generated to an associated subdirectory of the database generation directory. In addition, "make" scripts are generated for the entire package. The "Make_<package name>" script calls all the scripts for creating the datastore schema objects. The "make" scripts will also call the associated make scripts in any nested packages.

31-46

Windchill Customizers Guide

How Rose UML Maps to Localizable Resource Info Files


Since Windchill is localized to run in a variety of locale specific languages, default display names are generated into localizable resource info (.rbInfo) files, for each model element name that might need to appear on a user interface. Language translators can then create localized versions of these files, so that modeled elements can be displayed in a locale specific language. The Localizable property is available on the Windchill tab of the Package, Class, Attribute and Association Role specifications in Rose. The purpose of this property is to limit the entries in the resource info files to those that need to be translated. The Class Localizable property is an enumerated type, and has three possible values: <Default>, True and False. The default value is <Default>. The Class will be considered Localizable by the localizable display generator only under the following circumstance: The Class Localizable property is explicitly set to True

The Localizable property for Attributes and Roles is also an enumerated type, and thus has possible values: <Default>, True and False. The default value is <Default>. These elements will be considered Localizable by the localizable display generator only under the following circumstance: The element's Localizable property is explicitly set to True

If the resource info file contains an entry for a particular model element, the generator will not overwrite it, but it can remove it if the modeled element no longer exists, or if it is no longer considered localizable. The removal of elements is controlled by the wt.generation.cleanupDisplayNames property in the tools properties. For more information on creating localizations, see the Internationalization and Localization chapter on page 39-1. The generated resource info files should only be edited by the owner of the package. The resource info tool set provides a means of customization, where the customers of the package can define customizations in a separate file. For more information on customizing localizable resource entries, see Defining Localizable Text for the UI in the Generic UI Customizations chapter on page 9-1. The name of the file is "ModelRB.rbInfo", with the simple package name prepended, for example, partModelRB.rbInfo. The following sections describe the generated resource info files.

Metadata Resource Info Header


Each resource info file contains the following lines that define certain file level information:
ResourceInfo.class=wt.tools.resource.MetadataResourceInfo ResourceInfo.customizable=true ResourceInfo.deprecated=false

System Generation

31-47

Resource Entry Format


See Resource Entry Format in the Internationalization and Localization chapter on page 39-9. 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.

Metadata Resource Entry Examples


Below are examples of the default entries that are generated.
WTPart.value=Part WTPart.partType.value=Part Type

The first entry is the display name for the WTPart class, and the second is the display name for partType attribute of the WTPart class. These values will only be generated once, so that the package owner can override the default values, if desired. For example, the value for the partType attribute could be changed as follows:
WTPart.partType.value=Type

In addition, any of the keys described in the Resource Entry Format on page 39-9, could be added for an element. For example, the following information could be added for the partType attribute.
WTPart.partType.fullDisplay=Part Type WTPart.partType.longDescription=Classification of parts according to predefined types.

Note: Follow the practices described in the Managing Customizations chapter on page 5-1 when customizing rbInfo files.

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 modelRB file, use the following command: ResourceBuild <absolute_directory> For example:
ResourceBuild <Windchill>/src/wt/part

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 wt/part

31-48

Windchill Customizers Guide

The resulting resource file is named <name>RB.ser, which is a serialized instance of SerializedResourceBundle. For example, src/wt/part/partModelRB.rbInfo will build to codebase/wt/part/partModelRB.RB.ser. To print the contents of the serialized resource bundle, you can run the following utility:
windchill wt.util.resource.ResourceBundleUtil <fully_qualified_name> [<locale>]

For example:
windchill wt.util.resource.ResourceBundleUtil wt.part.partModelRB en_GB

The output goes to: $(wt.temp)part.partModelRB_en_GB.lst

System Generation

31-49

Using the Windchill System Generation Tool


When you are ready to generate code, the packages being generated must be loaded in the model. Any model dependencies will automatically be loaded as a result of generating. Therefore, it is not necessary to load the entire model, or even to manually load dependent packages. Also, ensure that your WT_WORK Rose Edit Path variable specifies the correct location for the generated mData (model data) files. To use the Windchill System Generation Tool from Rose, select the classes and packages for which you would like to generate code. Go to the Tools menu, select the Windchill menu item, and then select the System Generation option. A popup window allows you to select the desired system generation options. WT Introspector Support creates the Info objects. Database Support creates the DDL scripts for the database. Localizable Displays updates the resource info (rbInfo) files for the generated packages.

System Generation Dialog

As mentioned in the overview at the beginning of this chapter, the system generator creates mData files which, in turn, are used to create Java code, Info files, SQL files and Resource Info files. The system generator also updates the classRegistry, descendentRegistry and associationRegistry, properties files.

Registry Files
The classRegistry, descendentRegistry, and associationRegistry files are located in the directory specified by the wt.generation.bin.dir entry in the tools properties. The classRegistry file contains all the information the code generator needs to create import statements for the generated Java classes. When classRegistry is

31-50

Windchill Customizers Guide

initialized, it goes through all the directories in your CLASSPATH variable and makes an entry for every class it finds. The classRegistry must be deleted and regenerated if you change your CLASSPATH to include new packages that contain classes for which the code generator will need to generate imports. As the number of CLASSPATH packages increases, the potential for conflicts increases. These conflicts are best resolved by explicitly modeling package level dependencies in Rose. The generator will then use this information to resolve any ambiguities that occur due to having multiple classRegistry entries for a particular class name. The descendentRegistry file contains genealogy information about which classes extend the classes above them. It is required to support subclass queries. The associationRegistry contains information about Persistable associations. Classes that are renamed or removed from a package will be automatically removed from the registries upon a regeneration of that package. A complete package can be removed from the registries (uninstalled), by using the modelUnInstall script.

Generating mData Files


An mData file is an ASCII file in non-proprietary format that contains all the information the Windchill system generation tool needs. It is an intermediate file format that allows for support of other model specification tools in the future. The mData files contain all of the information about the models. The export tool creates one mData file for each package in Rose and puts them in the WT_WORK directory. The mData files have a directory structure that maps to the package structure inside Rose. For example, because there is an fc package in Rose, there is a corresponding fc directory in the WT_WORK directory. In that fc directory is one mData with the name of the package (for example, fc.mData). Using mData files, the system generator creates Java classes and Info files. Java classes are source code that is generated into the source tree directory. Info files, because they are serialized resource files, are generated into the directory where Java classes are located.

Generating Java Code


As described earlier in this chapter, one Java class is generated for each modeled class. In addition, classes modeled as remote interfaces (such as TimelineService.java) will have forward classes generated for the service (such as TimelineServiceFwd.java). All the generated Java classes are put into directories, specified by the wt.generation.source.dir entry in the tools properties, which follow the package structure. All the classes generated for a particular package are placed in the corresponding directory.

System Generation

31-51

Generating Info Files


Info files contain all the metadata needed by the run time system. They are generated from the corresponding mData files, one Info file for every interface, and one for each class that implements NetFactor. Info files are put into directories, specified by the wt.generation.bin entry in the tools properties, using a directory structure that follows the package structure. The generated file name is the same as the class name plus the suffix ClassInfo.ser (such as MyItem.ClassInfo.ser).

Generating SQL Files


SQL files contain DDL for generating datascore schema objects for persistable classes. On the System Generation window, you can choose Database Support and the system generator creates the SQL files for you. If you do not choose that option, the system generator creates the information necessary for you to generate the SQL files yourself. Input always comes from the corresponding Info files. A utility is provided which allows you to generate SQL yourself. For each persistent class from your model, enter the following command: JavaGen "<your package .your classname>"F F True F F Or, to generate the SQL for an entire package, enter the following command: JavaGen "<your package >.*" F F true F F When specifying your class, include the fully qualified name of the class, which includes the parent package names. If you want to change the default storage parameters in the user.properties file and recreate all the SQL, Windchill DDL can be regenerated for all modeled and registered classes by entering the following command: JavaGen registry F F true F F DDL is generated into a datastore specific sql subdirectory named by the wt.generation.sql.dir property you specified in the user.properties file. For SQLServer, the directory name is sqlServer. For Oracle, the directory name is sql. For Oracle, if the wt.db.bytesPerChar property is greater than one, then the numeral is appended to the "sql" name. For example, if wt.db.bytesPerChar is 3, then the directory name would be sql3. File names are of the form create_ <tablename >.sql. Regardless of how you generated the SQL files, you must execute the DDL in these files to create the schema object. For Oracle, Oracles SQLPLUS application is used. Ensure that your SQLPATH environment variable is correct or, in the command you enter next, specify the full path to the SQL file. Use the following command: sqlplus <user/password >serviceName > @create_ <your table name >

31-52

Windchill Customizers Guide

If you have classes and tables, it is useful to create a single SQLPLUS script that can execute each @create script. (The create_ddl_wt.sql script is an example.) For SQLServer, a java command line application is provided in Windchill codebase. In addition, a bat file has also been created in $wt.home/db/sqlServer. Use the following command: execute_sql_script create_ <your table name >

System Generation

31-53

Using Windchill System Generation in a Build Environment


Using the Windchill System Generation tools in an integrated build environment requires an understanding of the dependencies that need to be managed. The following table shows the input and output relationships between the various artifacts of system generation.

Process

Input(s)

Outputs

Export Model Data Populate Model Registries

Rose model (.mdl and/or .cat) mData files for all dependent packages

mData file modelRegistry.properties descendentRegistry.properties 1 associationRegistry.properties 1 classRegistry.properties

Populate Class Registry

tools properties wt.classRegistry.search.path tools properties wt.classRegistry.search.pattern classRegistry.properties modelRegistry.properties registered mData files mData file for target package modelRegistry.properties registered mData files mData file for target package .ClassInfo.ser files for target package and dependents .mData file for target package .rbInfo files for target package

Generate Java Source

.java files modelRegistry.properties descendentRegistry.properties associationRegistry.properties

Generate Info Objects

.ClassInfo.ser files . modelRegistry.properties descendentRegistry.propertiesN associationRegistry.properties .sql files .rbInfo files .RB.ser files

Generate SQL Scripts Generate Resource Info Build Resource Bundles

1. Accumulated during generation, but used to define the modeled relationships for the installed runtime application.

Management of the mData File


An mData (model data) file is generated from the Rose .mdl and/or .cat file by using the Windchill Generation option on the Tools menu in Rose. If the mData will be used to generate code in an integrated build environment, the mData file must be kept synchronized with the cat file. This is best accomplished by always

31-54

Windchill Customizers Guide

checking in and checking out the two files in tandem, and ensuring that the generated mData reflects the saved version of the cat file.

Build Sequence
The following table describes the steps and commands used in a build sequence.

Step

Description

Command

Create classRegistry, based on search path and pattern defined in tools properties.1 Register all models that will be integrated Generate Java source code, info objects, SQL and resource bundle files scripts for target packages.2 Build the resource bundles for target directory. Compile Java source code.

tools class_registry -Dclass_registry.use_env=true ModelInstall "<package>.*" JavaGen "<package>.*"

2 3

4 5

ResourceBuild"<dir\sub>" javac ...

1. The system generation tool will create a classRegistry if one does not exist. 2. Remember to update database table structures after generating SQL scripts that have structural changes.

Command Line Utilities


Most of the utilities below are wrappers around Ant tasks that reside in bin\ tools.xml. Therefore, the utilities below, plus others, can also be executed directly with Ant.
tools

Access point to Ant targets that implement most of the utilities listed below. Executing this script with no arguments will list the targets that are available and explain how to get configuration options help for each target.
tools class_registry

Creates a class registry from scratch, searching for *.class & *.java files in the specified classpath. To specify the classpath, use one of these properties: class_registry.use_env - if true, will use the environment's classpath class_registry.classpath - can define any specific classpath

ModelInstall

Updates the model registries with all the modeled packages specified by Arg1. Arg1 can be either of the following: "<package>.*"

System Generation

31-55

Registers the single package specified. "<package>.**" Registers the package for each mData found recursively under the <package> directory.
ModelUnInstall

Removes the modeled packages specified by Arg1 from the model registries. Arg1 can be either of the following: "<package>.*" Removes the single package specified. "<package>.**" Removes the package for each mData found recursively under the <package> directory.
JavaGen

Generates the outputs specified by the arguments for the classes/packages specified by Arg1. Arg1 can be any of the following: <package>.<Class> Generates outputs for the single class specified. <package>.* Generates outputs for the single package specified. <package>.** Generates outputs for each mData found recursively under the <package> directory. registry Generates outputs for all registered packages. The following additional arguments can be specified: Arg2 Specifies if Java Source will be generated. Arg3 Specifies if Introspector Info Objects will be generated. When using this argument, it is recommended to comment out the following line in the moduleRegistry.properties file:
Module1=WNC/Windchill

Therefore, you should generate Info Objects separately from any other generations you are performing. For example, when generating info objects for all registered packages, do the following:

31-56

Windchill Customizers Guide

1. Comment the moduleRegistry entry indicated above. 2. Execute JavaGen registry f true f f f 3. Uncomment the moduleRegistry entry. Any other generations should be performed with Arg3 set to f. Arg4 Specifies if SQL scripts will be generated. Arg5 Specifies if Model Check will be performed. Values for arguments not passed will be obtained from the tools properties. Arg6 Specifies if Display Names will be generated into resource info files.
ResourceBuild

Builds the runtime resource bundles for the packages/directories specified by Arg1. Arg1 can be any of the following: <package>.<resource> Builds resource bundle for the single resource info. "<absolute_dir\sub>" Builds resource bundles for each resource info found under in the directory. ( <absolute dir\sub>is an absolute directory.) The following additional arguments can be specified: Arg2 Specifies if locale specific files will be built. (wt.locale.set in wt.properties define valid locales)
InfoReport

Reports the contents of info objects to a text file for classes/packages specified by Arg1. Arg1 can be any of the options below. Note: To display characters entered using something other than the default encoding, set the wt.locale.encoding property to the encoding appropriate to your locale before running this utility. <package>.<Class> Reports for the single class specified. <package>.*

System Generation

31-57

Reports for the single package specified. registry Reports for all registered packages.
VerifyEnvironment

Verifies the existence and ability to load all classes and serialized info objects that are referenced in the registry files. One caveat is that classes that have static initialization that requires a running method server environment will fail to load. Arg1 can be any of the following: executeTool wt.introspection.VerifyEnvironment "<package>.<Class>" Verifies the single class specified. executeTool wt.introspection.VerifyEnvironment "<package>.*" Verifies the single package specified. executeTool wt.introspection.VerifyEnvironment registry Verifies all registered packages.

31-58

Windchill Customizers Guide

IndexGenerator Generates index creation (and drop) DDL to a standalone SQL script. The utility supports both a single package and all indices for all modeled packages. executeApp wt.tools.generation.sql.OracleIndexGenerator "*" "create file name" "drop file name" Generates index creation DDL for all modeled packages to the specified files. Files names must be absolute. The "*" parameter must be specified in quotes. executeApp wt.tools.generation.sql.OracleIndexGenerator <package>.*" "create file name" " drop file name" Generates index creation DDL for the package to the specified files. If a file path is not absolute, then it is treated as path relative to the wt.generation.sql.dir directory.

System Generation

31-59

Deploying Modeled Customizations


Objective
You have created some modeled customizations on a development system, using Windchill InfoModeler. You want to deploy these customizations on your deployment system.

Background
It is recommended that you develop Windchill customizations on a development system that is separate from your deployment system. If you create modeled customizations (that is, using Windchill InfoModeler), follow this best practice to deploy your generated artifacts, rather than regenerating them on the deployment system. For example, your deployment system may run on an operating system (such as HP-UX) that does not support Windchill InfoModeler. To create modeled customizations, you could use a Windows server as your development system and run Windchill InfoModeler on that system. You would then follow this best practice to copy the necessary generated artifacts to your deployment system.

Scope/Applicability/Assumptions
Assume you have created new modeled customization packages on your development system. Assume that, prior to your new customization, your development environment included all the packages the production environment has. This best practice does not apply if, for example: Your production environment is an aggregation of multiple development environments; You have installed anything (such as an upgrade or module) into production that is not also in your development environment.

Intended Outcome
Your deployment environment will again mirror your development environment, including your new customizations.

Solution
Copy the relevant files from your development system to your deployment system.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:

31-60

Windchill Customizers Guide

Some method for transferring files from your development system to your deployment system. Executing SQL scripts on your database server.

Solution Elements

Element

Type

Description

Customized packages

Filesystem folders and their contents

Any folder corresponding to a customized package, containing compiled Java classes and related artifacts for the modeled and generated customization. This includes .class files, .RB.ser files, and .ClassInfo.ser files. Located under <Windchill>/codebase.

Registry files

Property files

Specifically, this includes the following registry files:


modelRegistry.properties descendentRegistry.properties associationRegistry.properties

Located in <Windchill>/codebase. SQL files SQL files These contain generated SQL scripts for creating the necessary database tables for your customized objects. Located in <Windchill>/db/sql.

Procedure - Deploying Modeled Customizations


Copy the folders and files described above from your development system to corresponding locations in your deployment system. 1. Place customized package folders in an equivalent folder structure relative to the <Windchill>/codebase directory. 2. Place the modified registry files in the <Windchill>/codebase directory on the deployment system, replacing existing registry files. 3. Place the generated SQL files in the <Windchill>/db directory on the deployment system. 4. Execute the SQL scripts (for example, by running SQL*Plus against an Oracle server) to create the customized database tables.

System Generation

31-61

31-62

Windchill Customizers Guide

32
Customizing Modeled Elements
This chapter describes how to customize modeled elements. Topic Page

Customizing Column Lengths...........................................................................32-2

32-1

Customizing Column Lengths


A column length for a modeled attribute can be customized. These column lengths are obtained through the wt.introspection package. The default column lengths are defined in the delivered Rose models with the attributes UpperLimit property. 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 which customization property entry must be added. 2. Add the customization entry to the appropriate customizations property file. 3. Generate the class info objects and SQL scripts. 4. Verify the customization. 5. Create 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 350. The following steps describe how to determine which customizations property file entry will contain the new column length, and how to set the value. The customization will be 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 properties1. Create this directory if it does not already exist. 1. Determine which customization property entry must be added: a. Obtain an info report for the class by executing the following command:
infoReport wt.doc.WTDocumentMaster

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:


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.

1.

See the tools.properties file and user.properties file descriptions in The Windchill Development Environment chapter on page 2-13.

32-2

Windchill Customizers Guide

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

3. Generate the class info objects and the SQL scripts: a. Update the serialized info object and the SQL script for the customized class by entering the following command (on one line):
ant -f <Windchill>\bin\tools.xml custom_column -Dgen.input=wt.doc.*

b. Inspect the infoReports descendents list for the WTDocumentMaster class:


getDescendentInfos(): ClassInfo wt.build.buildtest.SourceMaster ClassInfo wt.federation.ProxyDocumentMaster

c. If the customized class has descendants that are concrete, their tables must also be adjusted with the following commands (one line each):
ant -f <Windchill>\bin\tools.xml custom_column Dgen.input=wt.build.buildtest.SourceMaster ant -f <Windchill>\bin\tools.xml custom_column -Dgen.input=wt.federation.ProxyDocumentMaster

4. Verify the customization: a. 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. b. If the info report value is unchanged, perform the following steps: i. Verify that the generate step actually updated the following serialized info file:

<Windchill>\codebase\wt\doc\WTDocumentMaster.ClassInfo.ser

ii. Verify that a class or interface in WTPartMasters hierarchy does not also define the name attribute. This is done most easily by viewing the Attributes tab of the Class Specification dialog in Rose, with Show inherited selected. If the name attribute is defined in the hierarchy, the name attribute that was modeled originally must be customized.

Customizing Modeled Elements

32-3

5. Create the database tables, if they dont already exist, by executing the relevant SQL scripts generated above. If the tables already exist, adjust the length of the customized column by taking the following steps: a. Execute the Upgrade Manager to run the Compare Schema step only. See "Comparing a Database Schema with Persistence Model" in the Windchill Upgrade Guide. b. Inspect the generated output to find the SQL script(s) related to this customization. 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. Because, in this example, WTDocumentMaster.name is also the source for the derived attribute WTDocument.name, the derived attribute must also be customized in this manner. This customization is necessary because the derived attribute, WTDocument.name, does not get its UpperLimit from the source attribute, WTDocumentMaster.name. The derived attribute also explicitly set the UpperLimit property in the model. Therefore, the customization must be defined explicitly for the derived attribute WTDocument.name. Following the preceding steps would determine that a WTDocument.name.UpperLimit entry would be set in the customization property file <Windchill>\wtCustom\wt\doc\ docModel.properties. This additional step applies specifically to the way derived attributes work and is not necessary for normal attributes.

32-4

Windchill Customizers Guide

33
Enumerated Types
This chapter describes enumerated types. Topic Page

The EnumeratedType Class...............................................................................33-2 Creating an EnumeratedType Subclass.............................................................33-3 Editing the Resource Info for an Enumerated Type..........................................33-7 Localizing an Enumerated Type........................................................................33-9 Extending an Enumerated Type ......................................................................33-10 The Enumerated Type Customization Utility .................................................33-11 GUI Usage of an Enumerated Type ................................................................33-12

33-1

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 not available for generic use by GUI components; they must use getDisplay().

33-2

Windchill Customizers Guide

Creating an EnumeratedType Subclass


To create an EnumeratedType subclass, perform the following steps: 1. Model a class that extends wt.fc.EnumeratedType.

Select the EnumeratedType property set on the Windchill tab of the Class Specification. This property set provides just the properties that apply to EnumeratedType classes, and changes the default values of certain properties, such as PrimitiveType to String. If the values are to be ordered explicitly, set the ExplicitOrder property to True. Otherwise, the values will be ordered alphabetically at runtime, using the locale-specific display.

Enumerated Types

33-3

The Localizable property under the UI Properties section refers to the name of the class being localizable, not the display values.

2. Generating the EnumeratedType also generates its companion resource info file. For MySize, it will be named MySizeRB.rbInfo. If the wt.resource.updateLocales property of the tools properties1 is set to true, any locale-specific versions of the rbInfo file will also be updated, indicating which entries need to be translated.

1.

See the tools.properties file and user.properties file descriptions in the The Windchill Development Environment chapter on page 2-13.

33-4

Windchill Customizers Guide

3. Optionally, model any desired programmatic constants. For example:


SMALL : MySize = toMySize( "Sm" )

Modeled constants are Static and Final. A value definition for each modeled constant will be generated in the resource info file.

Enumerated Types

33-5

Select the constantEnumeratedType property set on the Windchill tab of the Attribute Specification. This property set provides just the properties that apply to EnumeratedType constants, and changes the default values of certain properties, such as BeforeStaticInitializer to False. If the constant represents the default value for the EnumeratedType, set the DefaultValue property to True. To explicitly define the display name to generate into the resource info file, set the Display property. Otherwise, the generated display name will be based on the initial value of the constant.

33-6

Windchill Customizers Guide

Editing the Resource Info for an Enumerated Type


The name of the generated resource info file is RB.rbInfo, with the simple package name prepended, for example, MySizeRB.rbInfo. The following sections describe the resource info files that are generated.

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 in the Internationalization and Localization chapter on page 39-9. 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 that are generated:
lrg.value=lrg lrg.order=30 med.value=med med.order=20 sm.value=sm sm.order=10

These default values are generated only once, so that the package owner can override the default values, if desired. If the classs ExplicitOrder property is set to True, the orders are controlled by the generator, and should not be edited directly in the resource info file. If one of the constants has DefaultValue set to True, it is controlled by the generator. For example, the value for the "sm" value could be changed as follows:
sm.value=Small sm.shortDescription=Small Comment sm.order=10 sm.defaultValue=true

Enumerated Types

33-7

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_name> For example:
ResourceBuild wt.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 wt/example

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.

33-8

Windchill Customizers Guide

Localizing an Enumerated Type


To have a locale-specific set of display values for an enumerated type, a localespecific version of the enumerated types 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

33-9

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.

33-10

Windchill Customizers 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, this utility should be used 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.

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.

Enumerated Types

33-11

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. 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 the Managing Customizations chapter on page 5-14) 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.)

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();

33-12

Windchill Customizers Guide

34
Windchill Design Patterns
This section describes design patterns that represent Windchills 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.

Topic

Page

The Object Reference Design Pattern ...............................................................34-2 The Business Service Design Pattern................................................................34-3 The Master-iteration Design Pattern .................................................................34-7

34-1

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 objects 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 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.

34-2

Windchill Customizers Guide

The Business Service Design Pattern


The most prevalent design pattern referenced to build Windchill services is the business service design pattern (figures B-2, B-3, and B-4).

Business Service Interface

Business Service Classification

Windchill Design Patterns

34-3

Business Service Information

This pattern has the following major kinds of abstractions: Type Cookie Helper Service ServiceEvent ServiceException

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. 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 Cookies cardinality is 0..1, the Cookie and all its nested attributes can be stored as null if none of the Cookies 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. The Helper abstraction provides a class representing the services 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. The static attribute is a remote reference to the services server-

34-4

Windchill Customizers Guide

side functionality by means of initializing the "service" attribute as shown in the following example.

Initializing the Service Attribute

Notice the property in bold type named "InitialValue" and its value, "new ServiceFwd()." This property setting directs the code generator to make an initializer for the "service" instance to what is specified as the value. The service name appended with "Fwd" is the name of the class generated for a class stereotype as being a "RemoteInterface." 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 stereotyped as a "RemoteInterface." Otherwise, the services 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 services methods exists. This standard implementation is a singleton executing on the server and is the default for all Windchill services. 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

34-5

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 services 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.

34-6

Windchill Customizers Guide

The Master-iteration Design Pattern


The design pattern that you must adhere to for all versioned data is the masteriteration 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 services API. The business object must assert itself as being a kind of mastered object in order for its instance to be iterated. 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

Windchill Design Patterns

34-7

superseded, rolled back, and rolled up through the version control services 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.

34-8

Windchill Customizers Guide

35
Developing Server Logic
This chapter describes how to develop server logic. Topic Page

Overview ...........................................................................................................35-2 Service Management .........................................................................................35-2 Service Event Management...............................................................................35-4 Implementing Business Data Types ..................................................................35-8 Lightweight Services.......................................................................................35-18 Customizing service.properties .......................................................................35-24 Windchill Multi-object Operations .................................................................35-26

35-1

Overview
Developing server logic is primarily a task of designing and implementing business data types and services. To develop these kinds of abstractions, you must understand applicable Windchill design patterns, service and event management in general, and guidelines used in detailed design and implementation. A business data type can be characterized as an important piece of information known in the business domain. This information consists of data and/or state once it exists and is recognized in the system. A business service can be characterized as a set of one or more functions that carry out business-specific processing. The purpose of these kinds of abstractions is to separate the entity objects from control objects. Once they are separated, developmental impacts and risks, typically caused by evolving requirements and behavior, are reduced. That is, data and behavior changes are less likely to directly affect each other given sound abstraction and encapsulation. In addition to the information presented here, see the Windchill Design Patterns chapter on page 34-1. That chapter describes design patterns that represent Windchills current best practices regarding development of server logic. See the Windchill Services chapter on page 30-1 for a description of standard, reusable Windchill services.

Service Management
The development of the standard, reusable Windchill services caused the need for a general mechanism to manage the behavior of and interaction between these services. This service management mechanism specifies a protocol for startup, shutdown, and communication between Windchill services.

Automatic Service Startup


The wt.properties configuration file includes entries that specify which services should be started automatically when the Windchill server is launched. In addition, each entry specifies a pairing between the service interface and which implementation of the service should be constructed. That is, if other implementations are supplied in addition to the standard implementation of the service, one of the other implementations can be declared to execute in these entries. On the other hand, multiple service interfaces can also be implemented by a single class. For example, the PersistenceManager and PersistenceManagerSvr are both implemented by StandardPersistenceManager. The following is an example of several entries for the standard Windchill services:
# Application Services wt.services.service.10 = wt.session.SessionManager/ wt.session.StandardSessionManager wt.services.service.20 = wt.fc.PersistenceManager/ wt.fc.StandardPersistenceManager wt.services.service.30 = wt.fc.PersistenceManagerSvr/ wt.fc.StandardPersistenceManager

35-2

Windchill Customizers Guide

wt.services.service.40 = wt.queue.QueueService/ wt.queue.StandardQueueService

Numbering of Service Entries


The service number dictates the startup order of the service. Services are started from lowest to highest number. If a service depends on other services, those services must be started first. There are no reserved ranges or values for Windchill services or customized services. At each new release, any out-of-the-box Windchill service may be renumbered, and any new number may be assigned. The maximum value for a service number is 231-1 (=2147483647). When defining customized services, you should choose a minimum service number that is significantly higher than the highest number used by any Windchill service. The numbers for the Windchill services can be determined by inspecting the wt.services.service.#### entries in <Windchill>/codebase/wt.properties in your installation. Each time you install a new release of Windchill, you need to check the entries in wt.properties to ensure that all of your customized services still have numbers higher than the highest Windchill service number. For each customized service, you must ensure that its number does not duplicate any number for an existing Windchill service or customized service.

Services and Managers


There are entries that are termed either a service or a manager. During the initial stages of Windchill development, the use of the terms manager versus service was unclear. It has been agreed that service represents the more general concept and manager represents those services that are characterized more as managing groups of objects. Currently the terms manager and service appear interchangeably.

Service Startup and Shutdown


In order for services to be managed, they must implement the wt.services.Manager interface. This interface specifies methods for starting and stopping services. A reference implementation of wt.services.Manager, named wt.services.StandardManager, provides most of the base functionality required for service management. If a new type of service does not require any special startup or shutdown processing, it can extend the base class wt.services.StandardManager without overriding any of its methods. Two methods in class wt.services.StandardManager are intended to be overridden to specialize startup and shutdown processing. These methods are performStartupProcess and performShutdownProcess. Examples of startup processing include subscribing to service events and establishing queues for use in background processing. For further information, see Service Event Subscription later in this chapter (page 35-5).

Developing Server Logic

35-3

Service Management
ManagerService is a manager which is used to startup and provide access to a predefined list of managers. This list includes different managers for services mentioned in the Windchill Services chapter on page 30-1. In addition to managing managers, the ManagerService provides a synchronous event dispatch service. This service can dispatch a vetoable or non-vetoable event to all listeners for the event key. Each listener may or may not object to the event. The service performs a synchronous "in thread/transaction" notification of each event listener for the event branch identified by the event key. It calls the notifyEvent operation on each subscriber.

Service Event Management


One means of interservice communication is by direct peer-to-peer cooperation and collaboration. No special mechanisms are required to support this kind of communication because it is already defined as explicit invocations. However, with a plug-and-play architecture, services become more independent and unaware of other services. To facilitate interservice communication between these autonomous services, general mechanisms are needed to convey information between these services and to manage unordered synchronous communications. Each service is responsible for specifying service events that can be emitted when significant events that may be of interest to other services occur within the service. Also, each service must establish listeners to other services events in order to be notified of and react to other significant events occurring within the system.

Service Event Registration


Services can register their events with the wt.services.StandardManager when they are started. Registering service events at startup time makes the events known to processes, such as access control. The following example illustrates how events are registered in an overridden wt.services.StandardManagers registerEvents method for the version control service:
public void registerEvents( ManagerService manager ) { manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent.NEW_VERSION ), VersionServiceEvent.class.getName(), VersionServiceEvent.NEW_VERSION ); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent.PRE_SUPERSEDED ), VersionServiceEvent.class.getName(), VersionServiceEvent.PRE_SUPERSEDED ); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent.POST_SUPERSEDED ),

35-4

Windchill Customizers Guide

VersionServiceEvent.class.getName(), VersionServiceEvent.POST_SUPERSEDED ); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent.PRE_ROLLBACK ), VersionServiceEvent.class.getName(), VersionServiceEvent.PRE_ROLLBACK ); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent. POST_ROLLBACK), VersionServiceEvent.class.getName(), VersionServiceEvent. POST_ROLLBACK); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent. PRE_ROLLUP), VersionServiceEvent.class.getName(), VersionServiceEvent. PRE_ROLLUP); manager.addEventBranch( VersionServiceEvent.generateEventKey( VersionServiceEvent. POST_ROLLUP), VersionServiceEvent.class.getName(), VersionServiceEvent. POST_ROLLUP); }

Note: A more implicit means of registering events is by not doing so in the registerEvents method, but by allowing the event to be registered when it is first emitted. Once this occurs, all listeners subscribing to this event will be notified.

Service Event Subscription


In order for services to be notified of events occurring within the system, they must subscribe to each particular service event of interest. To do this, you must invoke the wt.services.ManagerService.addEventListener method with a listener and key identifying the event of interest. The listener specified during subscription must implement the wt.events.KeyedEventListener interface. It defines the notifyEvent and notifyVetoableEvent methods. The wt.services.ServiceEventListenerAdapter class is provided as a utility whereby a listener can extend it and override only the methods that are required for notification. The notifyEvent is a general method that can be used in all subscription cases. The notifyVetoableEvent method is more specialized; its intended use is to provide a means of vetoing an event via an exception. Typically event listeners are implemented using either anonymous or named instances of inner classes. This allows the outer class to be designed without implementing the wt.events.KeyedEventListener interface. This keeps the outer class pure in that its type directly reflects its purpose without having to implement a listener interface. The following is an example of how to override the performStartupProcess method and define and add a listener for a specific event:

Developing Server Logic

35-5

protected void performStartupProcess() throws ManagerException { // // // // At a request prior to a modification, if the target is a lockable object then validate if a modify on the object would be accepted. If not then veto it.

getManagerService().addEventListener( new ServiceEventListenerAdapter( this.getConceptualClassname() ) { public void notifyVetoableEvent( Object event ) throws WTException PersistenceManagerEvent pmEvent = (PersistenceManagerEvent)event; Persistable target = pmEvent.getTarget(); if (target instanceof Lockable) validateLock( (Lockable)target); } }, PersistenceManagerEvent.generateEventKey( PersistenceManagerEvent.PREPARE_FOR_MODIFICATION )); } protected void validateLock( Lockable object ) throws WTException, LockException { if (object.getLock() != null) { if (object.getLock().isSeized()) { if (!object.getLock().getLocker().getObjectId().equals( (Object) PersistenceHelper.getObjectIdentifier( SessionHelper.manager.getPrincipal() ))) throw new LockException( RESOURCE, "5", null ); } } }

Service Event Notification


A list of all listeners subscribed to a particular event is maintained by the ManagerService. This list is traversed in an unordered fashion and each listener is executed one after the other using synchronous Java method invocations. Listener notification methods execute in the same thread and database transaction as the event emitter. This means that database operations performed by a listener in response to a notification call are included in the transaction of the event emitter. The following is an example that shows the dispatching of an event like PersistenceManagerEvent.PREPARE_FOR_MODIFICATION:
protected void dispatchVetoableEvent( String eventType, Persistable obj ) throws WTException { PersistenceManagerEvent event =

35-6

Windchill Customizers Guide

new PersistenceManagerEvent( this, eventType, obj ); getManagerService().dispatchVetoableEvent( event, event.getEventKey() ); }

Service Event Exception Handling


When a listener vetoes an event, it does so by throwing an exception. When an exception is thrown, each listener that has already been notified of this event can handle this exception by either passing the exception through, catching and rethrowing it to clean up, or by implementing a "finally" clause to clean up. As discussed earlier, event notification is dispatched within the same thread and transaction frame as the event emitter. This means that an event emitter must roll back any database updates that it has made if there has been a veto by another listener. The following example illustrates this guideline. If the POST_STORE event is vetoed, control is transferred to the "finally" clause, where the transaction will be rolled back because the line that set the transaction to null was never reached.
public Persistable store(Persistable obj) throws WTException { checkStore(obj); obj.checkAttributes(); dispatchVetoableEvent( PersistenceManagerEvent.PRE_STORE, obj ); Transaction trx = new Transaction(); try { trx.start(); insert(obj); dispatchVetoableEvent( PersistenceManagerEvent.POST_STORE, obj ); trx.commit(); trx = null; } finally { if ( trx != null ) trx.rollback(); } return obj; }

Service Event Conventions


The meaning of any particular service event is up to the designer of the event. Events should include all the information required by event listeners for follow-on processing. The wt.events package includes a base event class, wt.events.KeyedEvent, which can be extended to create new event types. A common event design pattern includes pre- and post-events. Pre-events are used to indicate to listeners that an event is about to begin. They are typically intended to give listeners the opportunity to validate and possibly veto the event. Post-

Developing Server Logic

35-7

events are used to notify listeners that an event has finished. They are most useful when a service needs to perform some kind of post-processing as a result of the event. Not all events have to be either pre- or post-events. A singular definition of an event can be used to indicate some special occurrence, which may or may not have happened.

Implementing Business Data Types


A business data type can be characterized as an entity object (that is, a knower) that deals basically with abstracting some crisp and clearly definable piece of information in the problem domain. Therefore, business data types are primarily defined by data, not behavior, as in control objects (that is, doers). Because most of the specification of a business data type is by its attributes, implementation of this business information typically focuses on the classes attributes. In addition, because business data types are entity objects and are typically lightweight compared to control objects, they efficiently transport information between an application and the server in the three-tier (client, server, and database) architecture.

Initializing Business Attributes


Initialization of business data type attributes is done by implicitly code generated "initialize" methods. No constructors are generated for modeled business data types. Instead, factories are created for each modeled constructor and, within the factory, an instance is made. Then the initialize method with a signature that matches the factory is invoked. These initialize methods are empty at the first code generation and must be handimplemented because the code generator currently cannot make any assumptions on what attributes should or should not be initialized. By default, once these methods are implemented, their code is preserved for subsequent use. To mimic Java constructor chaining, each initialize method should always invoke its parent initialize method before doing anything else.

Business Attribute Accessors


Attributes are always generated as private fields with two accessors: a getter and setter method, like JavaBean properties. The getter is generated as a no-arg method that returns the value of the attribute. The setter is generated as a single-arg method which sets the attribute to the value of the arg. Depending on whether the attribute is constrained, the setter is generated with or without a wt.util.WTPropertyVetoException throws clause. This exception extends java.beans.PropertyVetoException and allows for a

35-8

Windchill Customizers Guide

customized message. The following example shows the property for constraining an attribute, and a getter and setter for an attribute named "note".

Constraining an Attribute

public String getNote() { //##begin getNote% [ ]348C64E401C5g.body preserve=no return note; //##end getNote% [ ]348C64E401C5g.body } protected void setNote( String a_Note ) throws WTPropertyVetoException { //##begin setNote% [ ]348C64E401C5s.body preserve=no noteValidate( a_Note ); // throws exception if not valid note = a_Note; //##end setNote% [ ]348C64E401C5s.body }

Note that the body of the methods are flagged as "preserve=no." This instructs the code generator to overwrite the code within a method. Getters and setters can be preserved by setting this flag to "yes", but in general this is not recommended. On the other hand, the code generator can be instructed to not generate a getter and setter for an attribute with the "GenerateAccessors" property on the Windchill tab set to "False."

Overriding Accessor Methods


Typically, overridden accessors do the following:

Developing Server Logic

35-9

Attribute validation (as shown in the example) Lazy attribute initialization Computed attribute access

The following is an example of overriding accessor methods.


public void setStatus(int status) throws PropertyVetoException { // Set the status to the closed-code only if // closure comments were provided. if (status == CLOSE_CODE) { if ((getClosureComments() == null) || (getClosureComments().equals("")) { throw new PropertyVetoException(); } } super.setStatus(status); }

Validating Business Attributes


Validating business data type attributes is handled at two distinct levels. The simplest and completely code-generated level is implemented as a validation method for a constrained attribute that is invoked by its setter. The mechanism used to veto the setting of an attribute is a wt.util.WTPropertyVetoException capable of being thrown from the setter. If an attribute is not constrained, the setter is generated without the capability of an exception being thrown. The properties for specifying limits on a String or numeric attribute are LowerLimit and UpperLimit. In both cases, the value supplied is treated as a literal or constant. This means that the validation method is code generated with "if" statements that use Java less than or greater than operators to test against the specified value in the LowerLimit or UpperLimit property, respectively. The

35-10

Windchill Customizers Guide

following examples illustrate the use of these two properties and the validation code that is generated automatically:

Validation Example

private void noteValidate( String a_Note ) throws WTPropertyVetoException { if ( a_Note != null &amp;&amp; a_Note.length() > MAX ) { // upper limit check Object[] args = { "note", "MAX_LENGTH" }; throw new WTPropertyVetoException( "wt.fc.fcResource", wt.fc.fcResource.UPPER_LIMIT, args, new java.beans.PropertyChangeEvent( this, "note", note, a_Note ) ); } if ( a_Note != null &amp;&amp; a_Note.length() < MIN ) { // lower limit check Object[] args = { "note", "MIN_LENGTH" }; throw new WTPropertyVetoException( "wt.fc.fcResource", wt.fc.fcResource.LOWER_LIMIT, args, new java.beans.PropertyChangeEvent( this, "note", note, a_Note ) ); } }

The other more general level of validating one or more attributes is to override and implement the "checkAttributes" method inherited from wt.fc.WTObject. This method is invoked before the object is stored in the database initially and every time it is modified. In this case the exception thrown is wt.fc.InvalidAttributeException, not wt.util.WTPropertyVetoException.

Developing Server Logic

35-11

Implementing the checkAttribute Method


The checkAttributes method shown in the following example is an alternative to the setStatus method shown in the example in Overriding Accessor Methods earlier in this section. It ensures that closure comments are provided if the status is to be set to 2. The checkAttributes method is called by the PersistenceManager to ensure the state of the object is correct before storing it in the database. The following is an example of implementing the checkAttribute method.
// Example checkAttributes method public void checkAttributes() throws InvalidAttributeException { // Ensure that closure comments are provided if the // status is set to the closed-code. if (getStatus() == CLOSE_CODE) { if ((getClosureComments() == null) || (getClosureComments().equals("")) { throw new InvalidAttributeException (); } } }

Business Attribute Aggregation


Structured attributes (that is, non-first-class) at all levels of associations are placed in the same database table as the first-class object that stores the structure attributes. The aggregated attributes must be object mappable and, regardless of cardinality, will always exist in the database table as a flat structure. The flatness of the tables is due to the fact that the database tier in the three-tier architecture is assumed to be a relational database, not an object-oriented database. However, if the top-level structured attributes cardinality is 0..1 or 0..* and it is not flagged as being required, it can be nullified in the database. Care must be taken if this top-level structured attribute aggregates any other structured attribute because the nested structured attributes will not be nullified.

35-12

Windchill Customizers Guide

Business Attribute Persistence


A business attribute is persisted as a column in a first-class objects database table if it is flagged as being "Persistent" as shown in

Persistent Attribute

Otherwise, it is treated as an in-memory attribute only and is not mapped to a column in the database table.

Business Attribute Derivation


Derived attributes are strictly generated as getters and setters without any such named field for the modeled derived attribute. Typically, the purpose of modeling a derived attribute is to make it act as a computed value when accessed. One side effect of derived attributes is they are neither serializable nor externalizable. They could be an implementation detail in the body of a class, but Windchills generated externalization methods will not recognize the attribute as existing. That is, the externalization methods to read and write an objects data are generated based on what is known in the object model, not the implementation. If an object with a derived attribute is either being transmitted across-the-wire, or is being stored/retrieved externally, the derived attribute within it is non-existent. Any assumption made in implementation where a derived attribute is required for processing after the object has been serialized or externalized may produce erroneous results unless the accessor is called to re-derive the attribute.

Developing Server Logic

35-13

Implementing Business Services


A business service can be characterized as a set of abstractions based on the business service design pattern that collectively provide essential behavior and processing for a problem domain. For further information on the business service design pattern, see the Windchill Design Patterns chapter on page 34-1. The main kinds of classes in a business service act as control objects (that is, doers) that carry out processing on business objects. Additionally, cookies are maintained by the business service that hold state and key information on a per object basis. Cookie classes are aggregated to interfaces that are managed by business services. For example, PersistInfo is a cookie class that is aggregated to the Persistable interface. Any class that implements Persistable will also aggregate PersistInfo, and the PersistenceManager business service will manage the attributes of PersistInfo such as createStamp and modifyStamp.

Initializing Business Services


Business services are designed to execute as singletons in the server only. When the server is launched, the wt.properties file is read to determine what services are to be started automatically. These specified services are constructed and statically initialized, service events are registered, and the services are then started. The ordering specified by wt.services.service entries in the wt.properties file controls the order in which services are started. If administrative access is required on service startup, it is necessary to create a new SessionContext and set the current user to the Administrator. It is equally important to reset the session context at the end of a services startup processing. To guarantee that a session context is always reset, it should be done in a "finally" clause.
protected void performStartupProcess() throws ManagerException { SessionContext previous = SessionContext.newContext(); // create new SessionContext try { // do startup processing such as registering // event listeners try { SessionHelper.manager.setAdministrator(); // } catch (UserNotFoundException wex) { System.err.println ("Administrator user doesnt exist (OK if installation)"); return; } // do startup processing that requires // administrative permissions such as // creating a queue } catch (WTException wex) {

35-14

Windchill Customizers Guide

throw new ManagerException (this, "Failed to initialize service."); } finally { SessionContext.setContext(previous); // restore initial SessionContext } }

Business Service Operations


Business service operations can be invoked either locally or remotely. Only remote invocations are made by a client. Local invocations can be either from a client or server. The business services Helper abstraction contains only methods that can be invoked locally. These methods are generally used for the accessing of the services cookie information. Other types of methods that aid in processing may also be implemented in a Helper. The Service abstraction contains methods that can be invoked locally on the server and invoked remotely from the client if the Service is stereotyped as being a "RemoteInterface." With this stereotyping and aggregation of the "service" in the helper, all public methods are available for use. The business service should ensure that all externally available operations are exposed either through the Helper or Service class. All other operations should only be available internally with the possible exception of methods on utility classes that are used by other services. Often business service operations executing on the server must perform database actions. To maintain database integrity, service independence, and loose coupling between other services, database changes should be protected by the use of transaction blocks. The following section of sample code serves as a guideline on how to implement transaction blocks:
public Persistable store( Persistable obj ) throws WTException { //##begin store% [ ]3458AD98008C.body preserve=yes Transaction trx = new Transaction(); try { trx.start(); dispatchVetoableEvent( PersistenceManagerEvent.PRE_STORE, obj ); checkStore(obj); obj.checkAttributes(); insert(obj); dispatchVetoableEvent( PersistenceManagerEvent.POST_STORE, obj ); trx.commit(); trx = null; } finally {

Developing Server Logic

35-15

if (trx != null) trx.rollback(); } return obj; //##end store% [ ]3458AD98008C.body }

Vetoing Business Service Events


When a business service is notified of an event occurring within the system, it has the option of vetoing the event. This is done by subscribing as a listener and implementing the notifyVetoableEvent method. The listener must process the events data and determine if a veto is applicable. If so, the listener throws an appropriate exception. Otherwise, the listener does whatever processing is required and allows the event to continue.

Business Service Rules


If applicable, a business service should implement rules to enforce consistent and correct functionality of its operations. The two basic forms of business rules are access control and problem domain integrity. Access control establishes who can act upon what and in what manner. The enforcement of access control in a business service is explicitly implemented. In the locking service, for example, when an object is requested to be locked, the service guarantees that the principal attempting to place the lock has modify access to the object such that the lock for it can be persisted in the database as shown below:
public Lockable lock( Lockable object, WTPrincipalReference locker, String note ) throws WTException, LockException, WTPropertyVetoException, PersistenceException { //##begin lock% [ ]342A8DDB0271.body preserve=yes Transaction trx = new Transaction(); // // // // // // // // // Check if the object is not currently locked and the locker has modify access rights then dispatch a vetoable event to signal listeners that a lock is about to commense. If no listener vetos the lock (i.e., no exception was thrown) then go ahead and set the objects lock state (i.e., cookie).

if (!object.getLock().isSeized()) { if (AccessControlHelper.manager.hasAccess( locker.getPrincipal(), object, WTPermission.MODIFY )) { dispatchVetoableEvent( LockServiceEvent.PRE_LOCK, object ); object.getLock().seize( locker, note );

35-16

Windchill Customizers Guide

// // // // //

Now update the object without changing the objects modify date. The modify date is left as is since all that is being updated is the cookie information, not the object.

try { trx.start(); PersistenceServerHelper.manager.update( (Persistable) object, LEAVE_MODIFY_DATE ); trx.commit(); trx = null; } finally { if (trx != null) trx.rollback(); } dispatchVetoableEvent( LockServiceEvent.POST_LOCK, object ); } } return object; //##end lock% [ ]342A8DDB0271.body }

Enforcement of problem domain integrity is somewhat different than access control. Maintaining correct problem domain behavior within the business service should always be a goal, but in particular there may be some special requirements that must be satisfied. As in version control, for example, when an object is checked in, it is then once again available to be checked out. However, if the object is already checked out, it can not be checked out again unless some sharing and merging rules are in place.

Business Service Communication


Business services can communicate with one another either directly through synchronous Java invocations or by events. Direct peer-to-peer communication to another service is how access control is implemented in all of Windchills services. This is the most rudimentary means of communication. Event-based communication is a more sophisticated means of communicating between services. Services can register their events and subscribe listeners to another services events when they are started. When a service event is emitted, all subscribed listeners are notified of the occurrence of the event. The event notification and responses are synchronous. Therefore, it is equivalent to method invocations to the services, except that services which cause events do not know which other services will be notified. If one of the notified services vetoes the event, the other services not yet notified are not informed.

Developing Server Logic

35-17

Lightweight Services
Lightweight services reside in the application layer between the client and the business service layer. Lightweight services are light because they do not start automatically and dispatch events. Consequently, lightweight services are not specified in the wt.properties file with wt.services entries. Lightweight service methods should be designed to do the following: Reduce the number of round trips between the client and the server. Provide task-specific and higher-level functionality than business service methods. Ensure client transactional integrity.

Lightweight services can dispatch events but should not listen for them. If a service is not started automatically, it will not be able to hear events that it is supposed to listen for until it is started. Lightweight services are an effective means to ensure client transactional integrity. Several client-server operations can be grouped into a single, lightweight service method call that will carry out these operations on the server in a single transaction. Lightweight services can be implemented in the following two ways: Through a modeled class that extends wt.services.StandardManager Through a non-modeled, inner class that implements wt.method.RemoteAccess

The following subsections describe both implementations.

The Modeling Implementation


Lightweight services are modeled like business services in that they are defined by a remote interface and have an implementation class that extends StandardManager. The remote interface enables the service to run in the method server and be invoked by remote clients (for example, applets). The mapping between the service interface and implementation class is accomplished with a naming convention. The implementation class for a lightweight service must have the same name as the interface with "Standard" at the beginning of the name. To use a lightweight service, create an instance of the generated Forwarder class and call the services methods through the Forwarder. This is similar to a business service where a static attribute on the Helper class is initialized with an instance of the Forwarder class. In both cases, the mechanism for invoking service operations is identical.

35-18

Windchill Customizers Guide

The following is an example of a lightweight service named CommentLogger. This model can be found in WTDesigner.mdl in the wt.services.test package.

CommentLogger Service Example

In this example, the CommentLogger interface defines a lightweight service that will log a message to the server log file. This service could be useful for applet clients that want to include a message in the server log. Without such a service, all System.out.println calls will send their output to the browsers Java console window instead of the server log file. StandardCommentLogger implements this service by extending wt.services.StandardManager and the CommentLogger interface. Note that the name must be StandardCommentLogger in order for the ManagerService to find the implementation class for the CommentLogger service. Since CommentLogger has a stereotype of RemoteInterface, a Forwarder class named CommentLoggerFwd is automatically generated. It is this class that is used to invoke the CommentLogger service methods:
CommentLoggerFwd logger = new CommentLoggerFwd(); logger.log("a message");

The Inner Class Implementation


The second way of implementing a lightweight service is through a non-modeled, inner class that implements wt.method.RemoteAccess. An example of an inner class implementation follows. The objectives are to invoke a complex server-side activity, collecting information of interest to the client, while minimizing the number of classes loaded by the client. These techniques improve performance for the client because loading classes can be slow and expensive. In this example, note the type of the inner class. To avoid IllegalAccess violations, the forwarder must be declared as a "public static class". Using this declaration, the MethodServer is able to instantiate and invoke methods on the inner class. Note also the technique for invocation of the desired server method. To avoid loading classes specified as part of the action to be carried out in the MethodServer, we specify the target inner class and method of interest as Strings. Any reference to the class itself will cause it and all the classes it needs to be loaded into the client VM, which is not desirable.
package wt.appfwd;

Developing Server Logic

35-19

import import import import import import import

java.applet.*; java.awt.*; java.awt.event.*; java.lang.reflect.InvocationTargetException; java.rmi.RemoteException; java.io.Serializable; java.util.Vector;

import wt.util.WTContext; import wt.method.RemoteMethodServer; import wt.method.RemoteAccess; import import import import import import import wt.fc.QueryResult; wt.fc.PersistenceHelper; wt.fc.PersistenceManager; wt.part.WTPart; wt.part.WTPartMaster; wt.query.QuerySpec; wt.query.SearchCondition;

public class AppLightFwd extends Applet { // Class name of our inner class that runs in the server private static final String SERVER_CLASS = AppLightFwd.class.getName() + "$Server"; private private private private private private private Button action; RunnerEventListener rel; Label partNames; TextField text; Label queryCount; TextField countVal; TextArea feedback;

public void init() { WTContext.init(this); action = new Button ("Get Parts"); this.add(action); rel = new RunnerEventListener(); action.addActionListener(rel); partNames = new Label( " with names like ... " ); this.add(partNames); text = new TextField("", 25); this.add(text); queryCount = new Label( "Number of parts to return" ); this.add(queryCount); countVal = new TextField( "5", 4); this.add(countVal); feedback = new TextArea("",10, 40); this.add(feedback); } public void start() { WTContext.getContext(this).start(this); super.start(); }

35-20

Windchill Customizers Guide

public void stop() { WTContext.getContext(this).stop(this); super.stop(); } public void destroy() { WTContext.getContext(this).destroy(this); super.destroy(); } // Applet event listener class RunnerEventListener implements ActionListener { public void actionPerformed (ActionEvent event) { Object o = event.getSource(); if (o == action) { String name = text.getText(); String count = countVal.getText(); if (!name.equals("")) doSomeWork(name,count); else text.setText("must enter a part name search key" ); } } } // // // // Food for thought: here we should disable appropriate GUI components and spin off a separate thread to do the actual work so we dont hang the AWT-Thread ( the GUI thread )

public void doSomeWork(String name, String count) { Vector results = null; String like = "% [ ]"+name.toUpperCase()+"% [ ]"; feedback.setText(""); try { Integer cnt = null; try { cnt = new Integer(count); } catch (Exception e) { // some parse exception, just get default count try { cnt = new Integer(5); // this will work } catch (Exception e2){} } // construct arguments for call Class [] argTypes = { String.class, Integer.TYPE }; Object [] args = { like, cnt }; // Run to server and do some work there. // Build Server inner class name as a string so we dont // load the class here. results = (Vector) RemoteMethodServer.getDefault().invoke( "doSomeWork", SERVER_CLASS, null, argTypes, args);

Developing Server Logic

35-21

// display results in text area for (int i=0;i results.size(); i++) { PartMasterInfo pmi = (PartMasterInfo)results.elementAt(i); feedback.append("> "+pmi.getName()+" # "+pmi.getNumber()+\n); } } catch (RemoteException e) { // // Put localized Exceptions // into a Dialog popup // feedback.append(e.toString()); } catch (InvocationTargetException e) { // Localize in a dialog feedback.append(e.toString()); } } // "Public" static inner class. // Yes 2 public classes in the same file, this is the // only exception public static class Server implements RemoteAccess { public static Vector doSomeWork (String name, int count) { int i=0; Vector parts = new Vector(count); WTPartMaster wtpm; try { // // Use feedback mechanism to send progress updates // to the user // and of course be sure to Localize it // QuerySpec queryspec = new QuerySpec(WTPartMaster.class); queryspec.appendSearchCondition( new SearchCondition(WTPartMaster.class, WTPartMaster.NAME, SearchCondition.LIKE, name) ); QueryResult queryresult = PersistenceHelper.manager.find(queryspec); // create a vector of PartMasterInfo object to return // to the client while (queryresult.hasMoreElements()) { wtpm = (WTPartMaster)queryresult.nextElement(); parts.addElement(new PartMasterInfo(wtpm.getName(), wtpm.getNumber())); if (++i >= count) break; }

35-22

Windchill Customizers Guide

} catch (Exception e) { // Localize parts.addElement(new PartMasterInfo(e.toString(),"-1")); e.printStackTrace(); } return parts; } } // simple support (inner) class which contains // the information we are interested in returning to the // client for display purposes public static class PartMasterInfo implements Serializable { String name; String partNumber; public PartMasterInfo( String name, String number ) { this.name = name; partNumber = number; } public String getName() { return name; } public String getNumber() { return partNumber; } } }

Developing Server Logic

35-23

Customizing service.properties
The service delegate mechanism uses Java property files to specify the delegates that are used for each service for a given set of criteria. The main property file is named service.properties and is located in /Windchill/codebase/. For further information, see the section on property files in the The Windchill Development Environment chapter on page 2-1) Instead of adding new entries to the service.properties file, or overriding existing entries in it, use a separate file. This file must have entries with the same format as those in service.properties. To use the new property file, add the files full path (relative to the system classpath) to a comma-separated list of files in the following property located in wt.properties:
wt.services.applicationcontext.WTServiceProviderFromProperties. customPropertyFiles

Consider the example of creating a new wt.identity.DisplayIdentification delegate. The DisplayIdentification service is an interface that defines methods for creating strings that identify an object for user interface display purposes. In service.properties, several entries exist for the DisplayIdentification service, as follows:1
# The wt.identity.DisplayIdentification service. # # Delegate definitions for all objects ################################################# wt.services/svc/default/wt.identity.DisplayIdentification/null/ java.lang.Object/0= wt.identity.DisplayIdentificationObjectDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.fc.Persistable/1= wt.identity.DisplayIdentificationPersistableDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.folder.Folder/2= wt.folder.DisplayIdentificationFolderDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.folder.Shortcut/2= wt.folder.DisplayIdentificationShortcutDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.doc.WTDocumentMaster/2= wt.identity.DisplayIdentificationWTDocumentMasterDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.enterprise.RevisionControlled/2= wt.identity.DisplayIdentificationRevisionControlledDelegate/

1.

Indentation in this example indicates a continuation of the preceding line, necessary for presentation in the manual. The entry for each property in a property file can be on only one line.

35-24

Windchill Customizers Guide

duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.part.WTPartMaster/2= wt.identity.DisplayIdentificationWTPartMasterDelegate/ duplicate wt.services/svc/default/wt.identity.DisplayIdentification/null/ wt.part.WTPart/3= wt.identity.DisplayIdentificationWTPartDelegate/ duplicate

Each entry maps a class or interface, such as wt.part.WTPart, to a class that implements the interface wt.identity.DisplayIdentification, such as wt.identity.DisplayIdentificationWTPartDelegate. If a customization includes a subclass of WTPart named AcmePart, and that part has different display identification needs than WTPart, a new delegate must be implemented. After the delegate class is implemented, it is used only when the correct entry has been added to a service delegate property file. To do so, perform the following steps: 1. Create a new property file named acme_part_services.properties to contain all entries for service delegates that apply to the AcmePart class. 2. Put this property file in a directory where it will not be deleted if your Windchill installation is reinstalled or upgraded, for example: <Windchill>/src/com/acme/part. Place a copy in <Windchill>/codebase/com/acme/part. 3. Add the name of the new property file to the list of files specified in the wt.properties file property named wt.services.applicationcontext.WTServiceProviderFrom Properties.customPropertyFiles, using the following procedure: Create a new declarative xconf file, for example, <Windchill>/src/com/acme/part/acme_part_services.xconf that looks like the following:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE Configuration SYSTEM "xconf.dtd"> <Configuration targetFile="codebase/wt.properties"> <!-- Ensure that the file com/acme/part/acme_part_services.properties is appended to the list of custom property files. --> <Property default="com/acme/part/acme_part_service.properties" name="wt.services.applicationcontext.WTServiceProviderFromProperties.customProperty Files"/> </Configuration>

Modify the customPropertyFiles property in <Windchill>/codebase/wt.properties and generate the acme_part_services.properties file by executing the new xconf file from a windchill shell as follows:

xconfmanager -i src/com/acme/part/acme_part_services.xconf -p

4. Restart the method server in order for the change to take effect.

Developing Server Logic

35-25

Windchill Multi-object Operations


Windchill's multi-object API infrastructure support makes it possible to perform an operation against a collection of objects without resorting to looping somewhere in the process to persist the changes, call other APIs, or dispatch events. This reduces the number of trips to the database and the number of method calls: an operation to persist 100 objects can call the database once (using a batch operation) and dispatch, again once, the events pertinent to the operation. Similarly, the event listeners can operate against the entire collection, replacing duplicative persistence (CRUD2) operations with multi-object operations that hit the database as little as one time (as opposed to n times). The multi-object API should significantly outperform the looping equivalent even when the collection has only one element, as event listeners to copy associations, etc., can benefit from the multi-object APIs. Windchill's support for multi-object APIs consists of: Windchill-specific collections Multi-object event dispatch and notification Multi-object delegation Multi-object exceptions Multi-object "CRUD" persistence manager APIs Batch ("UPDATE WHERE" and "DELETE FROM") statement capabilities Transaction context and listeners Referential integrity association validation during object delete

Windchill-specific collections utilize the Java Collections framework to provide sets, lists, and maps optimized for Windchill persistent objects. These collections seamlessly handle Persistables represented as QueryKeys, WTReferences, and fully-inflated Persistables. The collections also provide numerous APIs for doing things such as refreshing and inflating, getting sub-collections based on class, and testing membership. See the wt.fc.collections package in the Javadoc for more information. Multi-object event dispatch and notification allows any event (such as PRE_STORE) to be dispatched and notified as either single- or multi-object. The event mechanism automatically handles the case where the dispatcher and notifier (that is, the listener) are inconsistent by converting the multi-object event into single-object events and looping over the listener and, vice-versa, by converting the single-object event into a multi-object event and notifying the multi-object listener. Multi-object events will have collections-based event targets.

2. "CRUD" refers to Create (store/insert), Read (find/query/navigate/expand), Update (modify/update), and Delete (delete/remove) operations.

35-26

Windchill Customizers Guide

Multi-object delegation makes it possible to request the delegates for a collection of objects. The multi-object delegate APIs will then map the appropriate delegates to sub-collections of the collection that would use them. It is then possible to execute multi-object APIs on the delegate, passing these subcollections to the delegate's multi-object APIs. For example, when requesting the "x.y.Z" delegate for a collection of parts and documents, the result may be that delegate1 matches the parts and delegate2 the documents; delegate1's multi-object API can then be called, passing the parts sub-collection. See the Javadoc entry for wt.services.ac.DefaultServices for more information. Multi-object exceptions are thrown by multi-object APIs and listeners. These exceptions provide extended information about the nature of the problem(s) associated with some of the objects in the passed-in collection. For example, if a change identity against ten objects failed because three of the objects were assigned non-unique identities, the resultant exception will indicate the three individual failures. This is made possible by the addition of "additionalMessages" to wt.util.WTException. Multi-object CRUD persistence manager APIs interact with the database using batch operations, reducing the total number of database interactions for a CRUD operation to as little as one (more practically, as little as one per table). A "store" operation passing a collection of 100 parts can employ a single bulk insert to the database, rather than 100 individual insert operations. See the wt.fc Javadoc entry for more information. Batch ("UPDATE WHERE" and "DELETE FROM") statement capabilities produce Windchill statements that, in the database, are translated as UPDATE WHERE and DELETE FROM statements. This makes it possible, for example, to delete all of the associations for a collection of objects in one database hit without even requiring the links to be pre-queried (in practice, these operations are still subject to events, so the OIDs may be returned and, if the listeners require full persistables, inflated). See wt.fc.batch for more information. Transaction context and listeners provide fine-grained mechanisms for adding information to the nested and global transactions (in a manner similar to the MethodContext) and for being notified when a transaction is about to commit, has committed, or rolls back. See the Javadoc entries for Transaction, TransactionListener, and TransactionCommitListener in the wt.pom package. Referential integrity association validation during object delete employs a declarative mechanism to specify how associations should behave during deletion. Each role can indicate that, when the role object is being deleted, the association should be deleted or the deletion vetoed.

Developing Server Logic

35-27

35-28

Windchill Customizers Guide

36
The Enterprise Layer
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. Topic Page

Enterprise Abstractions .....................................................................................36-2 Document Abstractions ...................................................................................36-10 Part Abstractions .............................................................................................36-13 Change Abstractions........................................................................................36-21

36-1

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.

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

36-2

Windchill Customizers Guide

folders, they tend to be more administrative in nature (that is, created by administrators but referenced by end users).

Simple Business Class

The Enterprise Layer

36-3

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. 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

36-4

Windchill Customizers 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

The Enterprise Layer

36-5

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 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 Class

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).

36-6

Windchill Customizers Guide

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-inprogress activity (checkouts and checkins) for the object.

The Enterprise Layer

36-7

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

36-8

Windchill Customizers Guide

Cabinet Managed Business Cclass


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

The Enterprise Layer

36-9

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. A more complete diagram can also be viewed using Rose.

Doc Package

36-10

Windchill Customizers Guide

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 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.

The Enterprise Layer

36-11

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 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, see the section on Extending the EnumeratedType class in the System Generation chapter on page 31-36 and the Enumerated Types chapter on page 33-1.

36-12

Windchill Customizers Guide

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.

The Enterprise Layer

36-13

Attributes are on either WTPartMaster or WTPart. The WTPartMaster, as a Mastered object, represents the parts identity. As such, "number" and "name" have been placed on it. The parts 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

36-14

Windchill Customizers Guide

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 masters 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 WTPartUsageLinks aggregated Quantity can be used to indicate the amount of the component that is being consumed. The QuantityUnits values can be altered by editing its resource bundle. The WTPartUsageLink can be navigated using the PersistenceManagers navigate APIs, or even the StructServices navigateUses and navigateUsedBy APIs. Be aware that navigating the usedBy role results in the returning of all part iterations; StructServices navigateUsedBy API returns only versions. However, the StructServices APIs navigate using the IteratedUsageLink as its target; the

The Enterprise Layer

36-15

WTPartUsageLink might not be the only IteratedUsageLink in a customization. We recommend using the APIs in the following figure.

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 1st. 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 documents 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 WTPartServices getReferencesWTDocumentMasters API.

36-16

Windchill Customizers Guide

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. 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 WTPartServices APIs listed in the following figure.

Finding and Saving the WTPartConfigSpec

The ConfigSpecs aggregated by the WTPartConfigSpec have the following behavior:

The Enterprise Layer

36-17

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).
WTPartBaselineConfigSpec

When active, displays only those WTParts assigned to the specified baseline (see the wt.vc.baseline package for additional information).

36-18

Windchill Customizers Guide

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 Managers 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 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 Enterprise Layer

36-19

The Part, PartMaster, and PartIteration classes modeled in the wt.part package (see the following figure) are placeholders for future functionality.

Placeholders

36-20

Windchill Customizers 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.
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.

The Enterprise Layer

36-21

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.

36-22

Windchill Customizers Guide

Change Item Classes


The following figure shows the model for the change classes provided by Windchills change management module.

<<Abstract>> ChangeIssue 0..n FormalizedBy 0..1 <<Abstract>> ChangeRequest2 1 ResearchedBy 0..n <<Abstract>> ChangeAnalysis 1 <<Abstract>> ChangeInvestigation DetailedBy For the Windchill out of the box change process, there can be only one ChangeInvestigation per ChangeRequest. 0..n <<Abstract>> AnalysisActivity For the Windchill out of the box change process the UI does not expose this relationship <<Abstract>> ChangeProposal 0..1 AcceptedStrategy 1 0..n <<Abstract>> ChangeOrder2 Address edBy2 0..1 1 0.. n <<Abstrac t>> ChangeActivity2

IncludedIn2

Change Management Class Model

The Enterprise Layer

36-23

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 problems 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.
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.

36-24

Windchill Customizers Guide

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.

The Enterprise Layer

36-25

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.

<<Interface>> Changeable2
Product Master that is the_subject of_ the change request

W TProductInstance2
(from part)

<<Abstract>> RevisionCont rolled


(from enterprise)

WTPart
(from part)

WTDocument
(from doc)

EPMDocument
(from epm)

WTProduct
(from part)

Changeable Objects

36-26

Windchill Customizers 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.

Subject Product

Product Master

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.
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.

The Enterprise Layer

36-27

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:

This relationship identifies Changeable2 revisions which were relevant for a given Analysis Activity.

This relationship identifies Changeable2 revisions which must be changed to satisfy a Change Activity.

<<Abstract>> Object ToObjectLink


(from fc)

RelevantAnalysisData

AffectedActivityData

<<Abstract>> AnalysisActivity 0..n <<Abstract>> ChangeRequest2 0.. n 0..n 0..n

0..n 0.. n <<Interface>> 0..n Changeable2 0..n

0..n 0..n

<<Abstract>> ChangeActivity2

WTProductMaster
(from part)

RelevantRequestData2

ChangeRecord2

SubjectProduct This relationship identifies Changeable2 revsions which were relevant for a given Change Request. This relationship identifies Changeable2 revisions which were created to satisfy a Change Activity. These revisions are either entirely new, or new revisions of existing objects.

<<Abstract>> Object ToObjec tLink


(f ro m f c)

Associations Class Diagram

36-28

Windchill Customizers 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 (see the content package in the Windchill Services chapter on page 30-1), 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.

The Enterprise Layer

36-29

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 36-37.

Change issue
The following figure shows the model for change issues:

<<Abstract>> Managed
(from enterprise)

<<Interface>> ChangeIssueIfc

<<Interface>> ContentHolder
(f ro m co ntent )

<<Interface>> ChangeItem

<<Interface>> ElectronicallySignable
(from electronicIdentity)

<<Abstract>> ChangeIss ue <<Abstract>> Identificat ionObjec t


(from fc)

<<Int erface>> Identified


(from fc)

WTChangeIssue number : String name : String description : String requester : String WTChangeIssue() WTChangeIssue() checkAttributes() WTChangeIs sueIdentity number : String name : String WTChangeIssueIdentity() assignToObject() setToObject() getIdentity()

<<Interface>> Typed
(from type)

0..1 IssuePriority HIGH : IssuePriorit y = toIssuePriority ("HIGH") ME DIUM : IssuePriority = t oIssuePriorit y(" MEDIUM" ) LOW : IssuePriority = t oIss uePriorit y(" LOW ") EMERGENCY : IssuePriority = t oIssuePriorit y(" EMERGENCY" ) 0..1 Category SAFETY_ISSUE : Category = toCategory("SAFETY_ISSUE") COST_REDUCTION : Category = toCategory("COST_REDUCTION") DESIGN_ISSUE : Category = toCategory("DESIGN_ISSUE") QUALITY_IMPROVEMENT : Category = toCategory("QUALITY_IMPROVEMENT") OTHER : Category = toCategory("OTHER")

Change Issue Model

36-30

Windchill Customizers Guide

Change Request
The following figure shows the model for change requests:

<<Abstract>> Managed
(f rom e nte rp ris ) e

<<Interface>> ChangeRequestIfc

<<Interface>> ContentHolder
(from content)

<<Interface>> ChangeItem

<<Interface>> ElectronicallySignable
(f ro m el ectroni cI den ti ty)

<<Interface>> Identified
(from fc)

<<Abstract>> ChangeRequest2

<<Interface>> Typed
(from type)

WTChangeRequest2 number : String name : String description : S tring needDate : Timestamp WTChangeRequest2() WTChangeRequest2() checkA ttributes()

0..1

Category SAFETY_ISSUE : Category = toCategory("SAFETY_ISSUE") COST_REDUCTION : Category = toCategory("COST_REDUCTION") DESIGN_ISSUE : Category = toCategory("DESIGN_ISSUE") QUALITY_IMPROVEMENT : Category = toCategory("QUALITY_IMPROVEMENT") OTHER : Category = toCategory("OTHER") RequestPriority HIGH : RequestPriority = toRequestPriority("HIGH") MEDIUM : RequestPriority = toRequestPriority("MEDIUM") LOW : RequestPriority = toRequestPriority("LOW") EMERGENCY : RequestPriority = toRequestPriority("EMERGENCY") Complexity

0..1

0..1

SIMPLE : Complexity = toComplexity("SIMPLE") COMPLEX : Complexity = toComplexity("COMPLEX")

<<Abstract>> IdentificationObject
(from fc)

WTChangeRequest2Identity number : String name : String WTChangeRequest2Identity() assignToObject() setToObject () getIdent it y()

Change Request Model

The Enterprise Layer

36-31

Change Investigation
The following figure shows the model for change investigations:

<<Interface>> ChangeAnalysisIfc

<<Abstract>> Cabinet Managed


(from enterprise)

<<Interface>> Content Holder


(from content)

<<Interface>> ChangeItem

<<Interface>> ElectronicallySignable
(from electron icIdentity)

<<Interface>> ChangeInvestigationIfc

<<Abs tract>> ChangeAnalysis

<<Abstract>> ChangeInvestigation <<Interface>> Ident ified


(from fc)

<<Abstract>> Ident ificat ionObject


(from fc)

WTChangeInvestigation number : String name : String description : String needDate : Timestamp results : String WTChangeInvestigation() WTChangeInvestigation() checkAttributes()

WTChangeInvestigationIdentity number : String name : String WTChangeInvestigationIdentity() assignToObject() setToObject() getIdentity()

<<Interface>> Typed
(from type)

Change Investigation Model

36-32

Windchill Customizers Guide

Change Proposal
The following figure shows the model for change proposals:

<<Interface>> ChangeAnalysisIfc

<<Abstract>> CabinetManaged
(f rom en terprise)

<<Interface>> ContentHolder
(f rom c ontent)

<<Interface>> ChangeItem

<<Interface>> ElectronicallySignable
(f rom el ectroni cI denti ty)

<<Interface>> ChangeProposalIfc

<<Abstract>> ChangeAnalysis

<<Int erface>> Ident ified


(from fc)

<<Abstract>> ChangeProposal

<<Abstract>> IdentificationObject
(from fc)

<<Interface>> Ty ped
(from type)

WTChangeProposal number : String name : String description : String WTChangeProposal() WTChangeProposal() checkAttributes()

WTChangeProposalIdentity number : String name : String WTChangeProposalIdentity() assignToObject () setToObject() getIdentity()

Change Proposal Model

The Enterprise Layer

36-33

Analysis Activity
The following figure shows the model for analysis activities:

<<Interface>> AnalysisActivityIfc

<<Abstract>> CabinetManaged
(from enterprise)

<<Interface>> ContentHolder
(from content)

<<Interface>> ChangeItem

<<Interface>> Elect ronically Signable


(f ro m el ectroni cI dent ity )

<<Interface>> Identified
(f rom f c)

<<Abstract>> Analys isA ct ivit y

<<Abstract>> IdentificationObject
(f rom f c)

WTAnalysisActivity <<Interface>> Typed


(f rom t ype)

number : String name : String des cription : String needDate : Timest amp results : String W TAnalys isAct ivit y() W TAnalys isAct ivit y() checkAtt ributes ()

WTAnalysisActivityIdentity name : String number : St ring W TAnaly sisAct ivit yIdentity() assignToObject () s etToObject() getIdentit y()

Analysis Activity Model

36-34

Windchill Customizers Guide

Change Order
The following figure shows the model for change orders:

<<Abstract>> Managed
(f rom enterprise)

<<Interface>> ChangeOrderIfc

<<Interface>> ContentHolder
(from content)

<<Interface>> ChangeIt em

<<Interface>> ElectronicallySignable
(from electronicIdentity)

<<Int erface>> Typed


(from type)

<<Int erface>> Identified


(from fc)

<<Abstract>> ChangeOrder2

<<Abstract>> IdentificationObjec t
(f ro m f c)

WTChangeOrder2 number : String name : String description : String needDate : Timestamp WTChangeOrder2() WTChangeOrder2() checkAttributes()

WTChangeOrder2Identity number : String name : String getIdentity() WTChangeOrder2Identity() setToObject() assignToObject()

Change Order Model

The Enterprise Layer

36-35

Change Activity
The following figure shows the model for change activities:

<<Abstract>> CabinetManaged
(f ro m e nterp ri se )

<<Interface>> ChangeActivityIfc

<<Interface>> ContentHolder
(from con tent)

<<Interface>> ChangeItem

<<Interface>> ElectronicallySignable
(from electronicIdentity)

<<Interface>> Identified
(from fc)

<<Abstrac t>> ChangeActivity2

<<Interfac e>> Typed


(from type)

<<Abstract>> Ident ificationObject


(f rom f c)

W TChangeAct ivity2 number : String name : String description : String needDate : Timestamp WTChangeActivity2() checkAttributes() WTChangeActivity2()

WTChangeActivity2Identity number : St ring name : String W TChangeAct ivity2Ident it y() ass ignToObject() setToObject() getIdentit y()

Change Activity Model

36-36

Windchill Customizers Guide

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.
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.

The Enterprise Layer

36-37

36-38

Windchill Customizers Guide

37
Persistence Management
This chapter describes persistence management. Topic Page

Overview ...........................................................................................................37-2 Persistence Manager..........................................................................................37-2 Query .................................................................................................................37-4 Transaction ........................................................................................................37-8 Paging................................................................................................................37-9 Referential Integrity ..........................................................................................37-9 Multi-object CRUD Persistence Manager APIs..............................................37-12 Batch (update where/delete from) Statement Capabilities ..............................37-13 Transaction Context and Listeners ..................................................................37-14 Referential Integrity Association Validation During Object Delete ...............37-15 Persistence Datastore Sequence Customization ..............................................37-16

37-1

Overview
The PersistenceManager is an interface for database access. To use the PersistenceManager, a class must implement the wt.fc.Persistable interface. By implementing Persistable, the classes have the necessary code generated to read and write data to and from the database and display its identity. Applications should access the PersistenceManager through a convenience class named PersistenceHelper. The PersistenceManager operations support events associated with the operation. Application code can listen for these events and perform some related action in the same transaction. Operations that fetch objects from the database perform access control checks on each object returned in the result set. These query operations use wt.query.QuerySpec to define the classes of objects to select from the database. QuerySpec uses the wt.query.SearchCondition class to define search criteria. That is, in the SELECT statement that is generated, the QuerySpec defines which columns to select and which tables to select from, and SearchCondition defines the WHERE clause. The fetch operations return wt.fc.QueryResult. The operations that delete, modify, and store a Persistable object all perform access control checks before continuing with the operation. These operations return the Persistable object with updated persistence information. Support for large result sets and long running queries is provided via the paging mechanism. Much like a web search, paging allows the user to execute a query and view results in pages via fetch requests. Result pages are defined in terms of an offset and range. A paging session corresponding to a specify query is available for paging fetch requests for a limited amount of time. This is due to the limited system resources that must be used to implement the paging session. Therefore, the user must be prepared to handle exceptions caused by a paging session timeout.

Persistence Manager
The PersistenceManager is the base business manager that other managers use to handle persistence. For programming convenience, a helper class has been implemented to facilitate client (and server) usage of the PersistenceManager methods. The name of the class is PersistenceHelper. The wt.fc package Javadoc

37-2

Windchill Customizers Guide

contains documentation on the various publicly supported PersistenceManager methods.

Persistence Manager

Persistence Management

37-3

Query
The wt.query package contains the following classes for creating queries which retrieve objects from the database. When used with the find operation, QuerySpec can perform both single and multiple class queries. The following sections discuss how to perform single class queries using QuerySpec, SearchCondition, and QueryResult. The last section describes how all three are used in multiple class queries. The information in this section is sufficient for most database queries. If you require more advanced SQL queries, see the Advanced Query Capabilities chapter on page 36-1.

QuerySpec
QuerySpec is used as an argument on the find and navigate operations to define the classes of objects to retrieve. The SearchCondition object (described later in this section) defines the criteria on those classes.

QuerySpec in a Find Operation


You can specify a single class on the constructor for the find operation as follows:
QuerySpec(Class targetClass);

The following example retrieves all Parts from the database.


QuerySpec qs = new QuerySpec(wt.part.WTPart.class); QueryResult qr = PersistenceHelper.manager.find(qs);

Since this is usually not the desired result, search conditions are used to limit the number of objects returned. For example, to add a search condition to the QuerySpec, use the following form:
QuerySpec.appendWhere(WhereExpression where, int[] classIndices)

The classIndices parameter is used to apply the search condition to the appropriate classes in the QuerySpec. The classes referenced from the SearchCondition must match the QuerySpec classes at the specified index.

QuerySpec in a Navigate Operation


For the navigate operation, you must specify both the targetClass and linkClass on the constructor as follows:
QuerySpec(Class targetClass, Class linkClass);

The targetClass is the class of the "other side role" in the navigate. SearchConditions can be appended based on either the target or the link.

37-4

Windchill Customizers Guide

Example:
QuerySpec qs = new QuerySpec( wt.part.WTPartMaster.class, wt.part.WTPartUsageLink.class); CompositeWhereExpression where = new CompositeWhereExpression(LogicalOperator.AND); where.append(new SearchCondition(wt.part.WTPartMaster.class, wt.part.WTPartMaster.NAME,SearchCondition.EQUAL,"XYZ")); where.append(new SearchCondition(wt.part.WTPartUsageLink.class, WTAttributeNameIfc.CREATE_STAMP_NAME,true, new AttributeRange(beginTime,endTime))); qs.appendWhere(where, new int[] {0, 1});

SearchCondition
The number of objects retrieved by a QuerySpec is limited by criteria defined with SearchCondition. The most common format of a SearchCondition constructor is as follows: SearchCondition(Class targetClass, String attributeName, String operation, Object value) The targetClass can be a concrete class, abstract class, or interface. When appended to a QuerySpec, the SearchCondition is responsible for creating a WHERE clause on the query. The attributeName can be any attribute of the target class that maps to a column in the table being queried. In the case of a target class that has AutoNavigate associations to other classes, any attributes that map to columns in the base class or associated class can be used. Not all attribute types can be used in a search condition, for example, attributes stored in BLOB columns. To verify which attributes can be used, inspect the InfoReport for the target class, looking at the attributes PropertyDescriptor to ensure that its QUERY_NAME property is not null.

QueryResult
The QueryResult object is the standard container returned from all Persistence queries and navigations. QueryResult implements the standard java.util.Enumeration plus the added abilities to determine the number of objects in the QueryResult and reset the QueryResult to process it again. Example: (using the QuerySpec created in the previous section):
QueryResult qr = PersistenceHelper.manager.navigate(thePart, wt.part.WTPartUsageLink.USES_ROLE,qs,false);

Persistence Management

37-5

The QueryResult in this example will contain WTPartUsageLinks with both the WTPartMaster and WTPart roles populated because onlyOtherSide is false. If onlyOtherSide had been true, QueryResult would contain WTPartMaster objects. The SearchConditions narrow the search to only those WTPartMasters with the name of "XYZ" who had usage links created between a specified beginTime and endTime.

Multiple Class Queries


QuerySpec also supports multiple class queries when used with the find operation. Any number of classes can be added to the QuerySpec and objects of those classes will be returned from the database. The following two methods can be used for adding classes:
addClassList(Class targetClass, boolean isSelectable) appendClassList(Class targetClass, boolean isSelectable)

The difference between the two is that appendClassList() always adds a new class to the QuerySpec. If the method addClassList() is used and the specified class is already in the QuerySpec, the index of the existing class is returned. The index returned when adding (or appending) a class is used when appending a search condition for that class. When using multiple class queries, all of the classes usually should be joined to avoid redundant results. Use the following constructor for SearchCondition to join two classes:
SearchCondition(Class targetClass, String targetAttribute, Class linkClass, String linkAttribute)

When appending this type of SearchCondition to a QuerySpec, both class indexes must specify classes in the QuerySpec. When multiple classes are in the QuerySpec, the elements in the QueryResult will no longer be Persistable objects. If the full object is selected (via the isSelectable argument, then the QueryResult elements will be an array of wt.fc.Persistable objects (that is, Persistable[]). The array is needed because more than one class can be returned. The exact type of the element will be Persistable[]. If any attributes of the class are selected, then the QueryResult elements will be an array of java.lang.Object objects (that is Object[]). When adding (or appending) a class, the boolean parameter isSelectable specifies whether objects of that class will be returned in the QueryResult. The QueryResult Persistable array will have the same order as the classes in the QuerySpec. However, classes that are not Selectable will not appear in the QueryResult. For example, if the QuerySpec contains the classes W, X, Y, and Z with X and Z selectable, the QueryResult Persistable array will contain X and Z. All of the classes in a multiple class query are subject to Access Control regardless of whether objects of that class are returned in the QueryResult.

37-6

Windchill Customizers Guide

Example:
QuerySpec qs = new QuerySpec(); // Append the classes int partIndex = qs.appendClassList(wt.part.WTPart.class, true); int viewIndex = qs.appendClassList(wt.vc.views.View.class, true); // Join the WTPart class to the View class via the View object ID and // the WTPart Foreign Key SearchCondition sc = new SearchCondition( wt.part.WTPart.class, wt.part.WTPart.VIEW + "." + wt.vc.views.ViewReference.KEY + "." + wt.fc.ObjectIdentifier.ID, wt.vc.views.View.class, WTAttributeNameIfc.ID_NAME); qs.appendWhere(sc, new int[] { partIndex, viewIndex }); QueryResult result = PersistenceHelper.manager.find(qs); while(result.hasMoreElements()) { Persistable[] persistableArray = (Persistable[]) result.nextElement(); wt.part.WTPart part = (wt.part.WTPart) persistableArray[partIndex]; wt.vc.views.View view = (wt.vc.views.View) persistableArray[viewIndex]; }

Persistence Management

37-7

Transaction
Transaction objects provide a mechanism that supports the standard concept of a database transaction. It has the following methods:
start

After a transaction is started, all subsequent database inserts, deletes, and updates are part of that transaction.
commit

Commits the pending database operations to the database.


rollback

Discards the pending database operations. The pattern for a method that can throw WTException is as follows:
Transaction trx=new Transaction(); try { trx.start(); <your code here> trx.commit(); trx=null; } finally { if (trx!=null) trx.rollback(); }

If you create a transaction in which to perform some activities but never reach your commit statement, be sure you mark the current transaction for rollback. Someone else may accidentally ground out an exception and later try to commit your partially completed work. The rollback call in a finally block, marks any enclosing transaction so partial results cannot be accidentally committed later. If code following notices a problem and calls rollback, the database is safe but, if your code is the deepest transaction, it is your responsibility to call rollback if you do not get to your commit call. Because you may not know for certain if your code is the deepest transaction at the time an exception is thrown, you should always do it.

37-8

Windchill Customizers Guide

Paging
The basic idea behind paging is the concept of a "snapshot" query. When a paging session is opened, a "snapshot" is taken of the results. These results can then be fetched in pages over multiple calls. When all desired fetches are complete, the paging session should be closed. This cleans up any data associated with the paging session to free system resources. These system resources are significant so a timeout property exists. If the timeout limit is reached, then the paging session is automatically closed. Any further fetch requests would result in an exception. Another configurable property is the paging limit (there is a system wide value and this value can also be overridden when opening a paging session). Because of the system resource required, a limit can be set such that if the result set size of the "snapshot" query is less than this value, then all of the results are returned immediately and no paging session is established. Note also that the results of the initial "snapshot" query are access controlled. Only data that the user can access (i.e. data that the user has read permission for) will be stored for subsequent page requests. In addition, the total count of the size of the result set will also be returned when the paging session is opened. This "snapshot" behavior is important to understand in terms of how the underlying query results can change. Consider a paging session that is established and a total paging size of 50 is available for fetch requests. The first 25 objects are returned and displayed to the user. The set of data can be modified by other user operations. For example, another user could delete an object in the second set of 25 objects. Now when a fetch request is made for objects 25 through 50, the object that was deleted will not be available. The paging results will still contain 25 elements. However, for the object that was deleted, a null value would be returned in the paging results. Another situation can occur for updates. Consider a paging session that is established for a query that returns data where a numeric attribute of an object is less than some value. Between the time that the paging session was opened and a subsequent fetch request, an object from the results could have been modified and the numeric attribute changed such that it no longer meets the original querys criteria. Yet, it would still be part of the paging session results because it did meet the criteria at the time that the paging session was established. This is another reason for the timeout limit on paging sessions. The definition of the "snapshot" query uses the same query constructs as normal queries. Both QuerySpec and CompoundQuerySpec objects can be specified. The classes or column expressions that are selected will be returned in the fetch requests. Criteria and sorting will be applied when executing the "snapshot" query. The sorting (if any is specified) will be maintained on fetch requests. When specifying a sort on a QuerySpec that will be paged, each ColumnExpression must have a unique column alias. This should be specified using the ColumnExpression.setColumnAlias() method. The actual fetch requests return a PagingQueryResult, which is a sub-class of QueryResult. The PagingQueryResult has additional paging attributes such as the paging session ID (used for subsequent fetch requests) and the total paging size.

Persistence Management

37-9

The Paging APIs are specified as static methods in the wt.fc.PagingSessionHelper class (see the wt.fc.PagingSessionHelper class entry in your installed Windchill Javadoc for more information). There are several types of APIs that are available for opening a paging session, fetching from a paging session, and closing a paging session. The following example shows how these methods can be used to perform an interactive paging session for an arbitrary query passed to the method as an argument. The method consists of a while loop that prompts the user for an offset and range for a fetch request (or to end the paging session). The first time through the loop the paging results are null so the paging session is opened. The paging session ID and total paging count values are then stored in local variables. The paging session ID will be used to execute fetch requests and eventually close the paging session. If the paging session has already been opened, then a fetch is made using the offset and range. The paging results are then displayed along with the offset, range, and total count. The last piece of code in the loop checks the paging session ID to ensure that a paging session has been established. If the query returned no results or the paging limit was not reached, then no paging session would exist. This entire loop is enclosed in a try/finally block to ensure that the paging session is always closed (if one has been established).
public void executePaging(QuerySpec a_querySpec) throws WTException, WTPropertyVetoException { long pagingSessionId = 0; try { PagingQueryResult pagingResults = null; int offset = 0; int range = 0; int totalCount = 0; boolean done = false; while(true) { // Prompt user for offset and range offset = ..; range = ..; done = ..; if(done) { break; } if(pagingResults == null) { // Open Paging Session pagingResults = PagingSessionHelper.openPagingSession( offset, range, a_querySpec); pagingSessionId = pagingResults.getSessionId(); totalCount = pagingResults.getTotalSize(); else { pagingResults = PagingSessionHelper.fetchPagingSession(

37-10

Windchill Customizers Guide

offset, range, pagingSessionId); } // Display QueryResult items System.out.println("Displaying " + offset + " to " + (offset + range) + " of " + totalCount); if(pagingSessionId <= 0) { // No paging session was established break; } } } finally { if(pagingSessionId > 0) { PagingSessionHelper.closePagingSession(pagingSessionId); } } }

Persistence Management

37-11

Referential Integrity
The persistence layer supports associations between two Persistable objects via classes extending wt.fc.BinaryLink. For these associations, the persistence layer also supports enforcing referential integrity as specified in the associations modeled properties. The Rose Information Modeler supports Association Specification model properties, "Owner" and "Cascade", on the "Windchill A" and "Windchill B" tabs for the corresponding role . Both properties will be boolean options. The persistence layer will uses these properties when an object is removed. If the "Owner" property is true, then the persistence layer will remove the link object associated with the removed object. If the "Owner" property is false, then the persistence layer does not implicitly remove the link object when the object is removed, but it will verify that this association does not exist before the transaction is allowed to commit. The "Cascade" property is used only when an association link object is removed. If the "Cascade" property is true, then the persistence layer will cascade the remove operation to the associated role object. This occurs when the link is removed via a direct call or via the "Owner" processing. The default value for all roles is "Owner=true" and "Cascade=false". The role A and role B settings are independent of each other, and any combination is valid. When extending an association, the sub-class will inherit these role attributes from the parent, but the values can still be explicitly overridden in the sub-class.

Multi-object CRUD Persistence Manager APIs


The standard persistence manager persistence APIs now have multi-object variants taking Windchill collections. These include store/insert, modify/update, delete/remove, and prepareForModification as well as enhanced support for multiobject navigation (query is already multi-object).The multi-object APIs will dispatch multi-object events and will interact with the database using techniques that will result in a significant performance boost over a simplistic looping algorithm.

37-12

Windchill Customizers Guide

Batch (update where/delete from) Statement Capabilities


It is now possible to build the equivalent of the SQL statements update where and delete from. Their use will generally be limited to cases where the API does not have and does not need the objects brought back to the VM (from the database) and no events eed dispatching. However, these APIs are extremely efficient and when used properly represent the most efficient mechanism to update and delete rows in the database.

When to use
The batch update/delete operations represent the most performant option for affecting change in the database because they minimize both the data needed to perform the operation and the data needed to affect the change neither requires that the objects to be changed first be retrieved from the database and only the columns to change need to be sent (as opposed to full persistables) in the case of an update.These APIs should be considered when: There is no need to bring the object back into the VM, either to perform tests or to dispatch events None of the objects involved in the batch operation exist in memory prior to the batch operation

In most cases, it is sufficient to say that their use should be limited only to cases where there is never a need to bring the object or its reference back to memory and should never be used on objects already in memory. The above guidelines are based on the fact that the performance benefits drop when the data is actually needed and by the fact that the changes won't be reflected in any of the in-memory objects. However, a gray area for batch update is in cases where the references are needed for event dispatch, the dispatched event indicates that the change has occurred, and the listeners need not inflate.

Persistence Management

37-13

Transaction Context and Listeners


New transaction capabilities allow for transaction contexts and listeners. A transaction context is similar to the method context except that it is associated to either a local or global transaction. The transaction context, like the method context, allows for the sharing of data outside of that which is possible simply as arguments to APIs. A transaction listener, also associated to a local or global transaction, provides hooks that get executed when the transaction commits, rolls back, or is about to commit. These listeners provide a means to defer validations (until the database is known to have no additional changes associated with the transaction), defer work until immediately before the transaction would commit, as well as do additional processing once it is known that the transaction has committed or rolled back. Maintaining cache integrity is an example of when to use a TransactionListener.
// class for some Standard Service Manager public class StandardSomeServiceManager extends StandardManager { MyCache myCache; // member class for service events class MyListener extends ServiceEventListenerAdapter { public void notifyVetoableEvent (Event e) { KeyedEvent keyedEvent = (KeyedEvent) e; Object targetObject = keyedEvent.getEventTarget (); // // check out event and object to see if we really care what happens // // Set up with Transaction for commit if (keyedEvent.getEventType ().equals (PersistenceManagerEvent.POST_DELETE)) { Transaction.addTransactionListener(new Remover(targetObject)); } } } // member class for transaction events class Remover implements TransactionListener { Object obj; public Remover (Object obj) { this.obj = obj; } public notifyCommit() { // get my cache and remove object getMyCache().remove(this.obj); } public notifyRollback() { // ignore } } public void performStartupProcess () { myListener = new MyListener() // subclass of ServiceEventListenerAdapter

37-14

Windchill Customizers Guide

// Set up to receive service events getManagerService().addEventListener(myListener, PersistenceManagerEvent.generateEventKey (PersistenceManagerEvent.POST_DELETE)) } public static MyCache getMyCache() { if (myCache == null) { try { return new MyCache(); } catch (RemoteExcepiton re) { // do something } } return myCache; } } // class which implements the actual cache public class MyCache extends CacheManager { public MyCache() { super(); } }

Referential Integrity Association Validation During Object Delete


The referential integrity feature promises to cleanup delete listeners that exist simply to remove associations or to validate that objects should not be allowed to be deleted due to the existence of associations. The replacement of these listeners by referential integrity will improve performance because the centralized code can more efficiently query for and delete associations than the individual listeners can.

Persistence Management

37-15

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 the Windchill Information Modeler (i.e. Rose) has been successfully installed and configured. Assume you have access to the Windchill datastore directory, <WindchillHome>/db, and access rights to execute DDL scripts in the target datastore.

Intended Outcome
The end result of this solution is the creation of a datastore sequence.

Solution
Model a sequence class using Information Modeler.

Solution Elements

Element

Type

Description

<MySequence>

Java class

The class for representing a datastore sequence in Windchill.

37-16

Windchill Customizers Guide

Procedure - Creating a Datastore Sequence


1. Create a class <MySequence> in <MyPackage> implementing the wt.fc.DatastoreSequence interface.

2. Specify the sequence properties. Open the Class Specification dialog for the class, select the "Windchill" tab, and choose the "Sequence" value from the "Set" drop down list. Specify the initial seed and increment values if the defaults are not sufficient.

Persistence Management

37-17

3. Generate the model elements. 4. Execute the sequence DDL. From a Windchill shell, execute:
<WindchillHome>/db/execute_sql_script.bat <MyPackage>/create_<MySequence>_sequence.sql

5. Compile the <MySequence>.java class in <MyPackage>.

Customization Points Procedure - Obtaining the Next Value in a Sequence


In the primary procedure above, a sequence class was created. To obtain the next value in this sequence, use the PersistenceManager.getNextSequence(Class).

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.

Packaged Samples
None.

Related Package/Class Javadoc


Foundation module wt.fc

37-18

Windchill Customizers Guide

38
Advanced Query Capabilities
This chapter 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. Topic Page

QuerySpec .........................................................................................................38-2 SearchCondition ................................................................................................38-9

38-1

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. 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 class attribute that can be used in a SQL statement. Introspection information is used to determine the associated table and column.

38-2

Windchill Customizers Guide

Column Expression

Description

Required From Indices

SQLFunction

This class represents a SQL function within a SQL statement.

0 or more. This number is based on the sum of the required from indices of all arguments. 0 0

ConstantExpression KeywordExpression

This class represents a constant in a SQL statement. This class represents an expression that evaluates to a SQL keyword that can be used in a SQL statement. 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.

TableColumn

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. 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. When queries containing only columns are used as sub-selects as part of an ObjectReference query (described later in this section), then the Access Control columns are not added. 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.

Advanced Query Capabilities

38-3

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. 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". This class represents a subselect that can be used in a SQL statement. The subselect is specified via a StatementSpec attribute. 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.

ClassViewExpression

SubSelectExpression

ExternalTableExpression

The following example builds a query against a non-modeled table named dual:
QuerySpec qs = new QuerySpec(); 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)

38-4

Windchill Customizers Guide

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. This class represents an EXISTS expression in a WHERE clause. A StatementSpec instance is used for the subselect. This class represents a number of WHERE expressions connected using a logical operator (i.e. AND/OR). 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.

ExistsExpression

CompositeWhereExpression

NegatedExpression

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. 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);

Advanced Query Capabilities

38-5

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, 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

38-6

Windchill Customizers Guide

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);

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);

Advanced Query Capabilities

38-7

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)

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.

38-8

Windchill Customizers Guide

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. This class represents a SQL function within a SQL statement. This class represents a subselect that can be used in a SQL statement. The subselect is specified via a StatementSpec attribute. This class represents a constant in a SQL statement. This class represents an expression that evaluates to a SQL keyword that can be used in a SQL statement. This class represents a range in a SQL WHERE clause. This class represents a date constant in a SQL statement. This subclass of ConstantExpression is necessary to provide the special handling for date values. This class represents an array of constants in a SQL IN clause. 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.

SQLFunction SubSelectExpression

ConstantExpression KeywordExpression

RangeExpression DateExpression

ArrayExpression TableColumn

Advanced Query Capabilities

38-9

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. Note: The current version of the Oracle JDBC driver contains a bug that prohibits using parentheses around component statements in a nested compound query. The setting of the wt.pom.allowCompoundParentheses property in the db.properties file controls whether parentheses are used. By default, this setting is false to avoid the Oracle JDBC driver bug. This workaround could lead to unexpected results if the set operator precedence is significant. 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 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

38-10

Windchill Customizers Guide

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.

Advanced Query Capabilities

38-11

CompoundQuerySpec compound = new CompoundQuerySpec(); 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, nonaccess controlled query() method should be used.

38-12

Windchill Customizers Guide

PersistenceServerHelper.manager.query(statement);

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 QuerySpecs 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,

Advanced Query Capabilities

38-13

wt.part.WTPart.NAME); 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 users 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);

38-14

Windchill Customizers Guide

query.appendSelect(new ClassAttribute(wt.folder.SubFolder.class, wt.folder.SubFolder.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);

Advanced Query Capabilities

38-15

38-16

Windchill Customizers Guide

39
Internationalization and Localization

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. Topic Page

Background .......................................................................................................39-2 The Windchill Approach ...................................................................................39-3 Localizing Text Visible to the User ..................................................................39-5 Resource Info (.rbInfo) Files .............................................................................39-8

39-1

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 userYou 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 localeConsider the use of decimals within numbers, currency symbols, date formats, address styles, and system of measurement. How should data be formattedConsider 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 colorWhen 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.

39-2

Windchill Customizers 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 applications 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 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.

Internationalization and Localization

39-3

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 localedependent way.

39-4

Windchill Customizers 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 userspecified 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;

Internationalization and Localization

39-5

public void addNotify() { //Localize 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 { 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"},

39-6

Windchill Customizers Guide

{"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..."}, {"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.

Internationalization and Localization

39-7

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.
Resource Type Source File Run-Time File

Message Text

*RB.rbInfo *Resource.rbInfo

*RB.class *Resource.class

39-8

Windchill Customizers Guide

Modeled Metadata (Display Names) EnumeratedType Options Definition

<package>ModelRB.rbInfo <EnumType>RB.rbInfo

<package>ModelRB.RB.ser <EnumType>RB.RB.ser

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 <key>.constant

The localizable text that will be displayed. A string that will be used to generate a constant field into the runtime resource bundle, which can be used by code that does resource lookups. A comment describing the entry. A comment for each substitution argument of the value string. Indicates whether the resource entry is customizable. Indicates (to the developer) whether the resource entry is deprecated. Reserved for future use. Reserved for future use.

Required Message text: Optional Metadata: Unused EnumeratedType: Unused Optional Optional Optional Optional Unused Unused

<key>.comment <key>.argComment<n> <key>.customizable <key>.deprecated <key>.abbreviatedDisplay <key>.fullDisplay

Internationalization and Localization

39-9

Key

Description

Usage

<key>.shortDescription <key>.longDescription <key>.order

Reserved for future use. Reserved for future use. Explicit sort order for the value, unused for alpha ordering.

Unused Unused Message text: Unused Metadata: Unused EnumeratedType: Optional

<key>.defaultValue

Specifies the value is the default value for the Enumerated Type.

Message text: Unused Metadata: Unused EnumeratedType: Optional

<key>.selectable

Specifies if the value should be allowed to be selected.

Message text: Unused Metadata: Unused 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.
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.

39-10

Windchill Customizers Guide

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. See How Rose UML Maps to Localizable Resource Info Files in the System Generation chapter on page 31-47.

EnumeratedType Options Definition


Resource Info files for enumerated types are described in the Enumerated Types chapter on page 33-1.

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. For more information, see the Command Line Utilities section the System Generation chapter on page 31-55.

Internationalization and Localization

39-11

39-12

Windchill Customizers Guide

40
Customizing Archive, Purge, and Restore

Archive and Purge allow you to remove data from your Windchill system while preserving a reasonable working set of data for end users. You have the ability to couple archive functionality with purge so that while data is removed from the production system, an archive of that data still exists to be retrieved as required. Note: In order to access the archive functionality, you must install Windchill Archive. Topic Page

Archiving Related Classes.................................................................................40-2 Enabling Archive/Purge/Restore for Custom Classes.......................................40-4 Customizing Archive Upgrade..........................................................................40-8

40-1

Archiving Related Classes


Note: All objects that need to be archived must implement the wt.fc.archive.Archiveable interface. When creating an archive, Windchill gives you the ability to specify which versions and iterations and which dependencies should be included with the item selected for archival. The choices for each of these two options are as follows: CAD Dependencies: Required dependencies or All dependencies. This choice pertains to CAD dependencies the same way it does elsewhere in the product. Version and Iterations: Latest iteration of latest version or Latest iteration of each version: This logic (in some cases) recursively collects objects based on a list of link objects that connect archive-supported objects in Windchill.

This enables Windchill to recreate the object with enough contextual information to use it meaningfully after restore, even if all such information has been deleted from active use from the Windchill instance at the point of restore. Out of the box, Windchill takes a "safety first" approach and collects all the supported contextual objects (barring exceptions) for the Versions and Iterations category of related items. The list of supported objects is as follows:
wt.epm.structure.EPMMemberLink wt.epm.structure.EPMVariantLink wt.epm.structure.EPMReferenceLink wt.epm.build.EPMBuildHistory wt.epm.structure.EPMContainedIn wt.part.WTPartUsageLink wt.part.WTPartReferenceLink wt.part.WTPartDescribeLink wt.epm.build.EPMBuildLinksRule

For your business objectives, a subset of the above list may make more sense and/or you may need to add customized links to the list. The following information describes the way related objects are collected by Windchill; this needs to be understood to customize this behavior: Windchill uses wt.dataops.objectcol.RelationshipMapDef objects and wt.dataops.objectcol.RelationshipMap objects to control the collection of related objects. Windchill loads one wt.dataops.objectcol.RelationshipMapDef object, that holds the traversal map for related objects based on <Windchill>/loadFiles/content/RelationshipMap.xml file, as part of the base data loading. Windchill loads four wt.dataops.objectcol.RelationshipMap objects that use the above loaded wt.dataops.objectcol.RelationshipMapDef object and

40-2

Windchill Customizers Guide

correspond to each of the four options offered by Windchill (given the combination of two options with two choices each as described above), as part of the base data loading. To change/extend the related object collection behavior, you need to delete and recreate the five objects above. This can only be done before any one of them has been used in active Windchill use, that is, by creating a archive. Follow the steps below for this customization: 1. Delete the five objects referred to above, making sure they have not been used earlier (and thus ensuring referential integrity is not violated). For example, use the PersistenceManager API to delete the objects (see the Persistence Management chapter on page 37-1). 2. Make a copy of <Windchill>/loadFiles/content/RelationshipMap.xml and suitably alter the related object definition in it. The DTD is located in <Windchill>/codebase/registry/objectcol/dtds/Criterion-def.dtd. 3. Make a copy of <Windchill>/loadFiles/BaseCriterionDefs.xml, removing all sections except for those that relate to the creation of RelationshipMapDef and RelationshipMap objects. Change the reference of the XML to refer to the new, altered copy of RelationshipMap.xml from the previous step. 4. Reload the objects deleted in step 1 by loading the new BaseCriterionDefs.xml copy from the step above, using the LoadFromFile mechanism. For example,
windchill wt.load.LoadFromFile -d <Windchill>/loadFile/BaseCriterionDefs.xml

For more information on data loading, see: Windchill Installation and Configuration Guide - Windchill Windchill Data Loading Reference and Best Practices Guide

Customizing Archive, Purge, and Restore

40-3

Enabling Archive/Purge/Restore for Custom Classes


Introduction
This section describes the procedure for enabling the archive, purge, and restore of custom classes. Specifically it discusses the creation of Import Export (IX) handlers for those classes and steps for configuring the IX and Archive/Purge/Restore Framework. The following steps need to be performed in order to achieve this. Write IX handlers for all custom classes, including relationship classes. Make appropriate entries for the new classes in coreobjects.dtd , coreX05.xml. Make appropriate entries in RelationshipMap.xml

Note: All objects that need to be archived must implement the wt.fc.archive.Archiveable interface.

Writing Handlers
You will need to create IX handlers for all your custom classes including your link classes. Refer to the How to Write Exp/Imp Handlers section in the Import Export Framework chapter on page 41-17. In addition you can refer to the implementation of handlers for WTPart and WTDocument. Alternatively you can derive your handlers from existing handlers and reuse the code. Apart from importing normal attributes, you need to export and import certain additional attributes. To do this use the wt.ixb.archive.ArchiveHndHelper class. This class provides helper methods that IX handlers need to support Archive and Restore functionality. In your IX handler you should check to see whether archive/restore is being done. In this case you must also perform certain operations on the archive-specific attribute. To export/import Archive-related attributes use the ExpImpForFlexibleVersioningAttr, ExpImpForArchiveAttr, ExpImpForMarkUpAttr classes. You can refer to the IX Handler for WTPart for details. The following examples show sample code that is added to various methods to enable archive/restore. protected void exportAttributes (Object object, IxbDocument fileXML, Exporter exporter)

if (ArchiveHelper.isArchiveRestoreContext(exporter)) { IxbHndHelper.exportAttribute(ExpImpForFlexibleVersioningAttr.class, ob, fileXML, exporter);

40-4

Windchill Customizers Guide

IxbHndHelper.exportAttribute(ExpImpForArchiveAttr.class, ob, fileXML, exporter); IxbHndHelper.exportAttribute(ExpImpForMarkUpAttr.class, ob, fileXML, exporter); }

The above code will ensure that Archive and Flexible Versioning attribute information is also stored in the archive. public void checkConflicts (IxbElement fileXML, Importer importer)

If you are implementing this method you should also include the code below.
if (ArchiveHelper.isArchiveRestoreContext(importer)) { IxbHndHelper.checkConflictForAttribute(ExpImpForFlexibleVersioningAttr.class, existingOb, fileXML, importer); IxbHndHelper.checkConflictForAttribute(ExpImpForArchiveAttr.class, existingOb, fileXML, importer); }

public Object importObjectAttributes (Object ob, IxbElement fileXML, Importer importer)

if (ArchiveHelper.isArchiveRestoreContext(importer)) { ob = IxbHndHelper.importAttribute(ExpImpForFlexibleVersioningAttr.class, ob, fileXML, importer); ob = IxbHndHelper.importAttribute(ExpImpForArchiveAttr.class, ob, fileXML, importer); } public Object importObjectAttributesAfterStore(Object object,IxbElement fileXML, Importer importer) if (ArchiveHelper.isArchiveRestoreContext(importer)) { ob = (WTPart)IxbHndHelper.importAttribute(ExpImpForMarkUpAttr.class, ob, fileXML, importer); }

If your handler classes do not extend from existing handler and your classes are not derived from an out-of-the-box class you will also need to override the storeObject method to ensure that your objects are created with the same OIDs they had before archive/purge.

public Object storeObject( Object object, IxbElement fileXML, Importer importer )

For example,
ObjectIdentifier oid = ((Persistable) object).getPersistInfo().getObjectIdentifier(); ArchiveHndHelper.addOidForReuse(Transaction.getCurrentTransaction(), oid); PersistenceHelper.manager.save(object) ;

Make entries in coreobjects.dtd , coreX05.xml


Refer to the Import Export Framework chapter on page 41-1.

Customizing Archive, Purge, and Restore

40-5

Make entries in RelationshipMap.xml


Make entries for your link class in <Windchill>/ loadFiles/content/Relationshipmap.xml . You need to create entries in Relationshipmap.xml only if you have custom links between your classes. The link class is identified by the link tag and the classname is the fully qualified class name of your link class. The field attribute of the derived tag allows the collection service to fetch the dependent object. The seeds are the classes to be collected. These are specified using the seed tag. You can ensure that descendants of your class are selected by setting the allow-subtypes attribute to true. The output-type element is the other end of the relationship. The collection service will collect all objects of output-type that are related to the seed. You can set the allow-subtypes attribute to true to ensure that descendants are also considered for collection.

<!-- CustomOtoOLink --> <related> <by-relationship collect-related-by='true' collect-other-end='true' other-end-dependant='true'> <output-types> <output-type classname='auto.Custom.CustomDoc' allow-subtypes='true'/> </output-types> <relationship> <seeds> <seed classname="auto.Custom.CustomPart" allow-subtypes="true"/> </seeds> <link classname="auto.Custom.CustomOtoOLink"/> <role> <name> <derived> <derive classname="auto.Custom.CustomOtoOLink" field="CUSTOM_DOC_ROLE" /> </derived> </name> </role> <recurse> <input type="string" name="recurse-part-reference" required="false" default-value="false"> <match> <pattern resource="true value">true</pattern> <pattern resource="false value">false</pattern> </match> </input> </recurse> </relationship> </by-relationship> </related>

Recreate the schema for the Dataops module and load the XML file into the database using the LoadFromFile mechanism. For example,
windchill wt.load.LoadFromFile

40-6

Windchill Customizers Guide

-d <Windchill>/loadFile/BaseCriterionDefs.xml

Limitations
For archive information to be stored objects need to implement at least the Iterated and Ownable interfaces. For storing Archive attribute information your classes need to be Iterated and Ownable. For storing Flexible attribute information your classes need to be Iterated and Federatable. If your classes are not Iterated and Ownable you will not be able to store Archive information, however you can import/export your custom attributes, and restore the OIDs as this only requires your classes to be Persistable.

Customizing Archive, Purge, and Restore

40-7

Customizing Archive Upgrade


Since Customized objects can be exported and archived and also undergo schema changes, it is necessary to provide support for upgrade of jars that contain these objects. Archive upgrade also applies to customized objects. This needs to be done if all of the following conditions are true. Customers have customized (modeled) classes that are Archiveable. Such objects have been Archived

The dtd of objects have changed in the current version. The kinds of changes that may occur are listed in the Schema Changes section. All the facilities listed above can be used by customizes as well. Developers making these changes should not change any out-of-the-box artifacts. This may cause failures during Upgrade. To start customizing Archive Upgrade the customizer must decide on a location to store the Customized Archive Upgrade Artifacts. This will be referred to as the customization_dir. The com.ptc.windchill.ixupgrade.customization_dir property must be added to site.xconf and propagated to ixupgrade.properties. The artifacts to be created and the syntax is exactly the same as the out-of-the-box procedure. Please refer to the other sections for details. The most important difference is the location for the customized artifacts. Create all the required artifacts as described in the document. Run the IXUpgrade utility. The rules and XSLs will be generated under the customization_dir directory.

How customized archive upgrade works?


In a customized environment Archives created might contain out-of-the-box objects as well as well as customized objects. out-of-the-box objects are handled automatically. Rules for out-of-the-box objects cannot be customized or changed; they can only be changed as result of a MOR update. If the customization_dir is specified then the Archive Upgrade framework assumes that customization has been done. The Archive Upgrade framework distinguishes between customized artifacts and out-of-the-box artifacts. There are two sets of rules and two sets of generated and hand-written XSL. At the time of upgrade the two sets of rules are combined to form a single consolidated set of rules. Since there cannot be any overlap in the objects available out-of-the-box and objects that are Customized the right rules are automatically applied. It is very important to test all these changes and restore on a test system to make sure there are no problems in you upgrade code or artifacts.

40-8

Windchill Customizers Guide

Writing upgrades Preparation for Archive Upgrade Development


Create a directory structure similar to the following. The only variable is the cust_archive_upgrade directory that can be given a suitable name and stored in a convenient location.

CAPTION

Determine Schema Changes


Determine the types of changes that have occurred between releases. For the kind of changes that are possible please refer to Schema Changes.

Deciding what artifacts need to be created


Decide a phase / phases for which you would have to create Artifacts. Refer to the various phases in Archive Upgrade for details of the phase. JarPreUpgrade XMLUpgrade

Refer to common uses cases and how to write upgrades from them in the Common Use Cases section.

Create the Upgrade descriptor


Create an upgrade descriptor in the right directory having a meaningful name.

Create Artifacts as required


Create custom XSLs , write java code etc for the phases you have chosen and put them into the appropriate directory. Make sure that your complied java code is available in the Methodserver's classpath.

Customizing Archive, Purge, and Restore

40-9

Run the IXUpgradeUtility


Running the IXUpgradeUtility will cause generation of all artifacts viz. rules, Generated XSLs.

Testing Restore
The generated artifacts should be tested on a test system by restoring old archives containing customized objects prior to deploying on a production system.

40-10

Windchill Customizers Guide

41
Import Export Framework
This chapter describes the Import Export (IX) Framework and explains how to customize and use it for various solutions. Topic Page

Overview ...........................................................................................................41-2 How to Write an IX Application .......................................................................41-3 How to Write Exp/Imp Handlers.....................................................................41-17 Navigating Through an Objects Structure with ObjectSet Application.........41-26 Product Design eXchange (PDX) Support for Export ....................................41-46

41-1

Overview
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.

41-2

Windchill Customizers Guide

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(). The existing implementations of the Application Export Handler are:

Import Export Framework

41-3

WCXMLExportHandler extends ApplicationExportHandlerTemplate. This is a public class designed for creating export jar file on server. (It is mostly a copy of the inner class ExportHandler in StandardIXBService.). This handler will be removed in 7.0, since now we have ApplicationExportHandlerForJar. 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 in the section, "Example of an Export Application" later in this chapter. 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 IXBStreamer.CLIENT_SAVE_AS_FILE needs to be set with the complete client side file path:
WTContext.getContext().put(IXBStreamer.CLIENT_SAVE_AS_FILE,CLIE NT_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, String targetDTD, IxbElement localMappingRules, File policyRuleFile) throws WTException { super ("export", localMappingRules);

41-4

Windchill Customizers Guide

// -- init expActionTuner -applicationExportHandler = _applicationExportHandler; dtd = targetDTD; // -- init expActionTuner -expActionTuner = new ExportActionTuner (policyRuleFile); }

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 storeDocument (ApplicationDataob); (IxbElement elem);

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 used in Windchill 9.0 is standardX10.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. 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>

Import Export Framework

41-5

<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 dont 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> <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.

41-6

Windchill Customizers Guide

<?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> <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>

Import Export Framework

41-7

If you dont want to override anything, just pass null for the argument policyRuleFile. An instance of the Exporter must be created via the factory method newExporter() of the class IxbHelper. For example:
Exporter exporter = IxbHelper.newExporter ( appHandler, IxbHelper.STANDARD_DTD, localMappingRules, policyRuleFile);

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 <WC_home>\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 the part How to write Export Handler 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 one by one. Lets assume that those objects are in a set called res, then you can export them like this:
Iterator iter = res.iterator(); while (iter.hasNext()) { Persistable obj = (Persistable)iter.next(); exporter.doExport(obj); }

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.

41-8

Windchill Customizers 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 doImportImp() method in the StandardIXBService and 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 details in the part Example of an Import Application.

Import Export Framework

41-9

Versioned objects can be imported in any of 10 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 dont have to worry about the Actor classes. A list of all available action names can be found in the file Windchill\src\wt\ixb\registry\ixb\handlers\ actor.xml. All of the actions are different from each other in 3 crucial methods: previewObject, createObject and storeObject. In the class ExpImpForVersionedObject, based on action name and action information that are passed into the IxbDocument fileXML, appropriate actor will be created and this actors 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, 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. No, we dont check it 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

41-10

Windchill Customizers Guide

such an object exists AND it is checked out, update it with information from the XML file. Otherwise, throw an error. 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> <xsl:template match='WTDocument'> <actionInfo> <action>PickExistingObject</action> </actionInfo> </xsl:template> <xsl:template match='EPMDocument'>

Import Export Framework

41-11

<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,
String String Boolean Boolean ) throws WTException _dtd, _ruleFileName, _overrideConflicts, _validate

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 2 methods:

41-12

Windchill Customizers Guide

getContentAsInputStream (String contentId); getContentAsApplicationData (String contentId); The later method may always return null to indicate that the file does not exist in Windchill DB. Note: Please see the inner class ImportHandler of the class StandardIXBService for an example of implementation of an application import handler. 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 9.0 is standardX10.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> <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>

Import Export Framework

41-13

<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 If you dont want to override anything, just pass null for the argument localMapppingRules.
_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( handler, IxbHelper.STANDARD_DTD, ruleFileName, overrideConflicts, null);

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();

41-14

Windchill Customizers Guide

doImport (doc) This method doesnt 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 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:


doImport_CheckConflicts() - check conflicts for imported objects. doImport_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.

In the method importElement() the import handler for a particular type of the object is created by calling getImportHandler(tag, dtdFromXML). The method getImportHandler() finds the appropriate handler for the imported 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 R9.0 it is standardX10.dtd. After getting the handler for the element, the importElement() calls the following methods:
handler.importElement() to do the import task. handler.outputLog() to send log to user.

All handlers for non-versioned objects (for example links, ReportTemplate ... ) extend the class ClassExporterImporterTemplate, 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 doesnt implement the method importElement(), then the call invokes the default method importElement() of the class ClassExporterImporterTemplate. In this class, the importElement() method calls to findAmongExistingObjects (fileXML, importer); 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:

Import Export Framework

41-15

createObject (fileXML, importer); importObjectAttributes (ob, fileXML, importer); storeObject (ob, fileXML, importer); importObjectAttributesAfterStore (ob, fileXML, 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 doesnt implement the method importElement(), then the call invokes the default method importElement() of the class ExpImpForVersionedObject. In this class, despite the object in the XML file exists in the database or not, the importElement() method always calls to:
createObject (fileXML, importer); importObjectAttributes (ob, fileXML, importer); storeObject (ob, fileXML, importer); importObjectAttributesAfterStore (ob, fileXML, importer);

Then, the Import Application can do a clean-up, and send messages to the client. The import process is finished.

41-16

Windchill Customizers Guide

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>standardX10.dtd</dtd> <targetTag>default</targetTag> <handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler> </classExporter>

Import Export Framework

41-17

All handlers with the <dtd> tag standardX10.dtd are handlers for export object in R9.0. For example, for R9.0 we have tags:
<classExporter> <class>wt.part.WTPart</class> <dtd>standardX10.dtd</dtd> <targetTag>default</targetTag> <handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler> </classExporter>

So we know that the class wt.ixb.handlers.forclasses.ExpImpForWTPart is a handler for exporting the class wt.part.WTPart in R9.0 format. The class IxbHandlersManager contains all necessary methods to manipulate handlers.

DTD Files
In the folder Windchill\src\wt\ixb\registry\ixb\dtds\standardX10.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, IxbDocument fileXML, 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,

41-18

Windchill Customizers Guide

"exportAttributes: could not export object=<"+object+">"); } }

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 (<WC_home>\registry\ixb\ handlers\coreX10.xml) that specifies the class being exported (com.mycompany.MyObject), the XML DTD for core Windchill objects (standardX10.dtd), and the handler for the class (wt.ixb.handlers.forclasses.ExpImpForMyObject). An example entry follows:
<classExporter> <class>com.mycompany.MyObject</class> <dtd>standardX10.dtd</dtd> <targetTag>default</targetTag> <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 AttributeExporterImporterTemplate. 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. 3. 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() );

Import Export Framework

41-19

} catch (Exception e){ LogHelper.devExc (e, "Exception in ExpImpForLTPartAttr, ob=<"+obj+">"); } }

After adding this, the export handler for class may call this method to have the part attribute exported.

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>standardX10.dtd</dtd> <handler>wt.ixb.handlers.forclasses.ExpImpForWTPart</handler> </elementImporter>

All handlers with the <dtd> tag standardX10.dtd are handlers for import object in R9.0.
For R9.0 format we have tags:

41-20

Windchill Customizers Guide

<elementImporter> <tag>WTPart</tag> <dtd>standardX10.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 R9.0. The class IxbHandlersManager contains all methods to manipulate handlers.

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: 3. public Object createObject (IxbElement fileXML, Importer importer) 4. Override the following methods if necessary:
public Object importObjectAttributes (Object ob, IxbElement fileXML, Importer importer); public Object storeObject (Object object, IxbElement fileXML, Importer importer); public Object importObjectAttributesAfterStore(Object object, IxbElement fileXML, Importer importer); public Object findAmongExistingObjects (IxbElement fileXML, Importer importer);

Import handlers for non-versioned objects are quite straightforward, and any of the following classes can be referred as example:
ExpImpForWTPartDescribeLink ExpImpForWTPartReferenceLink ExpImpForWTPartUsageLink

Import Export Framework

41-21

Note: An object is imported by the following sequence: createObject(),


importObjectAttributes(), storeObject(), importObjectAttributesAfterStore(). createObject(): if the object doesnt exist in database (is not found by findAmongExistingObjects), it will be created, and all the Ufid attribute of the object is imported. importObjectAttributes(): import all attributes of the object storeObject(): the method storeObject() will call to PersistenceHelper.manager.store(). importObjectAttributesAfterStore() iimports all attributes that must be

imported after the object is stored. 5. Add an entry to the handlers registry file (<WC_home>\registry\ixb\ handlers\coreX10.xml). The entry specifies the class being imported (MyObject), XML DTD for core Windchill objects (standardX10.dtd), and the handler for the class com.ptc.mypackage.ExpImpForMyObject. An example entry follows:
<elementImporter> <tag>MyObject</tag> <dtd>standardX10.dtd</dtd> <handler>com.ptc.mypackage.ExpImpForMyObject</handler> </ elementImporter >

Handler for Versioned Object

1. Create a Java class that extends ExpImpForVersionedObject 2. Implement the following methods:
public Mastered getMaster (IxbElement fileXML):

returns the Object Master if there is any version of the importing object in the database, otherwise returns null.
public Versioned createNewObject (IxbElement fileXML,Importer importer): create a new object with

information from the XML file. 3. Override the following methods if necessary:
public Object importObjectAttributes (Object ob, IxbElement fileXML, Importer importer);

public Object importObjectAttributesAfterStore(Object object, IxbElement fileXML, Importer importer); public Object findAmongExistingObjects (IxbElement fileXML,

41-22

Windchill Customizers Guide

Importer importer);

Note: An object is imported by the following sequence: createObject(),


importObjectAttributes(), storeObject(), 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 dont 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 dont 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 (<WC_home>\registry\ixb\ handlers\coreX10.xml). The entry specifies the class being imported (MyObject), XML DTD for core Windchill objects (standardX10.dtd), and the handler for the class com.ptc.mypackage.ExpImpForMyObject. An example entry follows:
<elementImporter> <tag>MyObject</tag> <dtd>standardX10.dtd</dtd> <handler>com.ptc.mypackage.ExpImpForMyObject</handler> </ elementImporter >

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:

Import Export Framework

41-23

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.

41-24

Windchill Customizers Guide

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"); 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; }

Import Export Framework

41-25

Navigating Through an Objects 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 <WT_HOME>\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. 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.

41-26

Windchill Customizers Guide

Generators are rules that are used by the application to traverse through the objects 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 out-of-the-box 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.getAllAvaiableGenerators(). The call returns all available Generators in the system.
IXBHelper.service.getGeneratorList() returns a list of Generators that

will be displayed to the GUI for end-user selection. This helps to hide Generators that you dont want the end-user to see. To hide these Generators, the XML files for these Generators, should have the <display> tag set to false.

Import Export Framework

41-27

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>

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
.rbInfo file specified by localizedName/localizedString/class and its key in the .rbInfo file is localizedName/localizedString/key.

If you dont 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>

41-28

Windchill Customizers Guide

Available Filter Id-s 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.getAllAvaiableFilters(). It returns all available Filters in the system. IXBHelper.service.getFilterList() returns a list of Filters that will be displayed to the GUI for user selection. This function help to hide filters which you dont 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. Note: If the tag <display> is not specified, or set to true, the Generator will be included in the result of the method ObjectSetHelper.getListOfObjectSetGenerators() and it will be displayed in the GUI. If the tag <display> is false, the Generator will not be included in the result of the method ObjectSetHelper.getListOfObjectSetGenerators(), and it will not be displayed to the GUI. To get all Generators in the system, use the method ObjectSetHelper.getAllAvaiableGenerators(). All the methods getGenerators and getFilters return Vectors that contain an element list of the type IXBHandlerDescription. Use getId() of those elements to get lists of Generators or Filters that are 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. (From <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>

Import Export Framework

41-29

<rule> <for>wt.part.WTPartDescribeLink</for> <go> <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:
(File: <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.

41-30

Windchill Customizers 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: a. public boolean canBeUsedAsTopLevelObject(Persistable obj) b. 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

This appendix provides help for the GUI developer who will be using the IX Object Collection mechanism by calling: ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters(generatorIds, generatorParams, filterIds, filterParams);

Import Export Framework

41-31

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 (Dont pass null, an exception is thrown) To get String constants for GUI, see Windchill\codebase\wt\ixb\ objectset\ObjectSetResource.rbInfo.

41-32

Windchill Customizers Guide

Generators list
String id Description Localized name En (for GUI) Parameters as String

folderContent

Collects all objects in a given Cabinet/Folder (including subfolders) Collects all children of a given Part (e.g. Parts, which it uses and Documents which describe it)

Cabinet and Folder

<class name: oid>, like: wt.folder.Subfolder:1234 or wt.folder.Cabinet: 1234

productStructureNavi gator

Product Structure (built with active Config Spec)

<class name: oid>, like: wt.part.WTPart:1234 for the top-level object. This object must be instance of WTPart <class name: oid>, like: wt.epm.EPMDocument:12 34 for the top-level object. This object must be instance of EPMDocument <class name:oid>, like: wt.part.WTPart:1234 for the top-level object. This object must be instance of WTPart

productStructureNavi gatorEPM

Collects all children of a given CAD Document

CAD Document Structure (built with active config spec)

productStructureNavi gatorWithEPM

Collects all children of a given Part including related CAD Documents

Product Structure with CAD documents (built with active Config Spec)

singleDocument

Takes only given document

Document

<class name: oid>, like: wt.doc.WTDocument:1234

Note: actually <class_name:oid> is object local id

Filters list
String id Description Localized name En (for GUI) Parameters as String

filterByTime

Filters out objects with modification time before/after the given interval

Filter based on modification time

<timeFrom#timeTo>, where timeFrom and timeTo = null or Timestamp.toString()

Import Export Framework

41-33

Examples about Exp/Imp Application:


Export Application

The current Windchill Export out-of-the-box GUI and the StandardIXBService is an Export Application. The out-of-the-box Windchill Export GUI is Export Application (client) that calls export process in StandardIXBService (Export Application (server)) via IXBHelper. There are two ways to use it: With GUI:
IXBExpImpStatus status = IXBHelper.service.doExport( boolean previewOnly, String[ ] generatorIds, String[ ] generatorParams, String[ ] filterIds, String[ ] filterParams, IXBStreamer ruleFile, String guiId, boolean detailedLog);

Without GUI:
IXBExpImpStatus status = IXBHelper.service.doExport( boolean previewOnly, String[ ] generatorIds, String[ ] generatorParams, String[ ] filterIds, String[ ] filterParams, IXBStreamer ruleFile, boolean detailedLog, String stDtd);

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).

41-34

Windchill Customizers Guide

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. 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 out-of-the-box GUI is Import Application client that calls import process in StandardIXBService (Import Application server) via IXBHelper.

Import Export Framework

41-35

There are two ways to use it: With GUI:


IXBExpImpStatus status = IXBHelper.service.doImport( IXBStreamer ruleFile, IXBStreamer dataFile, boolean overrideConflicts, String guiId, boolean isPreview, boolean detailedLog, String creatorName);

Without GUI:
IXBExpImpStatus status = IXBHelper.service.doImport( IXBStreamer ruleFile, IXBStreamer dataFile, boolean overrideConflicts, boolean isPreview, boolean detailedLog, String creatorName, String stDtd);

IXBHelper is a class in wt.ixb.clientAccess.

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.

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.

41-36

Windchill Customizers Guide

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

41-37

Simple Export Handler Code:


import import import import import import java.io.File; java.io.PrintStream; java.io.IOException; java.io.InputStream; java.io.FileOutputStream; java.io.FileInputStream;

import java.util.HashSet; import java.util.Set; import java.util.Iterator; import import import import wt.pom.Transaction; wt.content.ApplicationData; wt.content.ContentItem; 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 ApplicationExportHandlerTemplate{ 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";

public SimpleApplicationExportHandler(File tmp_storeDir, PrintStream a_log) throws WTException{ if (!tmp_storeDir.exists()){ tmp_storeDir.mkdirs(); } targetDir = tmp_storeDir;

41-38

Windchill Customizers Guide

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); } } 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);

Import Export Framework

41-39

} public void exportObjectContent (Object obj, Exporter exporter, ContentItem 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, design57.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); 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); }

41-40

Windchill Customizers Guide

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, container, IxbHelper.STANDARD_DTD, clientSettingsElement, null, actionName); } else{ exporter = IxbHelper.newExporter (this, container, IxbHelper.STANDARD_DTD, clientSettingsElement, policyFile, null ); } //gen set of items to export Set res = ObjectSetHelper.computeObjectSetForGivenGeneratorsAndFilters (generatorIds, generatorParams, filterIds, filterParams); Iterator iter = res.iterator(); Transaction trx = new Transaction(); try { if ( !(actionName != null && actionName.equals(wt.ixb.tuner.ExportActionHelper.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.ExportActionHelper.NO_ACTION_CMD) )){ trx.commit(); } trx = null; } finally { if (trx != null) {

Import Export Framework

41-41

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; } }

41-42

Windchill Customizers Guide

Simple Import Handler Code:


import import import import import import java.io.File; java.io.PrintStream; java.io.IOException; java.io.InputStream; java.io.FileOutputStream; 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 import import import import wt.ixb.publicforhandlers.IxbElement; wt.ixb.publicforhandlers.IxbHndHelper; wt.ixb.publicforapps.IxbDocument; wt.ixb.publicforapps.Importer; 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; } public InputStream getContentAsInputStream (String contentId) throws WTException { try{ return jr.getStreamByName (contentId);

Import Export Framework

41-43

} 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, containerMappingFileName, actorName, overrideConflicts, null /*validate*/); String [] fns = jr.getNonContentFileNamesByExtension ("xml"); boolean validate = IxbHndHelper.getIxbProperty("import.parser.validate", false);

41-44

Windchill Customizers Guide

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

41-45

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 prodcut structure in Windchill system

Corresponding PDX output as seen in PDXplorer

41-46

Windchill Customizers Guide

Customization Points
Required artifacts Class files: wt.ixb.pdx.* XSL path used for transformation : <WT_HOME>codebase\registry\ixb\pdx DTD path: <WT_HOME>codebase\registry\ixb\pdx\dtds

Default behavior By default it would be Agile compatible. By default: Agile_07.dtd and wcxml2pdx_agile.xsl would be the respective dtd and xsl corresponding to Agile format. IPC_2571.dtd and wcxml2pdx.xsl would be the 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) wcxml2pdx_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.

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( java.lang.String name, java.lang.String exporter, java.lang.String[] generParams, java.lang.String[] filterParams) java.lang.String description, java.lang.String[] generIds, java.lang.String[] filterIds, throws wt.util.WTException

Import Export Framework

41-47

Purpose: Creates 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 String id for object set generator types, e.g. {"singleDocument", "productStructureNavigatorWithEPM"} 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( wt.inf.container.WTContainerRef container, java.lang.String description, java.lang.String[] generIds, java.lang.String[] filterIds, throws wt.util.WTException java.lang.String name, java.lang.String exporter, java.lang.String[] generParams, java.lang.String[] filterParams)

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 makes export generIds - Array of String id for object set generator types, e.g. {"singleDocument", "productStructureNavigatorWithEPM"} 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

41-48

Windchill Customizers Guide

Throws: wt.util.WTException

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX( java.lang.String name, java.lang.String exporter, java.lang.String[] generParams) java.lang.String description, java.lang.String[] generIds, 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 generator types, e.g. {"singleDocument", "productStructureNavigatorWithEPM"} generParams - Array of local id for the corresponding seed objects

Throws: wt.util.WTException

public static wt.ixb.objectset.ExportPackage createExportPackageForPDX( wt.inf.container.WTContainerRef container, java.lang.String description, java.lang.String[] generIds, throws wt.util.WTException java.lang.String name, java.lang.String exporter, java.lang.String[] generParams)

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 generator types, e.g. {"singleDocument", "productStructureNavigatorWithEPM"}

Import Export Framework

41-49

generParams - Array of local id for the corresponding seed objects

Throws: wt.util.WTException

doExportToPDX

public static void doExportToPDX( ExportPackageForPDX expPackage, File dirToSave, throws wt.util.WTException String attachmentOption, String zipName)

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) PDXExportHandler.XML_VALUE_ATTACHMENTS_AS_FILE_NAME S - 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 name without extension since extension '.pdx' is added)

Throws: wt.util.WTException

41-50

Windchill Customizers Guide

public static void doExportToPDX( ExportPackageForPDX expPackage, java.io.File dirToSave, throws wt.util.WTException java.lang.String attachmentOption, 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_NAME S - 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 name without extension since extension '.pdx' is added)

Throws: wt.util.WTException

Sample Program 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.size()]; 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);

Import Export Framework

41-51

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");

41-52

Windchill Customizers Guide

42
Evolvable Classes
This chapter describes evolvable classes. Topic Page

Background Information ...................................................................................42-3 General Externalization Guidelines...................................................................42-4 Hand-coded Externalization Guidelines............................................................42-4 Migration Guidelines for Classes with Hand-coded Externalization................42-5 Examples of Generated Externalization Code for Evolvable Classes...............42-6

42-1

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. During the migration period (that is, at Windchill Release 4.0), all Externalizable classes have the methods necessary to manage class compatibility but, in the future, only Evolvable classes will have these features. 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. This property is on the Windchill tab of the class specification in Rose.

42-2

Windchill Customizers Guide

Background Information
As of Release 4.0, 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.

Evolvable Classes

42-3

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.

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.

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 nontransient, persistent fields of the class. (This occurrence should be rare.)

Do not model a serialVersionUID attribute with a value other than 1 as this disallows the ability to read old versions of the class.

42-4

Windchill Customizers Guide

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 on the Windchill tab of the class specification in Rose 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().

Evolvable Classes

42-5

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 X-10 */ //##end version.uid uid = 6676079877272797361L

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 ); //##end writeExternal%writeExternal.body }

42-6

Windchill Customizers Guide

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 }

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

Evolvable Classes

42-7

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 ) super.readExternal( input ); 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.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 } // if not doing backward compatibility // handle super class

42-8

Windchill Customizers Guide

Example of a readOldVersion Method


This method is generated virtually the same as readVersion <EXTERBALIZATION_VERSION_UID> to support backward compatibility with the pre-R4 stream format. 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 ) { 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 streamif ( 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=

Evolvable Classes

42-9

" + readSerialVersionUID + " local class externalizationVersionUID= " + EXTERNALIZATION_VERSION_UID ); return success; //##end readOldVersion%readOldVersion.body }

42-10

Windchill Customizers Guide

43
Creating Large Objects (LOBs)
This chapter describes how to create large objects (LOBs). Topic Page

Creating Large Objects (LOBs) ........................................................................43-2

43-1

Creating Large Objects (LOBs)


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 attributes 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. 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:

43-2

Windchill Customizers Guide

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)

43-3

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(); File lobFile = new File(lobIt); long len = lobFile.length(); System.out.println( "file length "+len ); InputStream aIs = new FileInputStream(lobFile);

43-4

Windchill Customizers Guide

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 ); // save a LOB of known length len = lobFile.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 ) { trx.rollback(); throw new RuntimeException("Error processing lobs"); } } } } } catch (WTException WTe) { WTe.printStackTrace();

Creating Large Objects (LOBs)

43-5

} } 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

43-6

Windchill Customizers Guide

44
Customizing Data Formats
This chapter explains how to customize data formats. Topic Page

Adding and Updating Data Formats for Content Holders.................................44-2

44-1

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 the Managing Customizations chapter on page 5-1. 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 Solution Name, 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) MIME type (required)

Displays this name (for example, Microsoft Word) in the client to identify the file format. The value specified must be unique. 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 objects will be set when a file is uploaded. Describes this data format object. Indicates whether or not this data format type can be indexed. Most MIME types supported are defined in the system when it is installed. However, any simple text format is indexable.

Description (optional) Indexable (required)

44-2

Windchill Customizers Guide

Attribute

Description

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 Solution Name codebase. However, you must ensure that the pixel size for your icon is 16 x 16 to avoid an error when viewing icons. Defines the extensions that are associated with this particular mime type (for example, .doc or .rtf for Microsoft Word).

Extensions (required)

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.rbinfo file and then run the ResourceBuild utility to generate resource classes from FormatNameRB.rbinfo file. Enter the new line using the following format:
<Mime_Type>.value=<Display_Value>

For example, if the MIME type is Java Archive and display value desired is Java Archive File, then new entry is as follows:
Java Archive.value=Java Archive File

For details on using the ResourceBuild utility, see the System Generation chapter on page 31-1.

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.rbinfo 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

Customizing Data Formats

44-3

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, then data format is not deleted and error is shown.

44-4

Windchill Customizers Guide

V
Customization Appendices Section

Chapter

Page

Extendable Classes in the Windchill Supported API............................ A-1 Multi-Object Conversion Guidelines .................................................... B-1 Creating Non-Modeled Services for Listening ..................................... C-1 Windchill Profiler ................................................................................. D-1 Additional Topics - Client Customization .............................................E-1

A
Extendable Classes in the Windchill Supported API

This appendix lists many of the extendable classes and implementable interfaces in the Windchill supported API. It serves as a roadmap to help guide developers when initiating modeling activities. Further information about these classes can be found throughout this manual, and in the Windchill Javadoc. Many Windchill objects and features can be tailored without programmatic customization. For more information on these options, see the Customization Overview on page 1-1. Additional information can also be found in the Windchill System Administrator's Guide, and the Windchill Business Administrator's Guide. Topic Page

PDM Business Information Classes ...................................................................A-2 Enterprise Business Information Classes ...........................................................A-2 Windchill Services .............................................................................................A-2 Foundation Classes.............................................................................................A-3 PDM Auxiliary Business Information Classes...................................................A-3 Business Logic Classes ......................................................................................A-3 Server Development Classes ..............................................................................A-4 Client Development Classes...............................................................................A-5

A-1

PDM Business Information Classes


Following are the starting points for extending PDM objects (part, document, and change objects). If you want to extend the behavior of the Windchill out-of-thebox PDM objects, start by extending these classes. For an overview of these classes, see the The Enterprise Layer chapter on page 36-1.
wt.change2.WTAnalysisActivity wt.change2.WTChangeActivity2 wt.change2.WTChangeInvestigation wt.change2.WTChangeIssue wt.change2.WTChangeProposal wt.change2.WTChangeRequest2 wt.doc.WTDocument wt.doc.WTDocumentMaster wt.part.WTPart wt.part.WTPartMaster

Enterprise Business Information Classes


To create new business classes (other than the PDM classes described above), the following enterprise classes provide a good base from which to start:
wt.enterprise.FolderResident wt.enterprise.IteratedFolderResident wt.enterprise.Managed wt.enterprise.RevisionControlled wt.enterprise.Simple

Windchill Services
The following extendable classes represent the Windchill plug-and-play interfaces. For more information, see the Windchill Services chapter on page 30-1.
wt.change2.Changeable2 wt.content.ContentHolder wt.content.FormatContentHolder wt.folder.Foldered wt.folder.IteratedFoldered wt.index.Indexable wt.locks.Lockable wt.ownership.Ownable wt.vc.baseline.Baselineable wt.vc.Iterated wt.vc.Mastered wt.vc.Versioned wt.vc.views.ViewManageable wt.vc.wip.Workable

A-2

Windchill Customizers Guide

Foundation Classes
For an overview, see the Modeling Business Objects chapter on page 4-1, specifically the Windchill Foundation Abstractions section on page 4-8.
wt.fc.BinaryLink wt.fc.IdentificationObject wt.fc.Identified wt.fc.Item wt.fc.Link wt.fc.NetFactor wt.fc.ObjectMappable wt.fc.ObjectReference wt.fc.ObjectToObjectLink wt.fc.Persistable wt.fc.QueryKey wt.fc.SemanticKey wt.fc.UniquelyIdentified wt.fc.WTObject wt.fc.WTReference

PDM Auxiliary Business Information Classes


The following extendable classes provide some of the basic functionality of the PDM business information classes.
wt.vc.ObjectToVersionLink wt.vc.struct.IteratedDescribeLink wt.vc.struct.IteratedReferenceLink wt.vc.struct.IteratedUsageLink wt.VersionToVersionLink

Business Logic Classes


Following are extendable business logic classes:
wt.eff.DateEff wt.eff.DisplayIdentificationEffConfigurationItemDelegate wt.eff.Eff wt.eff.EffConfigurationItem wt.eff.EffContext wt.eff.EffGroupRangeDelegate wt.eff.EffManagedVersion wt.eff.EffRange wt.eff.IncorporationDate wt.eff.LeftFilledStringEff wt.eff.StringEff wt.eff.ValidEffsDelegate wt.effectivity.DatedEffectivity wt.effectivity.Effectivity wt.effectivity.UnitEffectivity wt.part.BOMHierarchyVisitor wt.part.BOMPartsListVisitor wt.part.HtmlHeadingHierarchyVisitor wt.part.HtmlNumberedHierarchyVisitor wt.part.HtmlPreformattedHierarchyVisitor

Extendable Classes in the Windchill Supported API

A-3

wt.part.HtmlPreformattedPartsListVisitor wt.series.HarvardSeries wt.series.IntegerSeries wt.series.MulticharacterSeries wt.series.MultilevelSeries wt.series.Series wt.vc.baseline.Baseline wt.vc.baseline.BaselineVisitor wt.vc.baseline.ManagedBaseline wt.vc.config.ConfigSpec wt.visitor.BasicNodeExpander wt.visitor.CompositeVisitor wt.visitor.ConfigSpecNodeExpander wt.visitor.Expander wt.visitor.NodeExpander wt.visitor.NodeExpandInfo wt.visitor.RoleExpandInfo wt.visitor.TextOutputVisitor wt.visitor.Visitor wt.visitor.VisitorAdapter wt.visitor.Walker

Server Development Classes


Following are extendable server development classes:
wt.cache.CacheManager wt.doc.DocumentContentProcessing wt.doc.DocumentDelegate wt.doc.WTDocumentDelegate wt.events.KeyedEvent wt.events.KeyedEventBranch wt.events.KeyedEventListener wt.events.KeyedEventListenerAdapter wt.feedback.ProgressCountFeedback wt.feedback.StatusFeedback wt.feedback.WTContextUpdate wt.httpgw.HTTPAuthentication wt.pom.TransactionListener wt.util.CollationKeyFactory wt.util.WTThread

A-4

Windchill Customizers Guide

Client Development Classes


Following are extendable client development classes:
wt.clients.beans.AssociationsLogic wt.clients.beans.EffectivityTaskLogic wt.clients.beans.explorer.WTBusinessObject wt.clients.beans.selectors.ComponentDelegate wt.clients.change2.WTChangeIssueTaskDelegate wt.clients.change2.WTChangeOrder2TaskDelegate wt.clients.change2.WTChangeRequest2TaskDelegate wt.clients.doc.WTDocumentTaskDelegate wt.clients.effectivity.ConfigurationItemTaskDelegate wt.clients.folder.SubFolderTaskDelegate wt.clients.homepage.WindchillHome wt.clients.prodmgmt.HelperPanel wt.clients.prodmgmt.PartItem wt.clients.prodmgmt.PartMasterItem wt.clients.util.ReferenceHolder wt.clients.util.TaskDelegateException wt.clients.vc.AlreadyCheckedOutException wt.clients.vc.CheckedOutByOtherException wt.clients.vc.CheckInOutException wt.clients.vc.NotCheckedOutException wt.identity.DisplayIdentification wt.identity.DisplayIdentificationDelegate wt.identity.DisplayIdentificationPersistableDelegate wt.identity.DisplayIdentificationStandardDelegate wt.identity.DisplayIdentificationStandardVersionedDelegate wt.identity.DisplayIdentificationVersionedDelegate wt.identity.DisplayIdentity wt.identity.StandardDisplayIdentity wt.identity.VersionedDisplayIdentity wt.util.LocalizableMessage

Extendable Classes in the Windchill Supported API

A-5

A-6

Windchill Customizers Guide

B
Multi-Object Conversion Guidelines

Topic

Page

Conversion Overview......................................................................................... B-2 API Guidelines ................................................................................................... B-3 Collections Guidelines ....................................................................................... B-7 Event Dispatch Guidelines ................................................................................. B-9 Multi-Object Delegation Guidelines ................................................................ B-10 Multi-Object Exceptions Guidelines ................................................................ B-11 Multi-Object CRUD API Guidelines ............................................................... B-13 Batch Update/Delete Guidelines ...................................................................... B-13 Transaction Context/Listener Guidelines......................................................... B-14 Neat Tips and Tricks ........................................................................................ B-15

B-1

Conversion Overview
Objectives
Windchill performance is largely a function of database access: how often you go to the database, what you send it, what you ask it to do, and what you ask it to send back to you.The primary goal of converting single-object APIs to multiobject is to replace the CRUD operations driven by single objects with multiobject CRUD operations. A single-object operation that does a query and then updates, individually, the objects returned by that query will execute n queries and as many updates as the number of objects those queries produce. Ideally, the multi-object conversion of that operation will execute one query and one update. While what is being sent to the database, asked of the database, and sent back from the database is about the same, the number of trips has been significantly reduced. Since the connection cost is significant (and, furthermore, since the CRUD operations take advantage of more performant batch SQL operations), the multi-object will significantly outperform the looped-over single-object operation. This is true even before the VM cost of the looping is factored in.

Considerations
The following factors weigh in to increase the complexity of multi-object operations over their single-object counterparts: What should the multi-object operation's signature look like? Exceptions? Related data changing? Data coming at you for different reasons? Complex query building?

B-2

Windchill Customizers Guide

API Guidelines
Multi-Object vs. Multi-Multi-Object APIs
The changeFolder example is a good, illustrative example of how far to go when converting to multi-object. The single object changeFolder API is defined as follows:
public Foldered changeFolder(Foldered member,Folder newFolder)throws WTException

Two obvious multi-object variants are:


public Foldered changeFolder(WTSet folderedSet,Folder newFolder)throws WTException public Foldered changeFolder(WTValuedHashMap folderedToNewFolderMap)throws WTException

The first API requires that all of the objects in the set go to the new folder and represents a simple multi-object API that would require the caller to call the API multiple times if changes to multiple folders are required. The second API simply maps the foldered object to the new folder to change to; it (the multi-multi-object API) is more complex there's a lot more to manage in the API and the caller is required to build the map even if all of the objects are going to a single location. If the second implementation requires an internal breakup by folder, it'll likely not be appreciably more performant than the former. Then again, if it doesn't need to break up the data and can dispatch a single event for all the moved objects, it will likely be more performant, although the added complexity will then be passed onto the multi-object listeners. If performance is the only measurement, the multi-multi-object API wins. However, there are other factors to consider: When weighing the performance benefits, is it really the case that in the API (and in any of the listeners for the events the API might dispatch) the code won't simply end up breaking up the work in such a way that it's really looping over the work as though it were multi-object and not multi-multiobject? Is there a real need to provide that flexibility? Is the additional flexibility worth the additional complexity? If more than a map is needed, multiple, ordered arguments grouped by index is probably the only way to pass the data, but this is somewhat ugly. For example, checkout takes a Workable to check out, a folder to check out to, and a note representing the check out comment; making all three arguments multi-object most likely implies two lists and an array, or three lists.

Note: The changeFolder APIs in the Folder Service are not intended to be used when moving Foldered objects between containers; the moveAllVersions API in the Container Move Service should be used instead.

Multi-Object Conversion Guidelines

B-3

Converting Boolean Operations


The conversion of operations that test conditions and return booleans will result in a collection-based operation that returns either true if all the objects pass the test, or a sub-collection of all the objects that pass the test. In some cases, two operations, one returning a boolean and the other a sub-collection. The decision to produce one, the other, or both should be based simply on need. It should be noted that the boolean operation will generally always be faster than the sub-collection operation because the boolean operation can terminate on the first failure. For this reason, if both are logically needed and the performance differences are non-negligible, it is preferable to produce both (rather than have the caller check that the size of the returned collection is either 0 or equal to the size of the passed-in collection). The boolean-based operation should then share the check and not simply be a wrapper. Whether this is actually done should be weighed against the cost and benefits of actually coding both operations. If both are needed, but time is not available to adequately produce both, the boolean implementation may simply wrap the sub-collection operation. It should be clear in the return type of the operation that the test applies to all or that the test will get those meeting the criteria.

Retaining Single-Object Operations


The creation of a multi-object variant of a single-object operation begs the question: What should you do with the single-object operation? If the operation is no longer used, remove it. If there are reasonable justifications for keeping it around, consider making the single-object operation a simple wrapper to the multi-object variant, as this will reduce maintenance over time. There may, in rare cases, be legitimate reasons to keep the implementations separate (for example, there may be cases where the single-object operation is much more performant than the multi-object counterpart).

WTCollection vs. WTSet/WTList and WTHashSet/WTArrayList


Operations that take collections as arguments will need to decide what type of collection to take. The highest level interface is WTCollection, which is implemented by both the list and set collections (maps do not extend collection in either Windchill or Java). The following high level considerations provide a good start for determining what to take: Your operations should always take interfaces and not the concrete classes; for example, instead of forcing WTHashSet, take WTSet. WTCollection provides the greatest flexibility. WTSet guarantees uniqueness, which is useful if the operation shouldn't logically operate on the same object twice.

B-4

Windchill Customizers Guide

WTList is ordered, which may be needed by some multi-multi-object operations. WTSets provide the most efficient lookup (good for when contains(...) is needed), WTLists have smaller and more efficient memory footprints It is easy to convert between container types.

So, what arguments should your operation take? Firstly (and to reiterate), it should take the interfaces (WTCollection, WTList, WTSet) rather than the concrete classes (WTArrayList, WTHashSet) because the synchronized and unmodifiable variants of these collections do not descend from WTArrayList/WTHashMap. Beyond that, an operations should take what it contractually requires (which may require internal conversions for implementation efficiency): Take a WTList if order matters because other arguments to the operation must be paired with collection (also consider WTKeyMap and WTValuedMap, covered later). Take a WTSet if duplicates should not exist. Take a WTList if both order and duplicates matter (the operation should then internally validate uniqueness). Take a WTCollection if neither duplicates nor order matters.

And, similarly, what should an operation return? Most operations should return WTCollection, providing them the ability to change the underlying implementation without impacting callers In cases where the returned collection is the same object as an argumentpassed collection, return the same type as that argument

Empty collections
Windchill does not have a prescribed standard for the validation of arguments to a method. Some methods exhaustively validate each argument, others leave invalid arguments to fail later in the method (via NullPointerExceptions and the like). The issue of argument validation comes up in collections not because they might be null, but because transformation operations (sub-collections, conditional copying of collection elements, etc.) may result in a collection being empty. That empty collection, then, may be passed to another multi-object API. What would it mean to call store with an empty collection? What should the store method do? There are a few options relative to this: The method checks if the collection argument is empty; if it is empty, it throws an IllegalArgumentException

Multi-Object Conversion Guidelines

B-5

The method checks if the collection argument is empty; if it is empty, it returns (which may necessitate the creation of a potentially ambiguous return value) The method follows the predominant practice for other arguments today; that is, it assumes arguments are passed correctly and attempts to go about its business, potentially failing in odd ways somewhere along the line.

This document recommends the last option. It is the caller's responsibility to recognize when its collections' manipulations may result in empty collections and the caller should not call other multi-object operations with an empty collection. The behavior, unless explicitly documented otherwise, of any multi-object operation is considered to be undefined when empty collections are passed. The justifications for this approach are as follows: There is no established precedent that suggests arguments should be exhaustively validated in Windchill methods, public or not, supported or not. The prevailing practice is that arguments are not checked at all. Operations that manipulate collections in such a way that empty collections may result are presumably a minority, while there can be lots of multi-object operations; it makes sense to localize the handling of empty collections by making it the responsibility of the method that could produce them to handle the end-case. Experience with methods that can produce empty collections has shown that the methods themselves will generally fail even if the multi-object methods they call do not, so it's generally necessary for these methods to be aware of and handle the empty collections they may produce.

Memory considerations
A multi-object operation has a much higher footprint than the corresponding single object operation. This is true in both the VM, where multi-object operations take significantly more memory, and in the database, where transaction sizes increase dramatically. There are some things that can be done to the reduce memory footprint, such as querying only what is needed to make decisions. Both the VM and Oracle can be tuned to handle the expected increased footprints.

B-6

Windchill Customizers Guide

Collections Guidelines
Inflating
The WTCollection interface transparently masks the fact that a persistable can be represented as a QueryKey, WTReference, or full-blown Persistable. It also has iterator APIs (queryKeyIterator(), referenceIterator(), and persistableIterator()) to get the objects based on the representation desired. The persistableIterator() will inflate the query keys and references if they are ot already inflated, but it is important to note that referenceIterator will not. This means that one should be extremely careful using the following code:
for (Iterator i =col.referenceIterator();i.hasNext();){ ... Persistable p =((WTReference)i.next()).getObject(); ... }

The problem with the above code is that the getObject() may result in sequential inflates. Unless you're absolutely sure the collection has bee inflated, this is a bad idea. Even if you are, it's a bad idea. Instead, use the persistableIterator()API.

Using connect()
WTCollection's inflate and refresh implementation does not replace persistables in-place. This means that two collections with the same data may become out-ofsync when an inflate or refresh is done on one of the collections. When creating new collections from the objects in existing collections, use the connect() APIs to ensure that the changes made to objects in one collection affect all the collections which contain the same objects.

WTKeyedMap vs.WTValuedMap
The WTKeyedMap is a map in which the keySet is essentially a WTCollection, providing all of the benefits of the WTCollection to the keys. The values, however, are just a regular collection. Many APIs will wish to map Persistables as keys to Persistables as values, which is exactly what the WTValuedMap provides; the WTValuedMap's values are a WTCollection. Where both the keys and the values are Persistables, the WTValuedMap should be used.

OBJECT_IDENTIFIER vs.VERSION_FOREIGN_KEY collections


Elements in a collection can be keyed by either their ObjectIdentifier/ObjectReference or their VersionForeignKey/VersionReference. The constants OBJECT_IDENTIFIER and VERSION_FOREIGN_KEY, defined in CollectionsHelper, determine which keying mechanism to use (where an Iterated object is added to the collection). Iterated objects in collections keyed

Multi-Object Conversion Guidelines

B-7

differently cannot be connected, because the toIdArray() API will return different IDs for the same objects (one will return OIDs and the other branch Ids), and the get/contains(QueryKey/WTReference) APIs will return false if the reference/key is different than the one in the collection even if the persistable is logically equivalent. Multi-object operations acting on Iterated data, presumably, would need to handle collections keyed either as OBJECT_IDENTIFIER or as VERSION_FOREIGN_KEY. This can get quite complicated, even if the operation simply throws in the towel, inflates the collection, and creates a new collection that is keyed properly . Rather than force all operations to deal with this, the guideline should be that all multi-object operations will assume the collection passed in is keyed as OBJECT_IDENTIFIER unless specifically documented otherwise. This is for the following reasons: The added complexity of handling multiple keyings could, and most likely would, dwarf the true logic on the method. Collections keyed differently cannot be connected. The collection must be inflated to convert their contents to another collection that is keyed differently.

Callers should not call multi-object APIs with collections keyed as VERSION_FOREIGN_KEY unless the APIs are explicitly documented to take them. The APIs being called are not required to verify the passed-in collections' key type, and will most likely fail in odd ways if invalid collections are passed.

Modifying collections
Generally, the contents of collections passed to an operation as argument should not be altered (by removing or adding members); doing so alters the caller's collection. Be especially careful using collections' APIs that produced backedcollections, such as the subCollection(...) APIs, as modifying the contents of a backed collection also change the contents of the source collection.

B-8

Windchill Customizers Guide

Event Dispatch Guidelines


Cleanup
Many of the single-object events could benefit from cleanup work. For exampole, a lot of them include the service, which is of dubious utility. Many have odd datatypes, such as paired vectors. When converting these events to multi-object, how much of this should be cleaned up? Should the multi-object variant, for example, include the service? Should the service be removed from the single object event? Should more of the single object be cleaned up? When considering how much to do, consider also the following: The ultimate goal is to totally replace the single-object variant by converting all the listeners to multi-object, so it may not make much sense to spend significant time cleaning up the single-object events Cleanup of the single-object events beyond that of removing the service will likely require reworking existing listeners, taking time from the more interesting tasks of making those listeners multi-object

In general, little should be done to the single-object events save superficial clean up (such as removing the service). An exception to this is when the changes to the event to make it multi-object necessitate a re-evaluation of the single-object event.

Use of collections
The multi-object events, like other multi-object operations, should pass collections of objects. These collections should be unmodifiable to ensure that listeners and the APIs they call do not alter the contents of the collection.This deviates slightly from the relaxed stance taken above, however there is never justification for a listener to alter an event's contents, so it should be ensured that this does not happen.

Single-and multi-object listeners?


Remember that if a listener listens for both single- and multi-object events (via notifyVetoableEvent and notifyVetoableMultiObjectEvent), it will be dispatched to twice. It is not the case that the dispatch mechanism will determine that it should only notify the single-object variant if the event was dispatched as singleobject, for example. There is only one known case where listening to both is appropriate, and that case is where the listener can't fully handle multi-object but could benefit by doing some of the work upfront,especially to pre-query data.The multi-object listener will be dispatched to first, followed immediately by the single-object listener (in a loop). So, it is possible to listen as multi-object, put the results of a query, for example, on the context, and then use that contextual data in the single-object listener.

Multi-Object Conversion Guidelines

B-9

KeyedEvent's getEventTarget()API
The single-object events all upheld an unspoken, implicit contract when implementing getEventTarget(). The API always returned the target Persistable of the event. This made it possible for listeners to listen generically to multiple events, casting the result of getEventTarget() to a Persistable. The notification functionality, for example, relies on the ability to generically listen to arbitrary events. Multi-object variants of the single-object events must adhere to this policy by ensuring that the result of calling getEventTarget() on a multi-object event is a WTCollection of some form. This will allow generic listeners to cast getEventTarget() to a collection without requiring further knowledge of the event. Note that this does not preclude using the eventTarget field to store more complicated data, such as WTValuedMaps in the WorkInProgressServiceEvent, so long as getEventTarget() is overridden in the event to return an appropriate collection.

Multi-Object Delegation Guidelines


Converting to wt.services.ac.DefaultServices
There are numerous patterns for delegation in place today. Wherever possible and practical, these patterns should be replaced by the use of wt.services.ac.DefaultServices. This single class and its static APIs eliminate the need to do things like implement interfaces such as ApplicationContextChild. As with other "cleanup work" associated with converting to multi-object, actually cleaning up delegation in code should be weighed against the cost of cleanup.

B-10

Windchill Customizers Guide

Multi-Object Exceptions Guidelines


Basic expectations
Multi-object operations can detect multiple failures.The simplest example of this is the query that, if results are found, indicates an error condition. The conversion to multi-object implies that multiple rows may be returned by such a query. Should a single-object exception be thrown against the first result or a multiobject exception against the entire result? More generally, how far should one go in reporting exception conditions to the user? The first, absolute rule is that if a exception is thrown to you, you are done. You should not be continuing after an exception has been thrown because an exception corresponds to a non-local exit, which means that the operation did not finish its normal processing and work was not completed. Not to mention that, oftentimes, the operation, as part of a finally block, will rollback the transaction. This document suggests a throw what you know approach to exceptions. Use the additionalMessages capabilities of the multi-object exceptions when you have additional knowledge. With the example above, it would make sense to build a multi-object exception out of all of the results. Another common example is that of validation in a loop. Say that code is processing the collection in a loop and would throw an exception if the value of a field is invalid. Should this code collect all the failures and throw a multi-object exception at the end of the loop, or should it throw a single-object exception immediately? In most cases, the code should collect the messages for the failures and throw a multi-object exception at the end of the loop.

Pre-flight checks
The single-object APIs all fail fast -- once an error condition is discovered, processing stops and an exception is thrown. For example, if it is determined that the object a user wants to check out is already checked out, the code doesn't continue determining if the user does or does not have modify access; it bails out and throws an exception. Many single-object APIs, and by extension their multi-object counterparts, perform what are called pre-flight checks . These are the validations that occur before the real work is done to the object(s). The single-object APIs bail when the first validation fails. With multi-object operations, however, it is possible to take the another approach. Upon encountering an error, they may continue to collect additional problems so as to later report a more informative exception message. Thus, the multi-object check out operation could check access (provided it uses the non-exception throwing hasAccess ), validate that the objects aren't already checked out, and do a number of other things, recording the problems along the way, and eventually throw a single exception with messages for each of the failures. The motivation to do this is the belief that it will aid the users, as they will get as much information

Multi-Object Conversion Guidelines

B-11

up front as opposed to needling them incrementally (assuming they can and actually do fix the problems reported to them). This document recommends against this approach in favor of the continued practice of failing fast for the following reasons: Exceptions are expected to be infrequent; you should not put significant work into them. This approach requires the use of non-exception-throwing APIs; the exception-throwing variants would prematurely terminate the pre-flight checks. These exception-throwing variants throw their own exceptions, which may be strongly-typed exceptions (such as NotAuthorizedException),and provide their own messages. Calling the non-exception-throwing variants drops the strong typing and makes the message building the caller's responsibility. The additional information gathered is not necessarily correct nor complete. You may either mask errors or produce unreliable ones by either dropping/retaining the objects in the collection that logically failed a preflight check. Similarly, addressing all the issues uncovered during the preflight checks does not guarantee success; there will always be at least some needling.

Focus instead on getting the positive case working.

Multi-object Exceptions and Single-Object APIs


A concern related to multi-object exceptions is that as single-object APIs wrap the multi-object counterparts, they'll suddenly receive multi-object messages. A poor but illustrative example of this is that operation that may have failed with a A message may now get something like The operation failed due to the following errors: A message . If the collection is of size 1 and the multi-object exception would not make sense or would otherwise seem awkward to the existing singleobject clients, preserve the original exception.

B-12

Windchill Customizers Guide

Multi-Object CRUD API Guidelines


Internal Dependency Issues
The multi-object persistence APIs will not unravel dependencies in a collection. If two objects are added to a collection to be persisted and one has a reference to the other, the multi-object store API will do nothing to ensure that the one object gets persisted ahead of the other such that the database will have an appropriate reference value. Worse, because of the manner in which the persistence manager handles persistence, the in-memory objects will appear to contain valid references even if the database does not. Be careful to understand the dependencies in the data. Split up the data where dependencies exist that would yield problems.

Batch Update/Delete Guidelines


When to Use?
The batch update/delete operations represent the most performant option for affecting change in the database because they minimize both the data needed to perform the operation and the data eeded to affect the change neither requires that the objects to be changed first be retrieved from the database and only the columns to change need to be sent (as opposed to full persistables) in the case of a update. These APIs should be considered when: There is no need to bring the object back into the VM, either to perform tests or to dispatch events None of the objects involved in the batch operation exist in memory prior to the batch operation

In most cases, it is sufficient to say that their use should be limited only to cases where there is never a need to bring the object (or its reference) back to memory and should never be used on objects already in memory. The above guidelines are based on the fact that the performance benefits drop when the data is actually needed and by the fact that the changes will not be reflected in any of the inmemory objects. However, a gray area for batch update is in cases where the references are needed for event dispatch, the dispatched event indicates that the change has occurred, and the listeners need not inflate.

Multi-Object Conversion Guidelines

B-13

Transaction Context/Listener Guidelines


Transaction Context vs.Method Context
The method context is a global map that remains in scope for the duration of a server-side call; the transaction context is a map that can be associated with the global (outer-most transaction) or the local transaction and remains in scope so long as the transaction is alive (the context is dropped as immediately prior to committing/rolling back). Nearly all of the usages of the method context should be replaced by the transaction context.

Single-object contexts
Existing single-object code that puts objects on the method context for downstream processing will need to be evaluated. Both the code that puts the object on the context and the code that processes it will likely need to change. In fact, only when the downstream consumer of the context data is guaranteed to still be flat-lined (from the point that the flat-lined code added the context) will the single-object context be OK. The issue, especially in the case of contexts added by listeners, is that the downstream code may be dealing with the entire collection while only a single object is on the context. Keep in mind that the dispatch order is multi0-ab, single0-a, single0-b, multi1ab, single1-a, single1-b, NOT multi0-ab, multi1-ab, single0-a, single1-a, single0-b, single1-b, so if one listener, in single-object mode, adds an object to the context for another listener to consume, the other listener will always only get the last object in the collection on the context because event dispatch will loop over the first listener (single0-a, single0-b) before getting to the second one (single1).

Deferred validation/work with transaction listeners


One of the biggest architecture shifts associated with multi-object operations is the fact that multiple, highly-related, objects are changing in a single transaction. In the single-object model, only one part was being revised or checked out, for example, and code could either assume all the related data was not changing or would explicitly lock the related objects to prevent change; the essential view of the database is that everything outside of the work being done to support the single-object operation is static and unchanging. Multi-object operations break this assumption and force the code to consider what it would mean for related objects in the same transaction to change, either as part of the operation itself or possibly either prior to or post the operation. There will be cases where it is either impractical or impossible to deal with the system while it is in flux; it will be impossible for the operation, when invoked, to validate that the resultant state of the database would be valid or even that everything that would need to be done has been done. This is where transaction listeners come into play. They allow the operation to defer work until the transaction is about to commit.

B-14

Windchill Customizers Guide

The classic use case for deferred validation is when changes to related objects in the same transaction impact the logic of the listener and its APIs. Because of flat-lining and the splitting of collections, if the listener/API cannot handle any of the following, it should move its work into a transaction listener: A related object having already undergone change prior to this object's/collection's changes that are being handled now. The changes occurring to related objects in the same collection. A related object changing after this listener/API processes it.

Remember that the other objects that are changing will likely have their own events associated with them, returning to the same listener/API. You should consider, based on the above points, what happens when related data changes and is processed by the same code both before and after this collection is processed and what it means for data in the same collection to be changing.

Neat Tips and Tricks


Inflating references
If you have a collection of objects with references you wish to inflate, simply add the references to a new collection and inflate it. Since the inflated objects are set in the existing references, this will result in the original object's references getting inflated.

Persisting interdependent data


It is necessary to break up the persistence of objects that have references to other objects being persisted. For example, if code is persisting the master and its first iteration in the same transaction, the store of both objects cannot occur by putting both objects in the collection and persisting them with one API call. However, the nature of the store API operation relieves the caller of the necessity of reconnecting the references, provided the operation is done server-side. The following code is fine:
partMasterCollection = PersistenceHelper.manager.store(partMasterCollection); partCollection = PersistenceHelper.manager.store(partCollection);

The master references in the parts will automatically reflect the persisted changes of the partMasterCollection (most notably, the OIDs will now be in the references.

Multi-Object Conversion Guidelines

B-15

B-16

Windchill Customizers Guide

C
Creating Non-Modeled Services for Listening

Topic

Page

Overview ............................................................................................................ C-2 Create a Service Interface................................................................................... C-2 Create a Standard Service Class......................................................................... C-3 Compile .............................................................................................................. C-5 Register the New Service ................................................................................... C-6 Restart the Method Server.................................................................................. C-6

C-1

Overview
Customers that do not have Windchill InfoModeler may create services for listening to events generated by other services (customers that have Windchill InfoModeler should create listeners by following the instructions in the Creating a Listener Service section of this Guide). Here are the steps necessary to create a non-modeled service for listening: 1. Create a service interface 2. Create a standard service class to implement your service interface and extend the StandardManager class 3. Compile your interface and class into your Windchill codebase 4. Register your new service in the codebase with xconfmanager Below is an example to create a service that listens for pre- and post-checkin events. When it "hears" one of these events, it prints a simple message to standard output. The example assumes the service is in a package called com.acme.listen, and that the service is called the "Listen" service. If you copy this example, be sure to change these names to something more appropriate. The example assumes that you are familiar with the information in the Developing Server Logic chapter on page 35-1.That chapter explains how to write code to register listeners for particular events.

Create a Service Interface


Save the nearly-empty service interface to:
<Windchill>/src/com/acme/listen/ListenService.java

Here is the source code:


package com.acme.listen; public interface ListenService { /* * The interface for the ListenService is empty, but to be compatible * with more complex services, it must exist. */ }

C-2

Windchill Customizers Guide

Create a Standard Service Class


Save the standard service class to:
<Windchill>/src/com/acme/listen/StandardListenService.java

The example below has comments that indicate "standard" pieces of code that should not be changed as they are necessary to interact with the standard service manager and other services. There are other comments that indicate pieces of code that should be changed, for example, to reflect your choice of package and class names and to listen to the particular events you are interested in. Here is the source code:
/* Change to your package name */ package com.acme.listen; /* javac -classpath z:/Windchill/codebase -d z:/Windchill/codebase *.java */ /* xconfmanager -t codebase/wt.properties -s wt.services.service.4160=com.acme.listen.ListenService/com.acme.listen.StandardList enService -p */ /* Change to import you Service Interface */ import com.acme.listen.ListenService; import java.lang.String; /* Standard imports for services */ import wt.services.ManagerException; import wt.services.ServiceEventListenerAdapter; import wt.services.StandardManager; import wt.session.SessionContext; import wt.session.SessionHelper; import wt.session.SessionServerHelper; import wt.session.SessionMgr; import wt.util.DebugFlag; import wt.util.DebugProperties; import wt.util.DebugType; import wt.util.DebugWriter; import wt.util.WTException; /* Changes required here: * Imports necessary for listening to particular events, in this case * check-in and check-out events */ import wt.vc.wip.Workable; import wt.vc.wip.WorkInProgressServiceEvent; /** * Listens for pre/post checkin events. When an event is * "heard", prints messages to the MethodServer log and console. * <p> * Use the <code>newStandardListenService</code> static factory method(s), * not the <code>StandardListenService</code> constructor, to construct * instances of this class. Instances must be constructed using the static * factory(s), in order to ensure proper initialization of the instance. * <p> *

Creating Non-Modeled Services for Listening

C-3

**/ /* Change to your class name */ public final class StandardListenService extends StandardManager implements ListenService { /* Standard class identification string */ private static final String CLASSNAME = StandardListenService.class.getName(); /* Standard debug variables for services */ private static final boolean DEBUG = DebugProperties.isDebugOn(CLASSNAME); private static final DebugWriter LOG = (DEBUG ? DebugProperties.getWriter(CLASSNAME) : null); /* Standard getter for class name */ public String getConceptualClassname() { return CLASSNAME; } /* * Standard default factory for the class. * */ public static StandardListenService newStandardListenService() throws WTException { StandardListenService instance = new StandardListenService(); instance.initialize(); return instance; } /* * Initializations of event listeners */ /* Override inherited method */ protected void performStartupProcess() throws ManagerException { /* Standard debug output */ if (DEBUG && DebugProperties.isTrace(this)) LOG.enter(CLASSNAME,"performStartupProcess"); /* Standard way to become admin */ SessionContext prev = SessionContext.newContext(); try { SessionHelper.manager.setAdministrator(); } catch (WTException wte) { System.err.println("StandardListenService: failed to set Administrator (ok if installation)"); return; } finally { SessionContext.setContext(prev); }

C-4

Windchill Customizers Guide

/* Change: Add event listeners here */ getManagerService().addEventListener( new ServiceEventListenerAdapter( this.getConceptualClassname() ) { public void notifyVetoableEvent( Object event ) throws WTException { final Workable target = ((WorkInProgressServiceEvent)event).getOriginalCopy(); System.out.println("Listen hears PRE_CHECKIN: "); System.out.print(" target:"); System.out.println(target.toString()); } }, WorkInProgressServiceEvent.generateEventKey( WorkInProgressServiceEvent.PRE_CHECKIN )); getManagerService().addEventListener( new ServiceEventListenerAdapter( this.getConceptualClassname() ) { public void notifyVetoableEvent( Object event ) throws WTException { final Workable target = ((WorkInProgressServiceEvent)event).getOriginalCopy(); System.out.println("Listen hears POST_CHECKIN: "); System.out.print(" target:"); System.out.println(target.toString()); } }, WorkInProgressServiceEvent.generateEventKey( WorkInProgressServiceEvent.POST_CHECKIN )); /* Standard debug output */ if (DEBUG && DebugProperties.isTrace(this)) LOG.exit(CLASSNAME,"performStartupProcess"); } }

Compile
Compile your classes into:
<Windchill>/codebase/com/acme/listen

Creating Non-Modeled Services for Listening

C-5

Register the New Service


The standard service manager must be notified that you have created a new service. This is done by registering the service in the wt.properties file using xconfmanager. Use a unique service number that does not already appear in the wt.properties file. Change the reference to the service interface and standard service class to your own.
xconfmanager -t codebase/wt.properties -s wt.services.service.4160=com.acme.listen.ListenService/com.acme.listen.StandardList enService -p

Note that xconfmanager will add the entry to site.xconf and then propagate the changes to wt.properties.

Restart the Method Server


The method server must be restarted so that the standard service manager will start your service and implicitly register your event listeners.

C-6

Windchill Customizers Guide

D
Windchill Profiler
The Windchill Profiler can be used to help diagnose performance bottlenecks after you have customized code. It enables you to capture an elapsed time profile while executing application logic in the method server. The profile shows call stacks, call counts, and context data (for example, SQL, bind parameters, JNDI strings, son on). PTC recommends profiling in a test environment; however, profiling is possible in a production environment without interrupting system operation. Topic Page

Overview ............................................................................................................D-2 Profiler Features .................................................................................................D-2 Profiler Operation...............................................................................................D-2

D-1

Overview
The Windchill Profiler enables you to instrument server side application logic. A user interface is provided to control the profiler, which is embedded within the method server. Note: Support for the profiler is limited and the profiler is subject to change without notice.

Profiler Features
The Windchill Profiler supports the collection of performance profiles in the following Windchill subsystems: JDBC execution CacheManager get/put/update WTAdapter JNDI Task RMI Object Serialization

The profiler allows you to filter call stacks by thread; sort call stacks by count or by cost (for example, elapsed time). The call stacks, call counts, and elapsed times are displayed in a JTree format. The output can include additional data such as SQL bind parameters or cache keys. Profiles can be saved to disk and reloaded, or they can be exchanged using e-mail. HTML summaries can also be generated.

Profiler Operation
To launch the profiler, open a command shell on the Windchill server. From the windchill shell, invoke the profiler as follows:
windchill wt.tools.profiler.WindchillProfiler

Note: A long running profile session might need a larger heap. In that case, use the following command to start the profiler:
windchill --javaargs=-Xmx512m wt.tools.profiler.WindchillProfiler

You are prompted to authenticate. Log in as the administrative user. If the authentication is successful, the profiler opens. From the Operations drop-down menu, select the area that you want to profile. For example to profile all JDBC executed by the Method Server, select SQL + Execution Time + Bind Parameters. To start collecting the SQL profile, click the blue start button. To stop collecting profile data, click the red button.

D-2

Windchill Customizers Guide

In the following example, an RMI-based client executed a number of method calls. Notice that the profile frame is divided into two panes: The left pane allows you to select call stacks sorted by count or by cost. The right pane shows the call stacks for all threads captured by the profile.

Call stacks appearing in the right pane need to be expanded until the leaf node for a given call stack is displayed. The leaf node of a call stack contains an SQL string.

Windchill Profiler

D-3

The call count field for SQL profiles may be a little confusing to interpret at first. To illustrate, look at the following example
O-count=157:wt.pds.BasicResultCursor.next(BasicResultCursor.java:487):cost=16 O-count=155:wt.pds.BasicResultCursor.advance(BasicResultCursor.java:626):cost=16 | O-count=155:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java:159): cost=16 | O-count=155:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java: 134):cost=16 | O-count=155:wt.util.TraceTimingThreadedLogger.addEndEntry( TraceTimingThreadedLogger.java:208):cost=16 | '-count=155:DB FETCH: SELECT 'wt.epm.workspaces.EPMWorkspace',... FROM EPMWorkspace A0 WHERE ((A0.idA3M5 = ?)) AND (A0.markForDeleteA2 = ?):cost=16 count=2:wt.pds.BasicResultCursor.advance(BasicResultCursor.java:633):cost=0 O-count=1:wt.pds.BasicResultCursor.getNextResultSet(BasicResultCursor.java: 683):cost=0 | O-count=1:wt.pds.BasicStatementBuilder.getStatement(BasicStatementBuilder. java:236):cost=0 | O-count=1:wt.pom.WTConnection.prepareStatement(WTConnection.java:433): cost=0 | O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java: 159):cost=0 | O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java: 134):cost=0 | O-count=1:wt.util.TraceTimingThreadedLogger.addEndEntry (TraceTimingThreadedLogger.java:208):cost=0 | '-count=1:DB PREPARE:cost=0 O-count=1:wt.pds.BasicResultCursor.getNextResultSet(BasicResultCursor.java: 705):cost=0 O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java: 159):cost=0 O-count=1:wt.util.TraceTimingHelper.addEndEntry(TraceTimingHelper.java: 134):cost=0 O-count=1:wt.util.TraceTimingThreadedLogger.addEndEntry (TraceTimingThreadedLogger.java:208):cost=0 '-count=1:SELECT 'wt.epm.workspaces.EPMWorkspace', FROM EPMWorkspace A0 WHERE ((A0.idA3M5 = ?)) AND (A0.markForDeleteA2 = ?):cost=0

Every new query comprises three phases: 1. DB PREPARE 2. EXECUTE 3. FETCH The sample above shows a count of 157 that is comprised of 1 Prepare, 1 Execute and 155 rows fetched. The cost field is milliseconds it took 16 ms to execute this query.

D-4

Windchill Customizers Guide

E
Additional Topics - Client Customization

This appendix provides additional procedures for performing client customizations. These procedures are not expected to be commonplace, but may be useful in advanced customization scenarios. Topic Page

Launching a DCA Wizard From a JSP Page...................................................... E-2 Embedding a DCA Page in a JSP to Use as a Main Page .................................. E-3 Defining Non-JSP Actions to be Executed From a JSP Page ........................... E-3 URLFactory in the JSP Environment................................................................. E-7 Using File-Handling Applets in Non-JSP Clients............................................ E-15

E-1

Launching a DCA Wizard From a JSP Page


When you have a new wizard written in DCA that you want to launch from a JSP page, you can create a URLActionDelegate with a URL() method that will return the appropriate URL (see Assignment of URL When renderType="PDM" on page E-5. For example:
public String URL( Object object ) throws WTException { String gwUrl = null; if (enableable(object).booleanValue()) { try { ReferenceFactory rf = new ReferenceFactory( ); String oidStr = rf.getReferenceString( ( Persistable )object); URLFactory urlFactory = getState().getURLFactory(); HashMap map = new HashMap(); map.put("alias"," com.ptc.windchill.esi:transactions "); map.put("ufid", oidStr); gwUrl = urlFactory.getURL("/wtcore/jsp/com/ptc/core/ca/web/gw/gw.jsp", map); //this next call will wrap the url with a javascript function to open the page in a new window. gwUrl = WindowUtils. getLaunchWindowURLWrapper (gwURL,"DCA page",700,550); } catch (Exception e) { throw new WTException(CLASSNAME + ".URL() - exception creating link to " + "DCA page"); } } return gwUrl; }

E-2

Windchill Customizers Guide

Embedding a DCA Page in a JSP to Use as a Main Page


When creating a new main page using DCA, you will need to embed that page in an IFRAME if you want to connect the page to a tab or sub tab. The Advanced Search page uses this technique. Within the JSP page, add an IFRAME HTML tag element and specify the DCA URL as the src:
<%@ include file="/netmarkets/jsp/util/begin.jspf"%> <IFRAME src="/wtcore/jsp/com/ptc/core/ca/web/gw/gw.jsp?<DCA page parameters>" name="window name" frameborder="0" width="100%" > </IFRAME> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

When your custom tab is selected, the DCA page will be presented in a frame under the tab.

Defining Non-JSP Actions to be Executed From a JSP Page


Actions that will be executed from a page built using the Windchill JSP framework must be defined in the file <Windchill>/codebase/actions.xml. Each object type needs a defined element (i.e., using <objecttype></objecttype>). Within this element is entered each of the actions that may be available for this type of object. The name specified for this element is used as an alias for a fully qualified class name. The class attribute is the fully qualified class name for the object type. The files <Windchill>/codebase/action_*.properties are complementary to actions.xml, containing entries for things such as labels, tooltips, and icons to use for the actions based on a certain locale. Below is a snippet from the actions.xml file used in R7.0. These actions are used for the Site tab and its sub-tabs.

Additional Topics - Client Customization

E-3

<objecttype name="site" class="com.ptc.netmarkets.site"> <action name="view" checkaccess="true" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listOrgs" checkaccess="true" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listFiles" checkaccess="true" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listAdmin" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listTypes" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listTemplates" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="listUtilities" enabledwhensuspended="true"> <command windowType="page"/> </action> <action name="site_audit_Reports" enabledwhensuspended="true"> <command windowType="page"/> </action> </objecttype>

Default Assignment of URL


The URL associated with an action is determined in one of several ways, depending on how that action is registered in the actions.xml file. The default mechanism maps the action to a URL of the form:
http://<hostname>/<webapp>/netmarkets/jsp/<type>/<action>.jsp

where <type> and <action> are, respectively, the names of the objecttype and action specified in actions.xml. For example, above is an action with name="view" defined under an objecttype with name="site". Since a renderType attribute is not specified in the action element, the URL
http://<hostname>/<webapp>/netmarkets/jsp/site/view.jsp

is assigned to this action. The corresponding JSP file is


<Windchill>/codebase/netmarkets/jsp/site/view.jsp

If you want to override this default you can specify a value of GENERAL, GENERAL_WITH _CONTEXT, or PDM for the renderType on the action.

E-4

Windchill Customizers Guide

Assignment of URL When renderType="GENERAL" or "GENERAL_WITH_CONTEXT"


For renderType="GENERAL", the method attribute of the command element is used to specify the JSP file to use. For example, if the view action above were defined as follows:
<action name="view" renderType="GENERAL"> <command windowType="page" method="/wtcore/jsp/customizedAction.jsp"/> </action>

then the produced URL would be


http://<hostname>/<webapp>/wtcore/jsp/customizedAction.jsp

with
<Windchill>/codebase/wtcore/jsp/customizedAction.jsp

as the corresponding JSP file. You can use renderType="GENERAL_WITH_CONTEXT" in the same fashion; the difference is that the dynamically-generated URL will include the context object OID.

Assignment of URL When renderType="PDM"


In contrast, renderType="PDM" can be used to indicate that the action generates a template processing or DCA page, and therefore you are using a URLActionDelegate to generate the URL to be assigned to the action. In this situation, the action name must map to a URLActionDelegate entry in a properties file. For example, below is an action entry for creating a document.
<action name="CREATEDOCUMENT1" renderType="PDM"> <command windowType="popup" method="CREATEDOCUMENT1"/> </action>

The URLActionDelegate (CreateDocumentURLActionDelegate) that produces the PDMLink URL to the Create Document wizard is identified in the properties file <Windchill>/codebase/com/ptc/windchill/pdmlink/doc/doc.properties in the following manner:
wt.services/svc/default/wt.enterprise.URLActionDelegate/CREATEDOCUMENT1 /java.lang.Object/0=com.ptc.windchill.pdmlink.doc.server.processors .CreateDocumentURLActionDelegate/duplicate

The selector for this action, CREATEDOCUMENT1, corresponds to the method attribute of the command element in the actions XML definition. This should be identical to the name of the action. In the above example, the type is specified in the property entry as java.lang.Object. This means you do not need to specify a class attribute on the command element -- the default is java.lang.Object.

Additional Topics - Client Customization

E-5

In some cases, you may need to specify the class to find the appropriate URLActionDelegate. Suppose you wanted to use a URLActionDelegate whose property entry is defined as follows:
wt.services/svc/default/wt.enterprise.URLActionDelegate/list2 /wt.pdmlink.PDMLinkProduct/0=com.ptc.windchill.pdmlink.templateutil.server .processors.DefaultProjectLinkURLActionDelegate/duplicate

Then your action element should specify a class:


<action name="list2" renderType="PDM"> <command class="wt.pdmlink.PDMLinkProduct" method="list2" windowType="page"/> <access name="read"/> </action>

If you didnt specify the class in the command element of the action, there is no guarantee that this property entry will be determined as the best match. This is because the list2 action is provided when the user has not yet viewed a Product, so they dont have a context set. Therefore, Windchill cant dynamically determine the class to use for the lookup. By specifying the class in the command element of the action, Windchill can match it to the appropriate property entry.

actions.xml Elements
Listed in the following table are the valid elements and their attributes that can be used to register an action.
Value (Default if not specified)

Element objecttype

Attribute

Required

Description

name class

Yes No

NA NA

A unique name for the alias to use for the object type. The fully qualified path to the actual class representing this type A unique name for the given objecttype to identify the action Indicates to execute the checkAvailable() method on the class specified for the objecttype Indicates if this action is valid only within the Wildfire Embedded Browser. Indicates what mechanism is used to determine the URL.

action

name checkaccess

Yes No

NA true/false

cad

No

true/false

renderType

No

<novalue>/GENERAL/P DM

E-6

Windchill Customizers Guide

command

windowType

No

page/popup/ no_content/normal NA

Indicates if the action will open a new window or replace the page in the current window Indicates the command class to use for this action if the action is a PJL action or the class to use in the lookup of the appropriate URL action delegate if the action renderType is PDM. The method to call on the command class if the action is a PJL action or the selector to use in the lookup of the appropriate URL action delegate if the action renderType is PDM. Indicates what level of access of the user should have to be able to execute this action.

class

No

method

No

NA

access

name

No

read/update/full

URLFactory in the JSP Environment


See The URLFactory in the Generic UI Customizations chapter on page 9-24 for more information on the URLFactory. There are several discrete steps required to utilize the URLFactory in the JSP environment. 1. Create a URLFactory Bean to be used for a given scope. 2. Setup the reference point for all HREFs (from a request, Base Tags, or fully qualified). 3. Create HREFs. Note: There is a URLFactoryBean created by begin.jspf : urlFactoryBean.getFactory().

Creating an URLFactory
All Windchill Java client Server Pages or Servlets should set the context by using the WTContextBean using the code below:
<% [ ] /*** The WTContextBean is a JavaBean for use in Java Server Pages or Servlets that wish to use Windchill Java client or server APIs ***/ % [ ]> <jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request"

Additional Topics - Client Customization

E-7

<jsp:setProperty name="wtcontext" property="request" value="<% [ ]=request% [ ]>"/> </jsp:useBean>

Next, an URLFactory instance may be created for the current codebase by using the useBean JSP command and setting the scope of the URLFactory (in this case for the request, which supports JSP include commands).
<% [ ] /*** The URLFactory is a JavaBean for use in the generation of HREFs used in Windchill HTML clients ***/ % [ ]> <jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" />

If a remote codebase needs to be accessed (note the request from the server) an URLFactory object can be instantiated by first creating the bean as above, and then recreating the URLFactory pointing it to the new codebase. (NOTE: The codebase ends with a / marking it as a directory.)
<% [ ] /*** The URLFactory is a JavaBean for use in the generation of HREFs used in Windchill HTML clients ***/ % [ ]> <jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" > <% [ ] url_factory = new wt.httpgw.URLFactory ( SomeURLToRemoteWindchill ); % [ ]> </jsp:useBean>

Setting the JSP Reference Point


The URLFactory needs to be informed of the current location, or way in which HREFs are to be generated. This can be done using three methods; 1. Setting the context to the current request (Recommended) 2. Setting the BaseTag in the page so that all HREFs are relative to the BaseTag 3. Forcing all HREFs to be fully qualified

Current Request Context


This is the recommended approach for developers. What needs to be done is to set the RequestURI of the URLFactory to be the request URI that was sent to the WEBServer. This will properly support reverse proxy configurations and firewalls. To configure URLFactory for this, utilize the setRequestURL method.
<% [ ] url_factory.setRequestURL(request.getScheme() ,request.getHeader("HOST"),request.getRequestURI()); % [ ]>

Setting a BaseTag
This configuration has the advantage of allowing a user to reload a page after it has been persisted (say to a local file system) and still have all the links work properly. If the base is to be the Windchill Codebase then a call to setRequestURItoBase() will suffice.
<BASE HREF="<% [ ]= url_factory.setRequestURItoBase() % [ ]>">

E-8

Windchill Customizers Guide

However in many situations, you may wish to set the base tag relative to some point in the Windchill codebase. An example is you want to generate a search page and have all the links be relative to some starting position. In this case, a little more is involved. If you can obtain the current request context (i.e., you are developing either a jsp or servlet page) then first you should set the request information using the setRequestURL() method described above.
Setting the BaseTag Within JSP pages and Servlets
<% [ ] // First set the request URI to be relative to the request (thus maintaining // the protocol, port and host information. url_factory.setRequestURL(request.getScheme(), request.getHeader("HOST"), request.getRequestURI() ); // Next set the request URI to be null (ie. to the Windchill codebase) url_factory.setRequestURI(null); // Now set the request URI to be relative to the resource you desire. url_factory.setRequestURI("wt/clients/login/ Login.html"); // Now the Base tag can be set to this resource % [ ]> <BASE HREF="<% [ ]=url_factory.getFullyQualifiedRequestURI ()% [ ]>">

Setting the BaseTag Within a Non-JSP Page or Servlet (i.e, Java code)

We will not have access to the request object in Java code that is not a servlet. Therefore we have to set the RequestURI to be relative to initially the Windchill codebase based on the configured host, protocol and port information and then set the requestURI to desired resource.
... // Set the request URI to the Windchill codebase. url_factory.setRequestURItoBase(); // Now set the request URI to the desired resource. url_factory.setRequestURI("wt/clients/login/Login.html"); // Now we can obtain the string for the Base Tag String baseTag = url_factory.getFullyQualifiedRequestURI();

Forcing all HREFs to be Fully-Qualified


If there is a need to force fully qualified HREFs (such as the current configuration) this can be accomplished using the following;
<% [ ] url_factory.setRequestURI( (java.lang.String)null ); % [ ]>

Generating Links on the Page


There are five types of HREFs used in the Windchill Environment.

Additional Topics - Client Customization

E-9

1. Standard resources located under the codebase. 2. Access to a Windchill Servlet via a Gateway (for example Authenticated Gateway) 3. Access to an external source 4. Forcing a fully qualified link with a URLFactory that has a non-null request URI 5. Creating a link from the request.getRequestURI() String

Standard Resources Under the Codebase


In order to generate links on the page, simply calling getHREF(resource) from URLFactory will create relative HREF Strings for the desired resource base on the RequestURI that was set earlier. The resources are all designated relative to the Windchill Codebase. For example, to obtain a link for Login.html located in wt/clients/login, the following line could be used:
<A HREF="<% [ ]= url_factory.getHREF( "wt/clients/login/Login. html" ) % [ ]>"> Link to Login.html </A>

Depending on the Request Context setup above, the correct HREF String will be returned and inserted into the output page at compile time.

Access Through a Servlet


In order to generate links via a Windchill Servlet the appropriate ServletHelper class should be referenced. There are ServletHelpers available for the Anonymous / Authenticated Gateways (WindchillGW / WindchillAuthGW), and also for the UIServlet and System Administrator (WindchillSAGW). See the GatewayServletHelper class entry in your installed Windchill Javadoc for more information.
<A HREF="<% [ ]= wt.httpgw.GatewayServletHelper. buildAnonymousHREF( url_factory, "wt.httpgw.HTTPServer", "echo", (java.lang.String)null ) % [ ]>">Windchill Echo</A>

Access to an External Source


To generate a link to an external source, simply make a call to getHREF as in example 1, except explicitly define the HREF to the resource you want. Whenever possible calls for external HREFs should be made through URLFactory to take advantage of possible future features.
<A HREF="<% [ ]= url_factory.getHREF( "http://www.ptc.com" ) % [ ]>"> Link to PTCs Website</A>

E-10

Windchill Customizers Guide

Forcing a Fully Qualified Link With a URLFactory that has a Non-null Request URI
If you want to create a link that opens a file in a new window (such as through the Javascript.open( ) method) the string must be fully qualified. However, the rest of the links on the page may be relative. Most getHREF() methods have a form which accepts a boolean. By using this form, it is possible to request a fully-qualified URL from a URLFactory which is otherwise configured to generate relative URLs.
<A HREF="<% [ ]= url_factory.getHREF( "wt/clients/login/Login.html" , true ) % [ ]>">Fully Qualified Link</A>

Creating a Link From the Request.getRequestURI() String

This only applies to servlets and JSP Pages. The request object has a method getRequestURI( ) which returns the path to the web resource (usually starting after the hostname/port onward). This String includes a leading / which by definition in the URLFactory would redefine the resource and not create a relative link. However, there is a chance to create a relative link if the getRequestURI( ) path and the Windchill codebase are common. This is where usage of the determineResource( ) method may be used.
<A HREF="<% [ ]= url_factory.getHREF( url_factory.determineResource(request.getRequestURI()))% [ ]>" > Resource Link</A>

Internationalizing JSP Pages in Windchill


With the introduction of JSP and new browser technology, it is no longer necessary to use separate encodings for each language. Instead, a single encoding: UTF-8 can be utilized. All JSP Pages in the Windchill environment should be written to utilize UTF-8 as their character set. This will allow a single JSP Page to be deployed for any language variant. (Previous versions implemented separate language versions for all HTML templates.)

International Encoding on JSP Pages


There are two steps that are needed to develop pages properly using UTF-8. 1. To set the content type of the current page that is being processed within the JSP Parser. The JSP page directive needs to be called with the content type being set.
<% [ ]@ page contentType="text/html; charset=UTF-8"% [ ]>

2. Set the response content type. This will set the encoding of the HTML page returned to the client. It should be set near the start of the JSP page (after Bean declarations). In order to do this the following needs to be added:
<% [ ] response.setContentType( "text/html; charset=UTF-8" ); % [ ]>

Additional Topics - Client Customization

E-11

Note: The response content type method must be called before any call to request.getParameter() is made.

Decoding UTF-8 Encoded Text


If you set the encoding as explained above, the text your code receives will be encoded using the UTF-8 encoding. However, the Java String class uses 16-bit integers to represent Unicode characters. You need to do the conversion from UTF-8 to Java String in your code.
EncodingConverter

Note: See the EncodingConverter class entry in your installed Windchill Javadoc for more information. The EncodingConverter class (in the wt.httpgw package) contains a series of decode() methods that may be used to efficiently decode text that has been encoded in UTF-8 format. This must be called on ALL text that is read from parameters that were submitted from a FORM element. There are two ways to decode text: The first method is to use the decode() methods of wt.httpgw.EncodingConverter to efficiently decode text that has been encoded in UTF-8 format. This must be called for every text entry that was submitted from a FORM element, or any parameters that contain encoded text. This methodology supports both request query strings and FORM data. For example:
// Create an instance of the encoding converter for the page // EncodingConverter encoder = new EncodingConverter (); // Using the EncodingConverter with the default encoding (UTF-8 ) // String tag = encoder.decode( request.getParameter ("tag") ); // Using the EncodingConverter with a specific encoding // String tag = encoder.decode( request.getParameter ("tag"), "UTF-8");

The second method that can be to used is the parseQueryString() method of the URLFactory() class. Usage of the parseQueryString() method takes an encoded query string and decodes it. The result is placed into a HashMap. The HashMap values may then be queried using the HashMap get method. This method will only work with Request Parameters and not form elements. For example:
// Use the URLFactory to parse the Query String // java.util.HashMap query_map = url_factory.parseQueryString(

E-12

Windchill Customizers Guide

request.getQueryString() ); // Retrieve the (already decoded) string from the hash map // String tag = query_map.get("tag");

Deprecation of WTURLEncoder

As of Windchill release 6.0 WTURLEncoder SHOULD NOT be used for text encoding or decoding. This class may be removed post-R 6.0.

Encoding of Forms
By default POST submitted forms are submitted using the encoding application/xwww-form-urlencoded. The methods provided above for decoding the text will allow these forms data to be written properly. All HREFs and URLs should be generated using the URLFactory class. The URLFactory provides methods to automatically encode any non-ASCII characters in the query string, if a HashMap containing the parameters is provided to the URLFactory. If a string is being passed in for a query string that has been created within your code, you must encode it first, with a call to EncodingConverter.encode() Note: See the URLFactory class entry in your installed Windchill Javadoc for more information.

Sample JSP Page


Below is a sample JSP Page that illustrates how to utilize the URLFactory, and proper UTF-8 encoding with a HTML form. If the file is saved into your Windchill codebase directory as sample.jsp, you can execute this sample. To see the power of this sample try to paste different languages into the text field and then click the button.
<HTML> <% [ ] /*** WTContest bean for Windchill Client ***/ % [ ]> <jsp:useBean id="wtcontext" class="wt.httpgw.WTContextBean" scope="request"> <jsp:setProperty name="wtcontext" property="request" value="<% [ ]=request% [ ]>"/> </jsp:useBean> <jsp:useBean id="url_factory" class="wt.httpgw.URLFactory" scope="request" > <% [ ] // Set the URLFactory to the current page request url_factory.setRequestURL(request.getScheme(), request.getHeader("HOST"), request.getRequestURI()); % [ ]> </jsp:useBean> <% [ ]@ page contentType="text/html; charset=UTF-8" % [ ]> <HEAD> <% [ ] // Set the content type for the response response.setContentType("text/html; charset=UTF-8"); // Get the current locale for the browser that is supported by Windchill // This to used with WTMessage.getLocalizedMessage(RESOURCE,"tagname",locale) java.util.Locale locale = wt.httpgw.LanguagePreference.getLocale(

Additional Topics - Client Customization

E-13

request.getHeader("Accept-Language") ); % [ ]> </HEAD> <BODY> <h1>Sample Form</H1> <% [ ] String text = request.getParameter("sample_text"); if ( text != null ) { % [ ]> Here was the text that was submitted: <i> <% [ ]= url_factory.decode(text) % [ ]> </I> <BR><% [ ]= new String(text.getBytes("ISO8859_1"),"UTF-8")% [ ]> <% [ ] } % [ ]> <P> <FORM METHOD="POST" ACTION="<% [ ]=url_factory.getHREF("sample.jsp",request. getQueryString () ) % [ ]>" > <% [ ] if ( request.getParameter("sample_text") != null ) { % [ ]> <INPUT TYPE="text" NAME="sample_text" VALUE="<% [ ]= url_factory.decode( text) % [ ]>"> <% [ ] } else { % [ ]> <INPUT TYPE="text" NAME="sample_text" > <% [ ] } % [ ]> <INPUT TYPE="submit" NAME="button" VALUE="click here"> </FORM> </BODY> </HTML>

Localizable text on JSP pages


Any displayed text should be obtained from ResourceBundles or RbInfo files that are language specific as defined by the Internationalization/Localization techniques located here. IMPORTANT: you must not hard-code localizable text directly on the JSP page! This would ruin the whole concept of having languageindependent JSP pages. Whenever text needs to be displayed on a JSP page, it should be pulled in during runtime from an RbInfo file.

E-14

Windchill Customizers Guide

Using File-Handling Applets in Non-JSP Clients


For more UI flexibility and more robust handling of file upload/download/ selection than is available through straight HTML, a basic set of lightweight filehandling applets has been provided. These applets can be used in a variety of HTML-generating architectures, including DCA and HTML template processing, and can be used with a variety of Windchill business objects.

The Three Applets


File selection applet

<Windchill>/codebase/wt/clients/util/FileChooserDropApplet (combined file drop target and file browser launch button or "hyperlink" which launches single-select or multi-select JFileChooser)
Content upload applet

<Windchill>/codebase/wt/clients/util/http/UploadApplet.java
Content download applet

<Windchill>/codebase/wt/clients/util/http/DownloadApplet.java

Advantages and Disadvantages


The primary advantages of these applets compared to straight HTML are: 1. Multiple-file handling - can handle multiple files in a single select/upload/download operation. 2. Drag-and-drop file selection - can drag and drop one or more files from the desktop or Windows Explorer into a Windchill UI 3. Configurability - can configure file select/upload/download behavior through user preferences. 4. Checksum handling - can persist/compare checksums to avoid unnecessary uploads. 5. Deferred upload and remembered values - can be used to implement multipage wizard or clerk which maintains the selected upload filepaths when switching between pages, and defers all file uploads until all pages of wizard/clerk are completed. 6. Pre-fillable file selection values - ability to update a previously-uploaded file without needing to re-browse for local filepath. The primary disadvantages of these applets compared to straight HTML are the necessary installation prerequisites for each user. 1. Plug-in - they require the one-time installation of a particular Java plug-in on the client machine. 2. Bootstrap loader - for certain secure server configurations, they require the one-time installation to the client machine of the Windchill bootstrap loader

Additional Topics - Client Customization

E-15

which enables the RMI tunneling necessary for the applet to communicate with the server 3. Java class archive - they require the one-time download of a Java class archive, which creates a noticeable loading delay the first time an applet is accessed from a given client machine. Subsequent visits to the same page are much faster because the class archive is cached locally by the Java plug-in.

The File Selection Applet File Selection


There are two ways to choose one or more files for upload in Windchill. 1. File Browse: Launch a file browser from the Windchill UI and navigate to the desired file(s). 2. Drag-and-Drop: Drag one or more file icons from the desktop or Windows Explorer onto a drop target in the Windchill UI.
File Browse Launchers

There are two looks for the applet button that launches a Java file browser. The "button" look is typically used in a single-select situation where the selected file will be written to an adjacent HTML textfield, in order to look and act like an HTML file input (only smarter!).

Button look:
<param name="buttonLook" value="true">

The "hyperlink with icon" look is typically used in a multi-select situation where each selected file will result in another row added to a table.

E-16

Windchill Customizers Guide

Hyperlink-with-icon look:
<param name="buttonLook" value="false"> <param name="imageFilename" value="wtcore/images/attach_add.gif"> <param name="multiSelect" value="true">

Drag-and-Drop targets

The presence/absence of a file drop target next to the file browse launcher is determined by the following parameter (true means drop target, false means no drop target):
<param name="acceptFileDrop" value="true">

When using a drop target, you will need to provide a pair of images to use for the drop target's normal state and active (dragged-over) state. The following images are provided by Windchill for this purpose:
Normal:
<Windchill>/codebase/wtcore/images/droptarget.gif

Additional Topics - Client Customization

E-17

Active:
<Windchill>/codebase/wtcore/images/droptarget_active.gif

Processing File Selection Output


The file selection applet will output the selected filepaths to the page by calling a Javascript method of specified signature: setPath (newValue, fileSep, pathComplete). The name of the method may be changed by setting an applet parameter, but the number and type of arguments must conform to the applet's expectations (see examples). For single-select situations, the Javascript method typically takes the result string from an applet, verifies that only a single file has been selected, then calls another method that writes the filepath to a form field. For multiple-select situations, the Javascript method typically takes the result string from an applet, then calls another method that performs parsing and/or concatenation on the result string in order to update hidden field values and submit the page to some sort of processor that generates an additional row in the table for each file selected. Various browser and encoding issues may affect handling of the backslash file separators in Windows filepaths. Some sort of escaping or replacement of these file separators is recommended, such as is performed by the method CheckFilePathSeparators in the file <Windchill>/codebase/templates/doc/WTDocumentSharedFunctions.js.

Sample Single-Select Javascript for FileChooserDropApplet


var DELIM = ";;;qqq"; // same as applet's delim parameter var appletString = ""; function setPathFromApplet(newValue,fileSep,pathComplete) { appletString = appletString + newValue; if ( pathComplete != null && pathComplete == "true" ) { window.focus(); var endPos = newValue.indexOf( DELIM, 0 ); if ( endPos >= 0 ) { wfalert( tooManyFilesDroppedMsg ); } else { setPath(CheckFilePathSeparators(appletString,fileSep)); } appletString = ""; } }

E-18

Windchill Customizers Guide

Sample Multi-Select Javascript for FileChooserDropApplet


var DELIM = ";;;qqq"; // same as applet's delim parameter var appletString = ""; function setPath(newValue,fileSep,pathComplete) { appletString = appletString + newValue; if ( pathComplete != null && pathComplete == "true" ) { window.focus(); submitNewAttachments(CheckFilePathSeparators(appletString,fileSep) ); appletString = ""; } }

Configuring File Select Behavior - User Preferences


The Default Local Directory preference (node=/wt/content key= workspacePath) determines where the file browse dialog will initially be launched. Users who have a particular directory where they like to keep all their Windchill files might like to set this preference to that directory. If no value is specified, or if the specified path does not exist on the local machine, then a default directory will be used as specified by the environment variables of the local machine's operating system.

Additional Topics - Client Customization

E-19

FileChooserDropApplet Parameters
Parameter Name java_codebase type java_code cache_archive Sample Value http://machinename.ptcnet.ptc.com/Windchill/ application/x-java-applet;version=1.4 wt/clients/util/FileChooserDropApplet "contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" wt/security/security.jar wt/security/security.cab Plugin true true en_US 15066585 Description Provided by taglib generator Provided by taglib generator Applet location in codebase never changes Java archives containing the classfiles used by this applet typically never changes Never changes Never changes Never changes Never changes Never changes Locale of users browser Decimal version of desired background color (i.e. what is seen around the button), typically matches the background color of the page or table cell where the applet is located (Optional) Decimal version of desired background color (i.e. what is seen around the button) when button is active. Defaults to same as bgcolor. (Optional) Decimal version of desired button color. Defaults to same as bgcolor. (Optional) Decimal version of desired button color when button is active. Defaults to same as bgcolor. (Optional) Name of Javascript method to be invoked from applet with the selected filepath value(s). Defaults to "setPath". Label for button or "hyperlink" seen in HTML page

java_archive cabinets cache_option SCRIPTABLE MAYSCRIPT wt.context.locale bgcolor

bgcoloractive

15066585

buttoncolor

13421772

buttoncoloractive

15066585

jsSetMethod

setPathFromMultiSelectApplet

buttonLabel

"Browse... ", "Add Attachments... ", "Add Files... "

E-20

Windchill Customizers Guide

acceptFileDrop dropImageFilen ame


dropImageFilena meActive buttonLook

true, false wtcore/images/droptarget.gif


wtcore/images/droptarget_active.gif true, false

Normally true, change to false if you dont want a drop target Image displayed when drop target is idle
Image displayed when drop target is dragged-over Normally true for single-select usage, normally false for multiselect usage (Optional) Icon shown above "hyperlink" if buttonLook is false (Optional) Label for window and action button on file browser dialog (Optional) Normally retrieved from workspacePath user preference setting, determines where file browse dialog initially launches. (Optional) Defaults to false for single-select, change to true for multi-select. (Optional) Delimiter string used to separate filepaths if multiSelect is true (Optional) Defaults to false, change to true for Java Console output during processing

imageFilename actionLabel defaultPath

wtcore/images/attach_add.gif "Open", "Choose File", "Select Attachments" C:/temp/MyWindchillFiles/

multiSelect

true, false

delim

;;;zzz

debug

true, false

Sample HTML for FileChooserDropApplet


Single-select, button look (Create/Update/Checkin Document primary content)
<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="200" height="40" codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windowsi586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/FileChooserDropApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="SCRIPTABLE" value="true"> <param name="actionLabel" value="Open"> <param name="debug" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="dropImageFilenameActive" value="wtcore/images/droptarget_active.gif"> <param name="buttonLabel" value="Browse...">

Additional Topics - Client Customization

E-21

<param name="acceptFileDrop" value="true"> <param name="MAYSCRIPT" value="true"> <param name="buttonLook" value="true"> <param name="cabinets" value="wt/security/security.cab"> <param name="dropImageFilename" value="wtcore/images/droptarget.gif"> <param name="cache_option" value="Plugin"> <param name="wt.context.locale" value="en_US"> <param name="bgcolor" value="15066585"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="200" height="40" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/FileChooserDropApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" SCRIPTABLE="true" actionLabel="Open" debug="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" dropImageFilenameActive="wtcore/images/droptarget_active.gif" buttonLabel="Browse..." acceptFileDrop="true" buttonLook="true" cabinets="wt/security/security.cab" dropImageFilename="wtcore/images/droptarget.gif" cache_option="Plugin" wt.context.locale="en_US" bgcolor="15066585" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Multi-select, hyperlink-with-icon look (Create/Update Document attachments, Create Multiple Documents)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="300" height="50" codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windowsi586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/FileChooserDropApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="SCRIPTABLE" value="true"> <param name="actionLabel" value="Open"> <param name="debug" value="false"> <param name="delim" value=";;;zzz"> <param name="multiSelect" value="true"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="dropImageFilenameActive" value="wtcore/images/droptarget_active.gif"> <param name="acceptFileDrop" value="true"> <param name="buttonLabel" value="Add+Attachment"> <param name="MAYSCRIPT" value="true"> <param name="imageFilename" value="wtcore/images/attach_add.gif"> <param name="cabinets" value="wt/security/security.cab">

E-22

Windchill Customizers Guide

<param name="dropImageFilename" value="wtcore/images/droptarget.gif"> <param name="cache_option" value="Plugin"> <param name="wt.context.locale" value="en_US"> <param name="bgcolor" value="15066585"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="300" height="50" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/FileChooserDropApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" SCRIPTABLE="true" actionLabel="Open" debug="false" delim=";;;zzz" multiSelect="true" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" dropImageFilenameActive="wtcore/images/droptarget_active.gif" acceptFileDrop="true" buttonLabel="Add+Attachment" imageFilename="wtcore/images/attach_add.gif" cabinets="wt/security/security.cab" dropImageFilename="wtcore/images/droptarget.gif" cache_option="Plugin" wt.context.locale="en_US" bgcolor="15066585" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

The Upload Applet


UploadApplet is an "invisible" applet, that is, a 2-pixel by 2-pixel applet whose background color matches the page. It starts the upload as soon as the page has loaded and the applet has initialized, using the values in the applet parameters. This behavior makes UploadApplet most appropriate for use in a "processing" page or popup rather than an interactive form page. In order to perform an upload, the applet needs to know what content item to upload and an upload destination where it should be uploaded. The item is described by a target type (FILE, URL or NONE) and a target. Items of type FILE have a filepath as a target, items of type URL have a URL string as a target. The upload destination is described by an upload destination URL. The only Windchill-supported use of UploadApplet is to upload content to an upload URL that leads to the saveContent method of the wt.content.ContentHttp class in the Windchill Method Server. Caution: While it may be possible to use UploadApplet to upload content to some other type of upload URL, such as an Info*Engine URL or even a totally non-Windchill URL, any such "off-label" use of UploadApplet is NOT considered supported by Windchill's tech support or R & D.

Additional Topics - Client Customization

E-23

Initial Upload of Primary and/or Secondary Content to a Single Windchill Object


When initially uploading to a Windchill object, such as during a Create Document or Create Document Template, or when updating a Windchill object which has not previously had content, there is no existing Windchill content item yet in the database so a new content item object will have to be created. This is indicated for primary content by setting the callingAction parameter to "create", and for secondary content by indicating "newfile" in place of the OID within the concatenated attachments parameter.

Initial Upload of Multiple Primary Files to Multiple Windchill Objects


When creating multiple documents, multiple primary files can be uploaded to multiple destinations with a single instance of UploadApplet. This is done by setting the "target" parameter to a concatenated list of target filepaths, and setting the "uploadURL" parameter to a concatenated list of uploadURLs corresponding in quantity and order to the concatenated "target" values.

Subsequent Upload to Update/Replace/Remove Content of a Windchill Object


When uploading to a single Windchill object that already has content, the aboutto-be-uploaded primary file needs to be validated and compared to the currentlypersisted primary content item, to avoid unnecessary uploads. This is indicated by setting the callingAction parameter to "updateReplace" and providing persisted filename and checksum information about the existing content item. The result of the validation/comparison, along with certain user preference values, determines whether to upload the file, skip the upload, or prompt the user for an upload decision or different filepath. (Secondary content is validated but no comparisons are performed.) Existing content items, both primary and secondary, need to have their OID provided so that the upload modifies the content of the existing content item rather than creating an additional content item. When removing primary or secondary content, the OID needs to be provided so that the correct existing content item can be removed. This is indicated for primary content by setting the oidString parameter to the OID of the current primary content item, and for secondary content by providing the OID of the to-be-removed-or-replaced attachment content item within the concatenated attachments parameter. Caution: The OID must be in the format of "wt.content.ApplicationData:1437923". Attempting to use an OID with a different format, such as "OR:wt.content.ApplicationData:1437923", will result in server-side failure to persist the uploaded object.

Handling Success/Error Navigation and Feedback on Uploads


To enable UploadApplet to be used in a variety of architectures/situations but maintain feedback behavior and language appropriate to each usage, UploadApplet allows the parameters and the page Javascript to define the appropriate feedback display handling and post-upload navigation.

E-24

Windchill Customizers Guide

When uploading to a single location, the selected primary content filepath is validated, preference values are checked and the user is prompted if necessary to decide what to do should the selected filepath be invalid. If the file is valid or the preferences and/or user prompt authorize skipping the upload, then the upload is considered successful, and the applet will forward to the "completionUrl" and/or "completionJSMethod" upon completion (if both are provided, completionUrl will be passed into completionJSMethod as an argument value). In Windchill Foundation & PDM, this typically submits to post-processing code followed by the properties page for the document. In Windchill PDMLink, this typically submits to post-processing code followed by closing the wizard window. In the absence of both completionUrl and completionJSMethod parameter values, completionJSMethod will default to "displayInvalidPaths". Note: The "uploadFeedback" argument provided to the completionJSMethod will be a value from the class wt.clients.util.http.UploadConstants indicating whether some kind of non-upload completion was reached (NO_UPLOAD, FILE_NOT_FOUND, FILE_UNCHANGED, DECLINED_UPLOAD). This can be used for customizing a feedback status message for a non-error outcome. If the file is invalid and the preferences and/or user prompt do not authorize skipping the upload, or if the file is valid but the upload is unsuccessful, or if the user cancels, then the applet will forward to the "failureUrl" and/or "failureJSMethod" (if both are provided, failureUrl will be passed into failureJSMethod as an argument value). This typically displays some sort of error feedback message (unless cancelled) and returns to the form where the primary filepath was originally selected. When performing a multiple-file upload, such as multiple primary files or attachments, individual feedback is not provided on each file. Instead, all valid files are uploaded and a list of all invalid filepaths is compiled. When the upload is complete, this list of invalid filepaths is sent as an argument to a designated Javascript method, along with the appropriate URL. When uploading multiple primary files, this will always be the Javascript method and URL specified in the applet parameters for the completion case. When uploading secondary files, the method and URL may be from either the completion or failure cases, depending on the outcome of the selected primary content file upload.

Sample Javascript for UploadApplet Feedback and Navigation


Note: This Javascript assumes the existence of a hidden HTML form in the page named <form name>, containing named hidden fields <checksum form field name> and <uploadFeedback form field name>. The real names of this form and these fields should be substituted into this Javascript before use.
<SCRIPT language=javascript> // localized display messages retrieved from resource bundles

Additional Topics - Client Customization

E-25

var invalidPathMessage = "The following files were not uploaded due to invalid filepaths:"; var uploadFailureMessage = "A problem occurred while uploading content to server. Please notify administrator if this problem continues."; function uploadCompleted( invalidPaths, nextURL, newChecksum, uploadFeedback ) { document.<form name>.<checksum form field name>.value = newChecksum; if ( uploadFeedback != null && uploadFeedback.length > 0 ) { \document.<form name>.<uploadFeedback form field name>.value = uploadFeedback; } if ( invalidPaths != null && invalidPaths.length > 0 ) { alert( invalidPathMessage + invalidPaths ); } if ( nextURL != null && nextURL.length > 0 && nextURL != "null" ) { submitForm( nextURL ); } else { submitForm( propertiesPageURL ); // generated value } } function uploadFailed( invalidPaths, nextURL, cancelled ) { if ( invalidPaths != null && invalidPaths.length > 0 ) { alert( invalidPathMessage + invalidPaths ); } if ( !cancelled ) { alert( uploadFailureMessage ); } if ( nextURL != null && nextURL.length > 0 && nextURL != "null" ) { submitForm( nextURL ); } else { submitForm( previousPageURL ); // generated value } } function displayInvalidPaths( invalidPaths, nextURL ) { alert( invalidPathMessage + invalidPaths ); location = nextURL; } </SCRIPT>

Persisting Information After an Upload


When uploading to a single document, the primary file checksum should be persisted after a successful upload, for use in future upload comparisons. To minimize network traffic, the checksum is appended to the end of the completionURL query string so that it can be processed in the same server hit as the request for the completion page. The server-side delegate or JSP that handles the completionURL request should check whether the "uploaded" flag on the query string is set to "true", and if so should persist the "checksum" query string value to the context object's primary content item.

E-26

Windchill Customizers Guide

Checksum persistence code:

Here are the essential steps for persisting the checksum (in reality, there may also be some error handling). The context object has to be a FormatContentHolder, such as a WTDocument.
Properties props = getQueryData(); String uploaded = (String)props.get("uploaded"); if ( uploaded != null && uploaded.equalsIgnoreCase("true") ) { long checksum = 0; checksum = Long.parseLong((String)props.get("checksum")); FormatContentHolder holder = (FormatContentHolder)getContextObj(); holder = (FormatContentHolder)ContentHelper.service.getContents(holder); ContentItem item = ContentHelper.getPrimary( holder ); if ( item instanceof ApplicationData ) { ApplicationData app = (ApplicationData)item; app.setChecksum( checksum ); ContentHelper.service.updateAppData( holder, app ); } }

Configuring Upload Behavior - System Properties


The optional "validEmptyFile" and "uploadImpl" applet parameters are typically set by retrieving the wt.properties values for "wt.content.validEmptyFile" and "wt.content.uploadImpl", respectively. The validEmptyFile parameter allows a particular implementation to determine whether or not a 0-size "empty" file is considered a valid content file or not - the default value is "false", that an empty file is not considered valid. This value typically will not be changed unless Windchill is being used to automate data storage from some other application that generates 0-size placeholder files. The uploadImpl parameter permits switching between RMI and HTTP upload mechanisms - the default value is "rmi" which provides full-functionality Windchill upload including full support of file vault caching and content replication. The other alternative is "http" which permits uploading to a nonWindchill URL but has severe limitations in both functionality and performance. This value typically will not be changed at the wt.properties level due to loss of functionality, but can be overridden at the page level by setting the applet parameter to allow an isolated unsupported instance of UploadApplet uploading to a non-RMI upload URL, without losing the RMI upload functionality in all other instances of UploadApplet. Caution: Changing the value of the wt.content.uploadImpl wt.properties value or uploadImpl applet parameter away from the default value is possible but is NOT officially supported - use at your own risk.

Additional Topics - Client Customization

E-27

Configuring Upload Behavior - User Preferences


The upload applet knows how to compare the new primary content filepath with the previously-persisted filename/checksum, and how to make sure the new filepath is valid, but the resulting behavior is determined by parameters that are typically set by the individual user's preferences. The Changed File Behavior preference (node=/wt/content key= uploadIfFileChanged) determines whether changes to the primary file are automatically uploaded, or whether the user wants to have the option to accept the upload or not. Most users will prefer to automatically upload a changed file without prompting, but some users who frequently do updates and checkins for metadata or attachments reasons might prefer the ability to be prompted in case the changes they're making to the primary content aren't yet ready to be checked in for others to see. The File Not Found Behavior preference (node=/wt/content key=continueIfFileNotFound) determines whether an invalid filepath means a failure condition or not. Most users will prefer to be notified of an invalid filepath so that they can correct the selection, but some users who frequently do updates and checkins for metadata or attachments reasons might set their download preferences to automatically skip the primary content download on checkout and set this upload preference to automatically skip the upload on update/checkin if the primary content file doesn't exist locally. The Unchanged File Behavior preference (node=/wt/content key= continueIfFileUnchanged) determines whether the absence of changes to the primary file automatically means to skip the upload as unnecessary, or whether the user wants to be notified and have the option to skip the upload or select a different primary file. Most users will only have a single local copy of the primary file and thus will prefer to skip the upload if the primary content hasn't changed, but users who routinely edit a copy of the primary content file in a different location or under a different filename might want to have the option to be reminded in case they accidentally attempt to upload the original file rather than the changed file.

E-28

Windchill Customizers Guide

Upload Applet Parameters


Parameter Name java_codebase type java_code cache_archive Sample Value http://machinename.ptcnet.ptc.com/Windch ill/ application/x-java-applet;version=1.4 wt/clients/util/UploadApplet "contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" wt/security/security.jar wt/security/security.cab Plugin true true en_US 16777215 Description Provided by taglib generator Provided by taglib generator Applet location in codebase never changes Java archives containing the classfiles used by this applet Never changes Never changes Never changes Never changes Never changes Locale of users browser Decimal version of desired background color, typically matches the background color of the page or table cell where the applet is located Never changes Local filepath(s) to the new primary content item(s) to be uploaded Category of newly-selected primary content URL(s) to accept the upload, typically leads to saveContent method of wt.content.ContentHttp in the Windchill Method Server Refers to context document create if this upload takes place as part of the initial creation of the document, update if this is a subsequent update or checkin Refers to primary content item create if there is currently no persisted primary content item, updateReplace if there is already a persisted primary content item

java_archive cabinets cache_option SCRIPTABLE MAYSCRIPT wt.context.locale bgcolor

removable target targetType uploadURL

true C:/Temp/MyFolder/Sample.jpg FILE, URL, NONE http://mecasey03d.ptcnet.ptc.com/Windchil l/servlet/WindchillAuthGW/wt.content.Con tentHttp/saveContent?wt.doc.WTDocument %3A656270 create, update

docOperation

callingAction

create, updateReplace

Additional Topics - Client Customization

E-29

oidString attachments

wt.content.ApplicationData:656261 FILE;;;qqqnewfile;;;qqqC:\TEMP\ DgadReq.doc;;;qqqADD;;;zzzURL;;;qqqne wURL;;;qqqwww.amazon.com;;;qqq;;;qqq ADD;;;zzzFILE;;;qqqwt.content.Applicatio nData:656293;;;qqqC:\TEMP\ MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qq qwt.content.URLData:656295;;;qqqhttp://w ww.askjeeves.com;;;qqqAsk Jeeves website;;;qqqREPLACE;;;zzzFILE;;;qqqwt. content.ApplicationData:656902;;;qqq;;;qq qREMOVE;;;zzzURL;;;qqqwt.content.URL Data:656904;;;qqq;;;qqqREMOVE 3 ;;;qqq

On updateReplace, the OID of the persisted primary content item Type, content item OID (if any), filepath/URL, description (if any) and action for any attachments to be added, removed or replaced. Attachments are separated by contentRecordDelim value, individual fields for each attachment are separated by contentDelim value

multipleQuantity contentDelim

(Optional) Number of different primary files/destinations (Optional) Delimiter within attachments entries and between multiple-upload targets/uploadURLs, defaults to ;;;qqq (Optional) Delimiter used between separate attachments entries, defaults to ;;;zzz (Optional) Methodname of Javascript method to be called if upload doesnt error out (Optional) URL to follow if upload doesnt error out

contentRecordDelim

;;;zzz

completionJSMethod

uploadCompleted

completionUrl

"http://mecasey03d.ptcnet.ptc.com/Windchi ll/servlet/WindchillAuthGW/wt.enterprise. URLProcessor/invokeAction?action=Create DocCloseWindow&class=wt.doc.WTDocu ment&OID=VR%3Awt.doc.WTDocument %3A288876&refresh=true&formName=Cr eateDocumentWizard"> uploadFailed

failureJSMethod

(Optional) Methodname of Javascript method to be called if upload errors out (Optional) URL to follow if upload errors out

failureUrl

"http://mecasey03d.ptcnet.ptc.com/Windchi ll/servlet/WindchillAuthGW/wt.enterprise. URLProcessor/invokeAction?nextAction= CreateDocument2&action=CreateDocumen tUploadFailure&class=wt.doc.WTDocume nt&OID=VR%3Awt.doc.WTDocument%3 A288876&uploaded=false&formName=Cr eateDocumentWizard

E-30

Windchill Customizers Guide

checksum

3774325531

(Optional on updateReplace) The checksum from previous upload of persisted primary content item (Optional on updateReplace) The filename of the persisted primary content item (Optional on updateReplace) The filepath from previous upload of persisted primary content item (Optional on updateReplace) Determines whether to automatically skip the upload and keep current primary content if the selected file cannot be found, normally retrieved from user preference setting (Optional on updateReplace) Determines whether to automatically skip the upload and keep current primary content if the selected file has not changed since the previous upload, normally retrieved from user preference setting (Optional on updateReplace) determines whether to automatically upload the file if it has changed since the previous upload, normally retrieved from user preference setting (Optional) Normally retrieved from user preference setting (Optional) Normally false, change to true if you want to permit 0-size files to be considered valid Windchill content (Optional) Defaults to rmi, change to http only for unsupported uses of this applet. (Optional) Defaults to false, change to true for Java Console output during processing

fileName

MyDoc.doc

uploadedFromPath

C:/temp/MyDoc.doc

continueIfFileNotFo und

true, false

continueIfFileUncha nged

true, false

uploadIfFileChanged

true, false

workspacePath validEmptyFile

C:/temp/MyWindchillFiles/ true, false

uploadImpl

rmi, http

debug

true, false

Additional Topics - Client Customization

E-31

Sample HTML for UploadApplet


Create Document (add primary/attachment files to single upload destination)
<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="validEmptyFile" value="false"> <param name="oid" value=""> <param name="SCRIPTABLE" value="true"> <param name="callingAction" value="create"> <param name="cache_option" value="Plugin"> <param name="MAYSCRIPT" value="true"> <param name="checksum" value=""> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="uploadedFromPath" value=""> <param name="completionUrl" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp rise.URLProcessor/invokeAction?action=CreateDocCloseWindow&class=wt.doc.WTDocument& OID=VR%3Awt.doc.WTDocument%3A288876&refresh=true&formName=CreateDocumentWizard"> <param name="workspacePath" value=""> <param name="docOperation" value="create"> <param name="debug" value="false"> <param name="failureUrl" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp rise.URLProcessor/invokeAction?nextAction=CreateDocument2&action=CreateDocumentUplo adFailure&class=wt.doc.WTDocument&OID=VR%3Awt.doc.WTDocument%3A288876&uploaded=fals e&formName=CreateDocumentWizard"> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value=""> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="oidString" value=""> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq"> <param name="uploadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten t.ContentHttp/saveContent?wt.doc.WTDocument%3A288877"> <param name="removable" value="true"> <param name="attachments" value="FILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft Excel Worksheet.xls;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\ MyFolder\New Microsoft PowerPoint Presentation.ppt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft Word Document.doc;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\ New Text Document.txt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New WinZip File.zip;;;qqqADD"> <param name="fileName" value="">

E-32

Windchill Customizers Guide

<param name="target" value="c:\temp\MyDoc.doc"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" bgcolor="16777215" validEmptyFile="false" oid="" SCRIPTABLE="true" callingAction="create" cache_option="Plugin" checksum="" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" uploadedFromPath="" completionUrl="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/w t.enterprise.URLProcessor/invokeAction?action=CreateDocCloseWindow&class=wt.doc.WTD ocument&OID=VR%3Awt.doc.WTDocument%3A288876&refresh=true&formName=CreateDocumentWiz ard" workspacePath="" docOperation="create" debug="false" failureUrl="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.e nterprise.URLProcessor/invokeAction?nextAction=CreateDocument2&action=CreateDocumen tUploadFailure&class=wt.doc.WTDocument&OID=VR%3Awt.doc.WTDocument%3A288876&uploaded =false&formName=CreateDocumentWizard" uploadIfFileChanged="true" targetType="" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" oidString="" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq" uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A288877" removable="true" attachments="FILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft Excel Worksheet.xls;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\New Microsoft PowerPoint Presentation.ppt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\MyFolder\ New Microsoft Word Document.doc;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\ MyFolder\New Text Document.txt;;;qqqADD;;;zzzFILE;;;qqqnewFile;;;qqqC:\TEMP\ MyFolder\New WinZip File.zip;;;qqqADD" fileName="" target="c:\temp\MyDoc.doc" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Additional Topics - Client Customization

E-33

Create Document (add primary/attachment URLs to single upload destination)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="validEmptyFile" value="false"> <param name="oid" value=""> <param name="SCRIPTABLE" value="true"> <param name="callingAction" value="create"> <param name="cache_option" value="Plugin"> <param name="MAYSCRIPT" value="true"> <param name="checksum" value=""> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="completionJSMethod" value="uploadCompleted"> <param name="uploadedFromPath" value=""> <param name="completionUrl" value=""> <param name="workspacePath" value=""> <param name="docOperation" value="create"> <param name="failureJSMethod" value="uploadFailed"> <param name="debug" value="false"> <param name="failureUrl" value=""> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value="URL"> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="oidString" value=""> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq"> <param name="uploadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten t.ContentHttp/saveContent?wt.doc.WTDocument%3A656270"> <param name="removable" value="true"> <param name="fileName" value=""> <param name="attachments" value="URL;;;qqqnewURL;;;qqqwww.google.com;;;qqqGoogle search engine;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.cnn.com;;;qqq;;;qqqADD"> <param name="target" value="www.ptc.com"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" bgcolor="16777215" validEmptyFile="false" oid="" SCRIPTABLE="true" callingAction="create" cache_option="Plugin"

E-34

Windchill Customizers Guide

checksum="" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" completionJSMethod="uploadCompleted" uploadedFromPath="" completionUrl="" workspacePath="" docOperation="create" failureJSMethod="uploadFailed" debug="false" failureUrl="" uploadIfFileChanged="true" targetType="URL" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" oidString="" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq" uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656270" removable="true" fileName="" attachments="URL;;;qqqnewURL;;;qqqwww.google.com;;;qqqGoogle search engine;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.cnn.com;;;qqq;;;qqqADD" target="www.ptc.com" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Create Multiple Documents (add primary files to multiple upload destinations)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windowsi586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet.class"> <param name="java_codebase" value="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="oid" value=""> <param name="SCRIPTABLE" value="true"> <param name="multipleQuantity" value="3"> <param name="callingAction" value="create"> <param name="cache_option" value="Plugin"> <param name="type" value="application/x-java-applet"> <param name="MAYSCRIPT" value="true"> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="lib/HTTPClient.jar, contentCust.jar, contentDSU.jar, contentFCS.jar, content3rdParty.jar, content.jar"> <param name="jreversion" value="1.4"> <param name="completionJSMethod" value="completion"> <param name="uploadedFromPath" value="">

Additional Topics - Client Customization

E-35

<param name="workspacePath" value=""> <param name="failureJSMethod" value="failure"> <param name="debug" value="true"> <param name="java_archive" value="wt/security/security.jar"> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value=""> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq"> <param name="uploadURL" value="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A20350;;;qqqhttp://lqkohpsh.ptcnet .ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.content.ContentHttp/saveContent ?wt.doc.WTDocument%3A20335;;;qqqhttp://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/serv let/WindchillAuthGW/wt.content.ContentHttp/saveContent?wt.doc.WTDocument%3A20365"> <param name="removable" value="true"> <param name="attachments" value=""> <param name="target" value="c:\temp\myfolder\New Text Document.txt;;;qqqc:\temp\ myfolder\New Bitmap Image.bmp;;;qqqc:\temp\myfolder\New WinZip File.zip"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet.class" java_codebase="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700" java_archive="wt/security/security.jar" bgcolor="16777215" oid="" SCRIPTABLE="true" multipleQuantity="3" callingAction="create" cache_option="Plugin" type="application/x-java-applet" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="lib/HTTPClient.jar, contentCust.jar, contentDSU.jar, contentFCS.jar, content3rdParty.jar, content.jar" jreversion="1.4" completionJSMethod="completion" uploadedFromPath="" workspacePath="" failureJSMethod="failure" debug="true" java_archive="wt/security/security.jar" uploadIfFileChanged="true" targetType="" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" java_code="wt/clients/util/http/UploadApplet" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq"

E-36

Windchill Customizers Guide

uploadURL="http://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/w t.content.ContentHttp/saveContent?wt.doc.WTDocument%3A20350;;;qqqhttp://lqkohpsh.pt cnet.ptc.com:2801/PDMLink700/servlet/WindchillAuthGW/wt.content.ContentHttp/saveCon tent?wt.doc.WTDocument%3A20335;;;qqqhttp://lqkohpsh.ptcnet.ptc.com:2801/PDMLink700/ servlet/WindchillAuthGW/wt.content.ContentHttp/saveContent?wt.doc.WTDocument%3A2036 5" removable="true" attachments="" target="c:\temp\myfolder\New Text Document.txt;;;qqqc:\temp\myfolder\New Bitmap Image.bmp;;;qqqc:\temp\myfolder\New WinZip File.zip" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Update Document (replace primary file)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="validEmptyFile" value="false"> <param name="oid" value="VR:wt.doc.WTDocument:656218"> <param name="SCRIPTABLE" value="true"> <param name="callingAction" value="updateReplace"> <param name="cache_option" value="Plugin"> <param name="MAYSCRIPT" value="true"> <param name="checksum" value="3774325531"> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="completionJSMethod" value="uploadCompleted"> <param name="uploadedFromPath" value="c:/temp/MyDoc.doc"> <param name="completionUrl" value=""> <param name="workspacePath" value=""> <param name="docOperation" value="update"> <param name="failureJSMethod" value="uploadFailed"> <param name="debug" value="false"> <param name="failureUrl" value=""> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value="FILE"> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="oidString" value="wt.content.ApplicationData:656261"> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq"> <param name="uploadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten t.ContentHttp/saveContent?wt.doc.WTDocument%3A656220"> <param name="removable" value="true"> <param name="fileName" value="MyDoc.doc">

Additional Topics - Client Customization

E-37

<param name="attachments" value=""> <param name="target" value="C:/TEMP/MyFolder/Sample.jpg"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" bgcolor="16777215" validEmptyFile="false" oid="VR:wt.doc.WTDocument:656218" SCRIPTABLE="true" callingAction="updateReplace" cache_option="Plugin" checksum="3774325531" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" completionJSMethod="uploadCompleted" uploadedFromPath="c:/temp/MyDoc.doc" completionUrl="" workspacePath="" docOperation="update" failureJSMethod="uploadFailed" debug="false" failureUrl="" uploadIfFileChanged="true" targetType="FILE" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" oidString="wt.content.ApplicationData:656261" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq" uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656220" removable="true" fileName="MyDoc.doc" attachments="" target="C:/TEMP/MyFolder/Sample.jpg" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Update Document (remove primary file)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="validEmptyFile" value="false">

E-38

Windchill Customizers Guide

<param name="oid" value="VR:wt.doc.WTDocument:656218"> <param name="SCRIPTABLE" value="true"> <param name="callingAction" value="updateReplace"> <param name="cache_option" value="Plugin"> <param name="MAYSCRIPT" value="true"> <param name="checksum" value="3774325531"> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="completionJSMethod" value="uploadCompleted"> <param name="uploadedFromPath" value="c:/temp/MyDoc.doc"> <param name="completionUrl" value=""> <param name="workspacePath" value=""> <param name="docOperation" value="update"> <param name="failureJSMethod" value="uploadFailed"> <param name="debug" value="false"> <param name="failureUrl" value=""> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value="NONE"> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="oidString" value="wt.content.ApplicationData:656261"> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq"> <param name="uploadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten t.ContentHttp/saveContent?wt.doc.WTDocument%3A656220"> <param name="removable" value="true"> <param name="fileName" value="MyDoc.doc"> <param name="attachments" value=""> <param name="target" value=""> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" bgcolor="16777215" validEmptyFile="false" oid="VR:wt.doc.WTDocument:656218" SCRIPTABLE="true" callingAction="updateReplace" cache_option="Plugin" checksum="3774325531" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" completionJSMethod="uploadCompleted" uploadedFromPath="c:/temp/MyDoc.doc" completionUrl="" workspacePath="" docOperation="update" failureJSMethod="uploadFailed" debug="false"

Additional Topics - Client Customization

E-39

failureUrl="" uploadIfFileChanged="true" targetType="NONE" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" oidString="wt.content.ApplicationData:656261" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq" uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656220" removable="true" fileName="MyDoc.doc" attachments="" target="" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Update Document (no primary content handling, add/replace/remove attachment files/URLs)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/UploadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="bgcolor" value="16777215"> <param name="validEmptyFile" value="false"> <param name="oid" value="VR:wt.doc.WTDocument:656269"> <param name="SCRIPTABLE" value="true"> <param name="callingAction" value="create"> <param name="cache_option" value="Plugin"> <param name="MAYSCRIPT" value="true"> <param name="checksum" value=""> <param name="contentRecordDelim" value=";;;zzz"> <param name="continueIfFileNotFound" value="false"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="completionJSMethod" value="uploadCompleted"> <param name="uploadedFromPath" value=""> <param name="completionUrl" value=""> <param name="workspacePath" value=""> <param name="docOperation" value="update"> <param name="failureJSMethod" value="uploadFailed"> <param name="debug" value="false"> <param name="failureUrl" value=""> <param name="uploadIfFileChanged" value="true"> <param name="targetType" value="NONE"> <param name="cabinets" value="wt/security/security.cab"> <param name="continueIfFileUnchanged" value="true"> <param name="oidString" value=""> <param name="contentDelim" value=";;;qqq"> <param name="wt.context.locale" value="en_US"> <param name="delim" value=";;;qqq">

E-40

Windchill Customizers Guide

<param name="uploadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.conten t.ContentHttp/saveContent?wt.doc.WTDocument%3A656270"> <param name="removable" value="true"> <param name="fileName" value=""> <param name="attachments" value="FILE;;;qqqnewfile;;;qqqC:\TEMP\ DGadReq.doc;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.amazon.com;;;qqq;;;qqqADD;;;zzzF ILE;;;qqqwt.content.ApplicationData:656293;;;qqqC:\TEMP\ MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qqqwt.content.URLData:656295;;;qqqhttp://www.askj eeves.com;;;qqqAsk Jeeves website;;;qqqREPLACE;;;zzzFILE;;;qqqwt.content.ApplicationData:656902;;;qqq;;;qqqRE MOVE;;;zzzURL;;;qqqwt.content.URLData:656904;;;qqq;;;qqqREMOVE"> <param name="target" value=""> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" MAYSCRIPT=true pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/UploadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" bgcolor="16777215" validEmptyFile="false" oid="VR:wt.doc.WTDocument:656269" SCRIPTABLE="true" callingAction="create" cache_option="Plugin" checksum="" contentRecordDelim=";;;zzz" continueIfFileNotFound="false" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" completionJSMethod="uploadCompleted" uploadedFromPath="" completionUrl="" workspacePath="" docOperation="update" failureJSMethod="uploadFailed" debug="false" failureUrl="" uploadIfFileChanged="true" targetType="NONE" cabinets="wt/security/security.cab" continueIfFileUnchanged="true" oidString="" contentDelim=";;;qqq" wt.context.locale="en_US" delim=";;;qqq" uploadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.co ntent.ContentHttp/saveContent?wt.doc.WTDocument%3A656270" removable="true" fileName=""

Additional Topics - Client Customization

E-41

attachments="FILE;;;qqqnewfile;;;qqqC:\TEMP\ DGadReq.doc;;;qqqADD;;;zzzURL;;;qqqnewURL;;;qqqwww.amazon.com;;;qqq;;;qqqADD;;;zzzF ILE;;;qqqwt.content.ApplicationData:656293;;;qqqC:\TEMP\ MyDoc.doc;;;qqqREPLACE;;;zzzURL;;;qqqwt.content.URLData:656295;;;qqqhttp://www.askj eeves.com;;;qqqAsk Jeeves website;;;qqqREPLACE;;;zzzFILE;;;qqqwt.content.ApplicationData:656902;;;qqq;;;qqqRE MOVE;;;zzzURL;;;qqqwt.content.URLData:656904;;;qqq;;;qqqREMOVE" target="" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

The Download Applet


DownloadApplet is an "invisible" applet, that is, a 2-pixel by 2-pixel applet whose background color matches the page. It starts the download as soon as the page has loaded and the applet has initialized, using the values in the applet parameters. This behavior makes DownloadApplet most appropriate for use in a "processing" page or popup rather than an interactive form page.

Download of a Single File


Downloading a file through DownloadApplet requires two pieces of information: the filename to download and the URL to download it from. These are indicated by setting the "filename" and "downloadURL" parameters. Depending on the user's preference for Download Operation Type, Windchill may open the file in application, save the file to disk in a location chosen by the user, or prompt the user to choose between open and save.

Download of Multiple Files from One or More Windchill Objects


Files can be downloaded from multiple Windchill documents or multiple content items to a single destination with a single instance of DownloadApplet. This is done by setting the "filename" parameter to a concatenated list of filenames, and setting the "downloadURL" parameter to a concatenated list of downloadURLs corresponding in quantity and order to the concatenated filename values, and setting the "downloadQuantity" parameter to the quantity of files to be downloaded. Depending on the user's preference for Download Operation Type, Windchill may open the first file in application, saved the first file to disk in a location chosen by the user, or prompt the user to choose between open and save for that file. All other files will be downloaded to the same directory chosen for the first file, without further prompting.

Configuring Download Behavior - User Preferences


The applet's prompt behavior and download location are determined by parameters that are typically set by the individual user's preferences. The Download Operation Type preference (node=/wt/content key= downloadOpType) determines whether the downloaded file should be opened in application, saved to disk or whether the user should be prompted to make that

E-42

Windchill Customizers Guide

choice. The default is to prompt. For downloads of multiple files, this decision only applies to the first file downloaded (all other files will be saved to disk, in the same location). The Default Local Directory preference (node=/wt/content key= workspacePath) determines where the file will be downloaded upon open-in-application, or where the file chooser will open to upon save-to-disk. Users who have a particular directory where they like to keep all their Windchill files might like to set this preference to that directory. If no value is specified, or if the specified path does not exist on the local machine, then a default directory will be used as specified by the environment variables of the local machine's operating system.

Additional Topics - Client Customization

E-43

Download Applet Parameters


Parameter Name java_codebase type java_code cache_archive Sample Value http://machinename.ptcnet.ptc.c om/Windchill/ application/x-javaapplet;version=1.4 wt/clients/util/DownloadApplet "contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" wt/security/security.jar wt/security/security.cab Plugin en_US 16777215 Description Provided by taglib generator Provided by taglib generator Applet location in codebase never changes Java archives containing the classfiles used by this applet

java_archive cabinets cache_option wt.context.loc ale bgcolor

Never changes Never changes Never changes Locale of users browser Decimal version of desired background color, typically matches the background color of the page or table cell where the applet is located URL that content will be downloaded from

downloadURL

http://mecasey03d.ptcnet.ptc.co m/Windchill/servlet/WindchillA uthGW/wt.fv.master.RedirectDo wnload/redirectDownload/1026 508screenshot.doc?u8&HttpOpe rationItem=wt.content.Applicati onData%3A294016&ContentHo lder=wt.doc.WTDocument%3A 294014" MyDoc.doc http://mecasey03d.ptcnet.ptc.co m/Windchill/servlet/WindchillA uthGW/wt.enterprise.URLProce ssor/invokeAction?action=Chec kOutDocCloseWindow&OID= VR%3Awt.doc.WTDocument% 3A294013&formName=CheckO utDocumentWizard 3

filename url

Filename of file to be downloaded, used in prompt dialogs, can be changed during download. URL to follow after processing is complete

downloadQua ntity

(Optional) Number of different files and download sources, if downloading more than one file

E-44

Windchill Customizers Guide

contentDelim downloadOpT ype defaultPath

;;;qqq ALWAYS_ASK, ALWAYS_SAVE, ALWAYS_OPEN C:/temp/MyWindchillFiles/dum my.txt

(Optional) Delimiter string used to separate filepaths if downloading more than one file (Optional) Normally retrieved from user preference setting, determines whether user is prompted to open-in-app vs. save-to-disk (Optional) Normally retrieved from workspacePath user preference setting, determines where file is downloaded for open-in-app or where file browser is launched for save-to-disk (Optional) Defaults to false, change to true for Java Console output during processing (Optional) Defaults to false, change to true to have main file's checksum and local download path appended to the URL query string for persistence by the post-processing code.

debug remember

true, false true, false

Sample HTML for DownloadApplet


Download (single file)
<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/DownloadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="filename" value="1026508screenshot.doc"> <param name="url" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterp rise.URLProcessor/invokeAction?action=CheckOutDocCloseWindow&OID=VR%3Awt.doc.WTDocu ment%3A294013&formName=CheckOutDocumentWizard"> <param name="debug" value="FALSE"> <param name="delim" value=";;;qqq"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="cabinets" value="wt/security/security.cab"> <param name="downloadOpType" value="ALWAYS_ASK"> <param name="cache_option" value="Plugin"> <param name="wt.context.locale" value="en_US"> <param name="downloadQuantity" value="1"> <param name="defaultPath" value=""> <param name="downloadURL" value="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.mas ter.RedirectDownload/redirectDownload/1026508screenshot.doc?u8&HttpOperationItem=wt .content.ApplicationData%3A294016&ContentHolder=wt.doc.WTDocument%3A294014"> <param name="recordDelim" value=";;;zzz"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/DownloadApplet"

Additional Topics - Client Customization

E-45

java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" filename="1026508screenshot.doc" url="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.enterpri se.URLProcessor/invokeAction?action=CheckOutDocCloseWindow&OID=VR%3Awt.doc.WTDocume nt%3A294013&formName=CheckOutDocumentWizard" debug="FALSE" delim=";;;qqq" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" cabinets="wt/security/security.cab" downloadOpType="ALWAYS_ASK" cache_option="Plugin" wt.context.locale="en_US" downloadQuantity="1" defaultPath="" downloadURL="http://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt. fv.master.RedirectDownload/redirectDownload/1026508screenshot.doc?u8&HttpOperationI tem=wt.content.ApplicationData%3A294016&ContentHolder=wt.doc.WTDocument%3A294014" recordDelim=";;;zzz" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Download (multiple files)


<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA" name="formApplet" width="2" height="2" codebase="http://java.sun.com/products/plugin/autodl/jinstall1_4_2-windows-i586.cab#Version=1,4,2"> <param name="java_code" value="wt/clients/util/http/DownloadApplet"> <param name="java_codebase" value="http://mecasey03d.ptcnet.ptc.com/Windchill/"> <param name="java_archive" value="wt/security/security.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="filename" value=";;;qqqRequirements_Template.doc;;;qqqAgenda_Template.doc;;;qqqMemo_Template. doc;;;qqqMinutes_Template.doc;;;qqqMS_Project_Plan_Template.mpp;;;qqqPresentation_T emplate.ppt;;;qqq"> <param name="url" value="javascript:close()"> <param name="debug" value="FALSE"> <param name="delim" value=";;;qqq"> <param name="cache_archive" value="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar"> <param name="cabinets" value="wt/security/security.cab"> <param name="downloadOpType" value="ALWAYS_ASK"> <param name="cache_option" value="Plugin"> <param name="wt.context.locale" value="en_GB"> <param name="downloadQuantity" value="6"> <param name="defaultPath" value=""> <param name="downloadURL" value=";;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt. fv.master.RedirectDownload/redirectDownload/Requirements_Template.doc?u8&HttpOperat ionItem=wt.content.ApplicationData%3A295941&ContentHolder=wt.doc.WTDocument%3A29593 9;;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.mas ter.RedirectDownload/redirectDownload/Agenda_Template.doc?u8&HttpOperationItem=wt.c ontent.ApplicationData%3A294345&ContentHolder=wt.doc.WTDocument%3A294335;;;qqqhttp: //mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.Redirect

E-46

Windchill Customizers Guide

Download/redirectDownload/Memo_Template.doc?u8&HttpOperationItem=wt.content.Applica tionData%3A294363&ContentHolder=wt.doc.WTDocument%3A294353;;;qqqhttp://mecasey03d.p tcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redir ectDownload/Minutes_Template.doc?u8&HttpOperationItem=wt.content.ApplicationData%3A 294381&ContentHolder=wt.doc.WTDocument%3A294371;;;qqqhttp://mecasey03d.ptcnet.ptc.c om/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownload /MS_Project_Plan_Template.mpp?u8&HttpOperationItem=wt.content.ApplicationData%3A294 399&ContentHolder=wt.doc.WTDocument%3A294389;;;qqqhttp://mecasey03d.ptcnet.ptc.com/ Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownload/Pr esentation_Template.ppt?u8&HttpOperationItem=wt.content.ApplicationData%3A295917&Co ntentHolder=wt.doc.WTDocument%3A295907;;;qqq"> <param name="recordDelim" value=";;;zzz"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" name="formApplet" width="2" height="2" pluginspage="http://java.sun.com/getjava/download.html" java_code="wt/clients/util/http/DownloadApplet" java_codebase="http://mecasey03d.ptcnet.ptc.com/Windchill/" java_archive="wt/security/security.jar" filename=";;;qqqRequirements_Template.doc;;;qqqAgenda_Template.doc;;;qqqMemo_Templa te.doc;;;qqqMinutes_Template.doc;;;qqqMS_Project_Plan_Template.mpp;;;qqqPresentatio n_Template.ppt;;;qqq" url="javascript:close()" debug="FALSE" delim=";;;qqq" cache_archive="contentCust.jar, contentDSU.jar, contentFCS.jar, lib/HTTPClient.jar, content3rdParty.jar, content.jar" cabinets="wt/security/security.cab" downloadOpType="ALWAYS_ASK" cache_option="Plugin" wt.context.locale="en_GB" downloadQuantity="6" defaultPath="" downloadURL=";;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuth GW/wt.fv.master.RedirectDownload/redirectDownload/Requirements_Template.doc?u8&Http OperationItem=wt.content.ApplicationData%3A295941&ContentHolder=wt.doc.WTDocument%3 A295939;;;qqqhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt. fv.master.RedirectDownload/redirectDownload/Agenda_Template.doc?u8&HttpOperationIte m=wt.content.ApplicationData%3A294345&ContentHolder=wt.doc.WTDocument%3A294335;;;qq qhttp://mecasey03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.Re directDownload/redirectDownload/Memo_Template.doc?u8&HttpOperationItem=wt.content.A pplicationData%3A294363&ContentHolder=wt.doc.WTDocument%3A294353;;;qqqhttp://mecase y03d.ptcnet.ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload /redirectDownload/Minutes_Template.doc?u8&HttpOperationItem=wt.content.ApplicationD ata%3A294381&ContentHolder=wt.doc.WTDocument%3A294371;;;qqqhttp://mecasey03d.ptcnet .ptc.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDo wnload/MS_Project_Plan_Template.mpp?u8&HttpOperationItem=wt.content.ApplicationData %3A294399&ContentHolder=wt.doc.WTDocument%3A294389;;;qqqhttp://mecasey03d.ptcnet.pt c.com/Windchill/servlet/WindchillAuthGW/wt.fv.master.RedirectDownload/redirectDownl oad/Presentation_Template.ppt?u8&HttpOperationItem=wt.content.ApplicationData%3A295 917&ContentHolder=wt.doc.WTDocument%3A295907;;;qqq" recordDelim=";;;zzz" ><NOEMBED> </COMMENT> </NOEMBED></EMBED> </OBJECT>

Additional Topics - Client Customization

E-47

E-48

Windchill Customizers Guide

Index

A
Access control Property, 2-12 Access control package, 30-5 Accessor methods Overriding, 35-9 Adding content holder data formats, 44-2 allSearch Types Search User Interface, 20-11 API report generation, 27-31 Applet Advantages, E-15 Content Download Applet, E-15 Content Upload Applet, E-15 Default Local Directory, E-19 Disadvantages, E-15 Download Applet, E-42 Download Applet Parameters, E-44 File Selection Applet, E-15 File Selection files for upload, E-16 FileChooserDropAppletParameters, E-20 FileChooserDropAppletsample HTML, E-21 Multi-Select Javascript sample, E-19 Processing File Selection Output, E-18 Sample Javascript for Feedback and Navigation, E-25 Single-Select Javascript sample, E-18 Upload Applet Parameters, E-29 Upload Behavior-System Properties, E-27 Upload Behavior-User Preferences, E-28 UploadApplet, E-23 Audit Event configaudit.xml file, 28-7 Handler Classes, 28-7 ProjectAuditEvent, 28-4 Audit Recorders, 28-7 auditing events configuration file, 28-3 Windchill Auditing Framework, 28-2

B
Batch scripts, 2-2 Best practices modifying files, 5-9 new files, 5-26 Bill of Materials Customizing, 21-19 Hierarchy Visitor, 21-20 product structure, 21-19 report, 21-19 bin directory, 2-2 BOM see Bill of Materials Business Classes, 21-2 Business classes Revision controlled business class, 36-6 Business data types Implementing, 35-8 Business objects Modeling, 4-1 Business services Implementing, 35-14

C
cat files, 2-7 For sharing code, 2-8 Change Management Delegates, 22-2 ChooseFolderDelegate, 22-2 ChooseLifeCycleDelegate, 22-2 ConcreteAssociationDelegate, 22-3 DisplayIdentificationDelegate, 22-4 Change Management Workflow Process Templates Change Issue Process, 24-6 Code Impacted, 24-12 Custom Workflow Process Templates, 24-12 customizing, 24-6 Existing Installations, 24-11 Installation and Upgrade, 24-11 New Installations, 24-11 Synch on Change Request Submit, 24-8 Synch on Multiple Object State Change, 24-10 synchronization robots, 24-6

Index-1

checkAttribute method, 35-12 ChooseFolderDelegate, 22-2 ChooseLifeCycleDelegate, 22-2 Class files, 2-5 Class path environment variable, 2-9 Classes Document, 36-10 Folder resident business class, 36-4 Foundation classes, 4-10 Item, 4-10 Link, 4-11 Managed business class, 36-5 Part, 36-13 Simple business class, 36-2 WTObject, 4-10 ClassInfo.ser files Location, 2-6, 2-13 CLASSPATH environment variable, 2-9 Client JAR files, 5-7, 5-11, 5-14 Code Sharing, 2-8 Code generation Files, 2-7 See system generation tools.properties file, 2-13 Code Impacted Change Management Workflow Process Templates, 24-12 codebase directory Details, 2-5 Location, 2-3 codebase files, 5-13 Column Length change for modeled attribute, 32-2 customizing, 32-2 default location, 32-2 comment EnumeratedType, 33-2 CompositeUnique property, 21-13 ConcreteAssociationDelegate, 22-3 constantEnumeratedType, 33-6 Content Download Applet, E-15 Content holders data formats, 44-2 Content Upload Applet, E-15 Control units, 2-8 cookie abstraction Design Pattern, 34-4 createSafeArea target, 5-6 Creating new packages, 5-26 CSS Customization, 27-17 csvReport Template, 27-11

elements, 27-11 Custom Reports, 1-6 custom_getFieldData overriding, 20-22 Customized files, 5-2 Customizing, 27-16 Customizing Modeled Business Objects Windchill Customization Points, 1-8 Customizing workflows key points, 24-14 lock/unlock promotion targets, 24-14 owner role, 24-16 review promotion request activity, 24-15

D
Data Model Customizations, 1-5 Database Access set by properties, 2-14 db.properties.file, 2-14 Default table size, 2-13 Properties file, 2-3 Property file See db.properties file Database indexes, 21-12 db directory, 2-3 db.properties file Database access properties, 2-14 General description, 2-10 wt.pom.dbPassword property, 2-14 wt.pom.dbUser property, 2-14 wt.pom.serviceName property, 2-14 DCA Update configurations, 20-14 DCA patterns Search Page, 20-10 Debug tracing, 2-12 debug.properties file General description, 2-10 Default Local Directory, E-19 defaultValue EnumeratedType, 33-2 Design Pattern Business Service, 34-3 cookie abstraction, 34-4 helper abstraction, 34-4 service abstraction, 34-5 ServiceEvent abstraction, 34-5 ServiceException abstraction, 34-6 type abstraction, 34-4 Iterated interface, 34-7 Master Iteration, 34-7

Index-2

Windchill Customizers Guide

Mastered interface, 34-7 Object Reference, 34-2 Development environment Directory structure, 2-2 Environment variables, 2-9 Files, 2-3, 2-7 Property files, 2-10 Source code control, 2-8 Directory Ant, 2-2 apacheConf, 2-2 bin, 2-2 cgi-bin, 2-2 codebase Details, 2-5 Location, 2-3 codebase/wt, 2-6 db, 2-3 installer, 2-3 lib, 2-3 loadFiles, 2-3 loadXMLFiles, 2-3 logs, 2-3 Module, 2-3 RoseExtensions, 2-9 src Details, 2-7 Location, 2-3 src/wt, 2-7 srclib, 2-3 Structure after installation, 2-2 upgrade, 2-4 display EnumeratedType, 33-2 DisplayIdentificationDelegate, 22-4 Doc package, 36-10 Document class, 36-10 Document package, 36-10 Download Applet, E-42 Download Behavior-User Preferences, E-42 Downloading a file, E-42 Downloading multiple files, E-42 Sample HTML, E-45 Download Applet Parameters, E-44 Drag and Drop Targets, E-17 drop, E-17

Customization Utility, 33-11 editing resource info, 33-7 entry contents, 33-7 entry format, 33-7 Extending, 33-10 GUI Usage, 33-12 localizing, 33-9 RBrbInfo, 33-7 resource bundle, 33-9 resource info header, 33-7 runtime resources, 33-8 start utility, 33-12 Enumerated Types creating subclass, 33-3 EnumeratedType class, 33-2 comment, 33-2 defaultValue, 33-2 display, 33-2 order, 33-2 selectable, 33-2 value, 33-2 enumVerify tool, 33-8 Environment variables Class path, 2-9 Rational Rose virtual path map, 2-9 SQL path, 2-9 Events Managing, 35-4 Examples Development process, 3-1 Executable class files, 2-5 ExportReport Template, 27-13 optional parameters, 27-13

F
feedback, E-24 File Browse Launchers launch Java file, E-16 File Selection Applet, E-15 File Browse Launchers, E-16 Processing Output, E-18 upload files, E-16 User Preferences, E-19 FileChooserDropApplet Parameters, E-20 Files new, 5-26 site-modified, 5-2, 5-5 Folder resident business class, 36-4 Foundation classes Definitions, 4-10

E
Enterprise package, 36-2 enumCustomize tool, 5-10, 33-11 Enumerated Type

Index-3

G
Generate Form URL, 27-33

J
java.rmi.server.hostname property, 2-12 java.util.Date, 27-29 Javascript method File Selection Applet, E-18

H
helper abstraction Design Pattern, 34-4 HTML files Location of, 2-6 HTML templates, 5-12

L
Link class, 4-11 listSiteChanges target, 5-6, 5-8 listSiteChangesIgnored target, 5-6 listSiteModExclusions target, 5-6 loadFiles directory, 2-3 Loading Initial data, 2-3 LoadReport Template, 27-11 standalone mode options, 27-13 Localization, 39-1 Location of required files, 2-6 Localizing Text, 39-5 Logging Default location for trace logs, 2-3 Enable/disable logging, 2-12 Trace messages From method server, 2-12 From server manager, 2-12 LogicalAttributes.xml file, 5-12 logs directory, 2-3

I
IdentificationObject, 21-6, 21-8 implements identified, 21-8 implements UniquelyIdentified, 21-10 Identified, 21-7 Identity Attributes flowchart, 21-5 IdentityService, 21-5 modify, 21-2 RevisionControlled Identity, 21-4 SemanticKeys, 21-11 System Assigned, 21-2 UniquelyIdentified, 21-11 User-Assigned, 21-2 Identity attributes, 21-2 IdentityService How to use, 21-6 Implementation of Visitors, 21-22 quantity units, 21-22 Indexed-Search webject customized search application, 20-15 IndexObject method reference, 20-23 IndexSearch indexed text, 20-19 Info*Engine, 1-6 Info*Engine tasks, 5-13 INI files, 5-13 Installation and Upgrade Change Management Workflow Process Templates, 24-11 installSiteChanges target, 5-6, 5-8 Internationalization, 39-1 Item class, 4-10 Iteration and Version Identifiers Customizing, 21-17 multicharacter series, 21-18 Iteration Identifiers integer series, 21-17

M
Macros customizing, 27-35 report parameter, 27-9 make_jar.config_jars target, 5-7 Managed business class, 36-5 Managing client JAR files, 5-14 mData files, 2-7 Location, 2-13 mdl files, 2-7 Meetings, 29-2 Method server Logging trace messages, 2-12 Model files, 2-7 Modeled PSE Support, 19-5 Modeling Business objects, 4-1 Modifying files, 5-9 Multicharacter Series, 21-18

Index-4

Windchill Customizers Guide

MyDerivedItem enumerated type, 33-10 MyDerivedSize enumerated type, 33-10 MySize enumerated type, 33-10

O
Object Identity System Managed, 21-4 User Managed, 21-4 Object Initialization Rules, 1-3 Object Selection Actions, 20-9 Oracle password property, 2-14 Oracle service name property, 2-14 Oracle user name property, 2-14 order EnumeratedType, 33-2 Organization and Container Templates, 1-4

customizing, 24-13 Properties, 1-2 Properties and Preferences, 1-2 Property files, 5-11 db.properties file, 2-10 debug.properties file, 2-10 Editing, 2-11 service.properties file, 2-10 System Configurator, 2-11 wt.properties file, 2-10 PSE Modeled and Soft Type Support, 19-5 ptcCurrent directory, 5-3, 5-4 ptcOrig directory, 5-3, 5-5

Q
QueryBuilder, 27-28 QueryBuilder Types Report Generation, 27-37 QueryResult, 37-5 QuerySpec, 37-4

P
Packages Access control, 30-5 Control units, 2-8 Doc, 36-10 Document, 36-10 Enterprise, 36-2 Location, 2-6 Overview, 30-2 Part, 36-13 Query, 37-4 Packages, new, 5-26 Parameters Input to the webject, 20-15 report generation, 27-7 Part class, 36-13 Part package, 36-13 PATH environment variable, 2-9 Path environment variable, 2-9 Persistence Management, 37-1 Manager, 37-2 Query, 37-4 Preferences, 1-2 Product Structure Explorer See PSE ProjectAuditEvent class, 28-4 Promotion Request Approval Process, 24-13 Promotion Request Review Process, 24-14 Promotion Request Workflow Processes

R
Rational Rose, 4-2 Virtual path map, 2-9 Windchill extensions, 2-9 WT_EXTENSIONS entry, 2-9 WT_STD_PACKAGES entry, 2-9 WT_WORK entry, 2-9, 2-13 Rational Rose Modeler Edition, 5-27 RB.java files Location, 2-6 RB.rbInfo enumerated type, 33-7 RBINFO files, 5-9, 5-10 Rebuilding client JAR files, 5-7, 5-11 Report Generation API, 27-31 basic example, 27-2 client, 27-30 csvReport Template, 27-11 customization details, 27-15 CSS Customization, 27-17 new formats, 27-26 query, 27-15 report format, 27-16 stylesheets, 27-18 XML Resource Bundles, 27-25 XML Result Format, 27-27 XSLT Customization, 27-17

Index-5

customizing macros, 27-35 ExportReport Template, 27-13 Generate Form URL, 27-33 initial query steps, 27-2 LoadReport Template, 27-11 macro generation form steps, 27-10 macros, 27-9 new client, 27-33 parameters, 27-7 QueryBuilder Types, 27-37 Report Templates, 27-11 URL customizing, 27-33 XSLT API, 27-32 XSLT standard, 27-26 XSLT Stylesheets as Report Formats, 27-30 Report Generation Form, 27-31 Report Generation Output, 27-32 Resource bundles Localizing, 39-5 Location, 2-6 Revision control, 36-6 Revision controlled business class, 36-6 RevisionControlled Identity, 21-4 Rose model components, 2-7 RoseExtensions directory, 2-9 Runtime environment Files, 2-3, 2-5 Runtime Resources building, 33-8

S
Safe area, 5-2, 5-3 Search Adding Actions to Search Table, 20-9 Adding Attributes, 20-7 Adding Search Component, 20-2 Adding Table Actions, 20-9 allSearch Types, 20-11 attributes within criteria pulldown, 20-7 componentId, 20-2 DCA patterns, 20-10 Defining a search component, 20-2 Formats, 20-14 Indexed-Search, 20-15 Indexing Behavior, 20-19 IndexObject reference, 20-23 IndexSearch, 20-19 Input Parameters, 20-15 Layout of page, 20-10 modify picker, 20-4 componentId parameter, 20-4

containerRef parameter, 20-4 containerType parameter, 20-4 frameTitleLabel parameter, 20-5 objectType parameter, 20-4 selectorType parameter, 20-4 Object Selection Actions, 20-9 overriding custom_getFieldData(), 20-22 Query Layer, 20-8 Row Level Actions, 20-9 Search component definition Key, 20-3 Windchill Solution, 20-2 Search User Interface, 20-11 SearchableAttributes.properties, 20-8 Soft Attributes, 20-6 Soft Types, 20-6 Style Sheet, 20-14 Update DCA Configurations, 20-14 Using a Component, 20-4 SearchCondition, 37-5 selectable EnumeratedType, 33-2 SemanticKey, 21-11 Server logic Overview of developing, 35-1 Server manager Logging trace messages, 2-12 service abstraction Design Pattern, 34-5 Service Customizations, 1-5 Service provider property file, 5-27 service.properties file General description, 2-10 ServiceEvent abstraction Design Pattern, 34-5 ServiceException abstraction Design Pattern, 34-6 Services Access control, 30-5 Event management, 35-4 Managing, 35-2 Overview, 30-1 Query, 37-4 Servlet Helper GatewayServletHelper, 21-30 URLFactory Functionality, 21-30 Sharing code, 2-8 Simple business class, 36-2 site.xconf file, 5-11 siteMod directory, 5-3, 5-4 Soft Attributes Search, 20-6

Index-6

Windchill Customizers Guide

Soft Types Searches, 20-6 Soft Typing, 1-4 Source code management, 2-8 Source files, 2-3, 2-7 SQL path environment variable, 2-9 SQL scripts, 2-3 Location, 2-13 SQLPATH environment variable, 2-9 src directory, 2-3 Details, 2-7 Style Sheet create new, 20-14 Stylesheets, 27-18 Supported API, 1-8 class, 1-8 method, 1-9 swmaint.xml script, 5-5 Synchronization robots, 24-6 System, 21-2 System generation Overview, 31-1 Using, 31-50 System-Managed Identity, 21-15

Updating client JAR files, 5-11, 5-14 content holder data formats, 44-3 Upload Applet, E-23 Checksum, E-27 feedback, E-24 multiple files initial upload, E-24 Persisting Information, E-25, E-26 Primary/Secondary initial upload, E-24 Sample HTML, E-32 Update/Replace/Remove, E-24 Upload Applet Parameters, E-29 uploadImpl parameter System Properties, E-27 URL parameters report generation table, 27-33 URLFactory implementation example, 21-31 User Interface Customizations, 1-6 User Preferences customizing, 21-24

V
validEmptyFile parameter System Properties, E-27 value EnumeratedType, 33-2 Version Identifiers harvard series, 21-17 Virtual path map Rational Rose Purpose, 2-9 WT_EXTENSIONS entry, 2-9 WT_STD_PACKAGES entry, 2-9 WT_WORK entry, 2-9, 2-13

T
Template files, 5-12 Text tailoring, 5-2, 5-9, 5-10 tools.properties file Use by code generator, 2-13 wt.classRegistry.search.path property, 2-13 wt.classRegistry.search.pattern property, 2-13 wt.generation.bin.dir property, 2-13 wt.generation.source.dir property, 2-13 wt.generation.sql.dir property, 2-13 wt.generation.sql.xxxTablesSize property, 2-13 ToolsSetup.bat, 2-2 Trace logs Default location, 2-3 Trace messages Logging From method server, 2-12 From server manager, 2-12 Transactions, 37-8 type abstraction Design Pattern, 34-4

W
Webex meetings customizing authentication scheme, 29-2 Windchill Auditing Framework configuration, 28-7 Windchill Customization Points, 1-8 Windchill directory structure, 2-2 Windchill Info*Engine tasks, 5-13 Workflow customizing, 24-2 Workflow HTML template customization steps, 24-3 Workflow HTML Templates customizing, 24-2

U
Unique database indexes, 21-12 UniquelyIdentified, 21-11

Index-7

Workflow Templates, 1-3 wt directory See also Packages wt.access.enforce property, 2-12 wt.change2 package change management delegates, 22-2 wt.change2.WTChangeRequest2 identified instructions, 21-7 wt.classRegistry.search.path property, 2-13 wt.classRegistry.search.pattern property, 2-13 wt.generation.bin.dir property, 2-13 wt.generation.source.dir property, 2-13 wt.generation.sql.dir property, 2-13 wt.generation.sql.xxxtablesSize property, 2-13 wt.home property, 2-11 wt.logs.enabled property, 2-12 wt.manager.verboseClient property, 2-12 wt.manager.verboseServer property, 2-12 wt.method.verboseClient property, 2-12 wt.method.verboseServer property, 2-12 wt.pom.dbPassword property, 2-14 wt.pom.dbUser property, 2-14 wt.pom.properties property, 2-14 wt.pom.serviceName property, 2-14 wt.properties file Double back slashes in path names, 2-11 Format of path names, 2-11 General description, 2-10 java.rmi.server.hostname property, 2-12 wt.access.enforce property, 2-12 wt.home property, 2-11 wt.logs.enabled property, 2-12 wt.manager.verboseClient entry, 2-12 wt.manager.verboseServer entry, 2-12 wt.method.verboseClient entry, 2-12 wt.method.verboseServer entry, 2-12 wt.pom.properties property, 2-14 wt.server.codebase entry, 2-11 wt.server.codebase property, 2-11 WT_EXTENSIONS entry, 2-9 WT_STD_PACKAGES entry, 2-9 WT_WORK entry, 2-9, 2-13 wtCustom directory, 5-2, 5-9 WTObject class, 4-10 wtSafeArea directory, 5-2, 5-3

XML Resource Bundles, 27-25 XML Result Format, 27-27 XSLT API report generation, 27-32 XSLT Customization, 27-17 XSLT standard, 27-26 XSLT Stylesheets Report Formats, 27-30 XSLT stylesheets XML resource bundles, 27-25

X
XCONF files, 5-11, 5-12, 5-28 xconfmanager, 6-2 XML Query results top level elements, 27-29

Index-8

Windchill Customizers Guide

You might also like