WCCustomizersGuide PDF
WCCustomizersGuide PDF
WCCustomizersGuide PDF
Windchill 7.0
December 2003
Copyright © 2003 Parametric Technology Corporation. All Rights Reserved.
User and training documentation from Parametric Technology Corporation (PTC) is subject to the copyright
laws of the United States and other countries and is provided under a license agreement that restricts copying,
disclosure, and use of such documentation. PTC hereby grants to the licensed 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. 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.
Third-Party Trademarks
Adobe is a registered trademark of Adobe Systems. Advanced ClusterProven, ClusterProven, and the
ClusterProven design are trademarks or registered trademarks of International Business Machines Corporation in
the United States and other countries and are used under license. IBM Corporation does not warrant and is not
responsible for the operation of this software product. AIX is a registered trademark of IBM Corporation.
Allegro, Cadence, and Concept are registered trademarks of Cadence Design Systems, Inc. AutoCAD and
AutoDesk Inventor are registered trademarks of Autodesk, Inc. Baan is a registered trademark of Baan
Company. CADAM and CATIA are registered trademarks of Dassault Systemes. COACH is a trademark of
CADTRAIN, Inc. DOORS is a registered trademark of Telelogic AB. FLEXlm is a registered trademark of
GLOBEtrotter Software, Inc. Geomagic is a registered trademark of Raindrop Geomagic, Inc. EVERSYNC,
GROOVE, GROOVEFEST, GROOVE.NET, GROOVE NETWORKS, iGROOVE, PEERWARE, and the
interlocking circles logo are trademarks of Groove Networks, Inc. Helix is a trademark of Microcadam, Inc.
HOOPS is a trademark of Tech Soft America, Inc. HP-UX is a registered trademark and Tru64 is a trademark of
the Hewlett-Packard Company. I-DEAS, Metaphase, Parasolid, SHERPA, Solid Edge, and Unigraphics are
trademarks or registered trademarks of Electronic Data Systems Corporation (EDS). InstallShield is a registered
trademark and service mark of InstallShield Software Corporation in the United States and/or other countries.
Intel is a registered trademark of Intel Corporation. IRIX is a registered trademark of Silicon Graphics, Inc.
MatrixOne is a trademark of MatrixOne, Inc. Mentor Graphics and Board Station are registered trademarks and
3D Design, AMPLE, and Design Manager are trademarks of Mentor Graphics Corporation. MEDUSA and
STHENO are trademarks of CAD Schroer GmbH. Microsoft, Microsoft Project, Windows, the Windows logo,
Windows NT, Visual Basic, and the Visual Basic logo are registered trademarks of Microsoft Corporation in the
United States and/or other countries. Netscape and the Netscape N and Ship's Wheel logos are registered
trademarks of Netscape Communications Corporation in the U.S. and other countries. Oracle is a registered
trademark of Oracle Corporation. OrbixWeb is a registered trademark of IONA Technologies PLC. PDGS is a
registered trademark of Ford Motor Company. RAND is a trademark of RAND Worldwide. Rational Rose is a
registered trademark of Rational Software Corporation. RetrievalWare is a registered trademark of Convera
Corporation. RosettaNet is a trademark and Partner Interface Process and PIP are registered trademarks of
"RosettaNet," a nonprofit organization. SAP and R/3 are registered trademarks of SAP AG Germany.
SolidWorks is a registered trademark of SolidWorks Corporation. All SPARC trademarks are used under license
and are trademarks or registered trademarks of SPARC International, Inc. in the United States and in other
countries. Products bearing SPARC trademarks are based upon an architecture developed by Sun Microsystems,
Inc. Sun, Sun Microsystems, the Sun logo, Solaris, UltraSPARC, Java and all Java based marks, and "The
Network is the Computer" are trademarks or registered trademarks of Sun Microsystems, Inc. in the United
States and in other countries. VisTools is a trademark of Visual Kinematics, Inc. (VKI). VisualCafé is a
trademark of WebGain, Inc. WebEx is a trademark of WebEx Communications, Inc.
vii
Setting the Length of Path Entries..................................................................................... 3-21
Creating a Custom RwareIndexDelegate.......................................................................... 3-22
Information Transfer When Indexing a Windchill Business Object.................................... 3-26
Customizing the Enterprise Search Interface.................................................................... 3-28
Customizing a Bill of Materials ................................................................................................. 3-28
Overview ........................................................................................................................... 3-28
Customization.................................................................................................................... 3-28
Current Implementation of Visitors .................................................................................... 3-31
Customizing User Preferences ................................................................................................ 3-32
The Preference Hierarchy and Delegates ......................................................................... 3-32
Writing a Servlet Helper to Use URLFactory Functionality ...................................................... 3-36
Example URLFactory Implementation............................................................................... 3-37
Contents ix
Form Processing and Action Processing ................................................................................. 7-61
Overview of Invoking an Action ......................................................................................... 7-61
Overview of Generating and Processing a Form .............................................................. 7-61
HTTPState and Form Processing ..................................................................................... 7-62
The invokeAction and processForm Methods ................................................................... 7-63
How to Invoke an Action.................................................................................................... 7-64
How to Generate and Process a Form.............................................................................. 7-67
Properties and Property Files .................................................................................................. 7-71
Application Context Service/Resource Properties............................................................. 7-72
HTML Client Services .............................................................................................................. 7-80
SubTemplateProcessing ................................................................................................... 7-80
ProcessorService .............................................................................................................. 7-82
Adding an HTML Help Link ...................................................................................................... 7-85
Adding Help Using Hyperlinked Text................................................................................. 7-85
Adding Help Using a Button .............................................................................................. 7-90
Adding Help Using the Global Navigation Bar................................................................... 7-91
Overview of HTML Components, Table, and Table Service .................................................... 7-92
HTML Components ........................................................................................................... 7-93
The HTMLTable ................................................................................................................ 7-97
HTML Table Service........................................................................................................ 7-100
Using HTML Components...................................................................................................... 7-102
The Standard Process..................................................................................................... 7-102
Using the HTMLComponentFactory................................................................................ 7-103
Creating a New Base HTML Component ........................................................................ 7-103
Creating a Custom HTML Component ............................................................................ 7-104
Selecting a New Context(#Service Name) for Initializing the Default Tag Attributes ...... 7-109
Printing Tags Only........................................................................................................... 7-110
Printing the Default Tag Values Only .............................................................................. 7-110
Using HTML Tables and Custom Tables ............................................................................... 7-111
Printing a Standalone HTML Table ................................................................................. 7-111
Setting cellSelector to Select Custom HTML Components for the Cells......................... 7-113
Enabling or Hiding Table Headers .................................................................................. 7-113
Using Custom Columns by Overriding createDefaultColumnsFromModel ..................... 7-113
Customizing the Table Body Generation by Overriding printRow ................................... 7-114
Customizing Header Generation by Overriding printHeaders ......................................... 7-117
Access the contextObj and TemplateState in an HTML Component in the Table .......... 7-117
Selecting a New Service Name for Custom Default Tag Attributes ................................ 7-118
Registering for the HTML Table Service ......................................................................... 7-118
Using the HTML Table Service .............................................................................................. 7-119
Contents xi
Action Configuration ............................................................................................................ 8-5
Default ActionDelegates and URLActionDelegates .......................................................... 8-32
Tables................................................................................................................................ 8-33
Common Customizations ......................................................................................................... 8-46
How to Create a Soft-Type-Specific Actions Dropdown Menu ......................................... 8-49
How to Add a Link to a Details Page Navigation Bar ........................................................ 8-53
How to Add a Soft-Type-Specific Details Page Navigation Bar ........................................ 8-57
How to Add an Action to the Actions Column of a PDMLink Table ................................... 8-59
How to Add a Multiselect Action to the Multiselect Action Bar of a PDMLink Table.......... 8-62
How to Add an Action to the Context-Specific Action Bar of a PDMLink Table ................ 8-67
Contents xiii
Report Generation ............................................................................................13-1
Overview .................................................................................................................................. 13-2
Basic Report Example ............................................................................................................. 13-2
Query................................................................................................................................. 13-2
Report Parameters ............................................................................................................ 13-7
Import and Export of Report Templates ................................................................................. 13-11
Customization Details ............................................................................................................ 13-15
Customizing the Query.................................................................................................... 13-15
Customizing the Report Format ...................................................................................... 13-16
Customizing the Report Generation Client...................................................................... 13-30
Customizing the Report Generation URL........................................................................ 13-33
Customizing Macros........................................................................................................ 13-35
Customizing QueryBuilder Types.................................................................................... 13-37
Contents xv
xvi Windchill Customizer’s Guide
Change Record
This chapter details major changes that have occurred since the last release.
Table 1 Changes for Release 7.0
Change Description
Chapter 15, Xconfmanager Utility This chapter was added for Windchill
7.0
Chapter 16, File-Handling Applets This chapter was added for Windchill
7.0
xvii
xviii Windchill Customizer’s Guide
About This Guide
Related Documentation
The following documentation may be helpful:
• What's New for Windchill Release 7.0
• Windchill Installation and Configuration Guide
• Windchill Upgrade Guide
• Windchill Application Developer's Guide
• Windchill System Administrator's Guide
• Windchill Business Administrator’s Guide
• Windchill Performance Tuning Guide
• Windchill User's Guide
If books are not installed on your system, see your system administrator.
xix
Technical Support
Contact PTC Technical Support through the PTC Web site, phone, fax, or e-mail
if you encounter problems using Windchill.
For complete details, refer to Contacting Technical Support in the PTC Customer
Service Guide enclosed with your shipment. This guide can also be found under
the Support Bulletins section of the PTC Web site at:
http://www.ptc.com/support/index.htm
The PTC Web site also provides a search facility that allows you to locate
Technical Support technical documentation of particular interest. To access this
page, use the following link:
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 License Management
using the instructions found in your PTC Customer Service Guide under
Contacting License Management.
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.
Documentation Conventions
Windchill documentation uses the following conventions:
Topic Page
Windchill Customization Points..........................................................................1-2
Handling Icons ....................................................................................................1-3
Creating Large Objects (LOBs) ..........................................................................1-5
1-1
Windchill Customization Points
Windchill is composed of thousands of Java classes. To help you focus your
customization efforts, the Windchill Java classes have been partitioned into two
sets. To customize Windchill, you should interact with the classes in the
Windchill Supported API set.
Javadoc
Javadoc is distributed for some, but not all, Windchill classes. Of those classes for
which Javadoc is distributed, some, but not all, are part of the Supported API.
Javadoc is distributed for some classes for informational purposes, even though
they may not be part of the Supported API.
Handling Icons
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.
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 Oracle 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.
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.
/*
*
* Lobber is an example of storing BLOBs. BlobClass has three BLOBs:
* imablob which is LobLocator, and imasmallblob, and imanothersmallblob
* which are
*
*/
try {
atr = createBlobClassRec(lobIt);
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();
if ( !lob_dir.isDirectory() )
return null;
s_files = lob_dir.list();
for ( int i=0; i
for ( int i=0; i
Topic Page
Customizing Column Lengths.............................................................................2-2
2-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 attribute’s 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 tools.properties. 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
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 %wt_home%\bin\tools.xml custom_column -
Dgen.input="wt.build.buildtest.SourceMaster
Topic Page
Identified Business Classes .................................................................................3-2
Customizing Iteration and Version Identifiers ..................................................3-17
Customizing Indexing Behavior........................................................................3-19
Customizing a Bill of Materials ........................................................................3-28
Customizing User Preferences ..........................................................................3-32
Writing a Servlet Helper to Use URLFactory Functionality.............................3-36
3-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 WTPart’s identity attributes are number and name. At least one of
the identity attributes of a class must have a uniqueness constraint in order to
distinguish between different instances of the class.
Overview
The following figure illustrates the IdentityService.
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 system-
assigned, 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.
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.
setParentFolderReference((ObjectReference)link.
getRoleAObjectRef());
setSubFolderName(link.getFoldered().getName());
//##end initialize%356993D30199.body
}
((SubFolderLink)obj).
setRoleAObjectRef(getParentFolderReference());
//##end setToObject%356993A900B2s.body
}
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.
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.
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 "+".
((WTChangeRequest2)obj).setNumber(number);
//##end assignToObject%356DC85D038A.body
}
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 multicharacter 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
multicharacter 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
multicharacter 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
RetrievalWare Fields
In addition to the full text index of object metadata and content files, text can be
indexed into specific RetrievalWare 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 RetrievalWare working directory that has a file
system library configured with the following fields:
Field Description
If you want a library to contain additional fields, you must add those fields before
data is indexed into the library. Refer to the File System Libraries section of the
RetrievalWare System Administrator’s Setup Guide for further information on
setting up library fields. After the fields have been defined for the library, you can
write a custom RwareIndexDelegate to populate the new fields with the
appropriate data.
Edit the rware.cfg file to set the SIZE variable to an integer value that will
accommodate the length of the desired paths.
Anytime you change this setting, you must use the RetrievalWare System Utilities
to delete and create a new index for the libraries, and repeat the BulkIndex
operation on them. Failure to delete and create the index, and then re-index (using
BulkIndex) will result in an error in the RWare Executive server and it will not
start.
To perform the required actions after changing the SystemId property, use the
following procedure:
1. Start the RetrievalWare System Utilities Menu.
2. If the Administration Servers or Search and Indexing Servers are already
running, shut them down as follows:
a. Select Administration Servers (option 3).
a. Select Shutdown (option 5).
a. Select [ Return to previous menu ] (option 1).
a. Select Search and Indexing Servers (option 4).
a. Select Shutdown (option 5).
a. Select [ Return to previous menu ] (option 1).
3. Select Indexing and index utilities (option 6).
4. Select Delete and create empty indexes for a library (option 10).
5. Enter the applicable library's name.
6. Respond Yes or No when the following prompt appears:
Are you sure?
8. Repeat steps 4 through 7 for all new libraries you want to index.
9. Select [ Return to previous menu ] (option 1).
10. Select [ Return to previous menu ] (option 1).
11. Restart the Administration Servers and Search and Indexing Servers.
a. Select Administration Servers (option 3).
b. Select Start servers in background (option 2).
c. Select [ Return to previous menu ] (option 1).
d. Select Search and Indexing Servers (option 4).
e. Select Start servers in background (option 2).
f. Select [ Return to previous menu ] (option 1).
12. Instantiate java wt.index.BulkIndexTool and re-index the affected libraries.
Uses introspection to get all attributes and their values defined for the current
Indexable object's type and gets all IBAs and their values for the current object
and indexes them to Rware. This method must be overwritten to do nothing or
return a specific set of fields if custom behavior is desired.
public void custom_getAdditionalMetaData()
Gets a default list of attributes like name, lifecycle state, modifyTimestamp, etc.
and their values and indexes them to Rware. If the default implementation for
custom_getMetaData() is being used then this method is not necessary because
any processing it does will be duplicate to what custom_getMetaData() does. The
only customizations that are valid for this method if custom_getMetaData() has
been customized are for attributes that are not detectable through introspection or
as IBAs.
public void custom_getAdditionalFieldData()
Customization point that allows for specific extra attribute and their values to be
defined and indexed to Rware. This customization point should not typically need
to be implemented.
In previous releases there were restrictions on removing the AppOID,
ObjectIdentifier, PersistInfoOID, and SystemId attributes. There are no such
restrictions in 7.0, customizers do not need to index these attributes. In 7.0,
PersistInfoOID is the only required attribute and it is handled outside of the
custom* methods so customizers do not need to be concerned with it.
To put your custom RwareIndexDelegate into action, you must update the
service.properties file to reflect this change. Following is the default
RwareIndexDelegate entry:
# #####################################################
# The wt.index.IndexDelegate service.
# ###########################################################
# note that you can change the "null" here for selector to a
# collection name to map a particular collection
# to a particular IndexDelegate
wt.services/svc/default/wt.index.RwareIndexDelegate/null/
wt.index.Indexable/0=wt.index.RwareIndexDelegate/singleton
(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.)
Alternatively, you may want all objects to go to a particular collection to be
indexed using a customized RwareIndexDelegate. In this case, you need to make
an entry similar to the following:
wt.services/svc/default/wt.index.RwareIndexDelegate/
A_Collection_Name/wt.index.Indexable/
0=mycust.ACustomIndexDelegate/singleton
// Then use whatever API calls are needed to get the data
// that is to populate the fields.
String fieldValue1 = customObject.getFieldValue1();
String fieldValue2 = customObject.getFieldValue2();
This example actually represents what the debug output would look like if the
RwareIndexDelegate was extended and the custom_getAdditionalFieldData( )
method was overridden as in the preceding example (note the two new fields in
bold). Assuming that the library definition defined NewField1 and NewField2, it
would be possible to search over these new fields.
After the IndexEntryToRware class generates this debug output, it makes an RPC
call to the RetrievalWare server telling the server to index it. The RetrievalWare
server then uses the document parser command file associated with the library that
the document is to be indexed into to parse the file.
Windchill supplies a document parser command file named wb_lib.dp, which
parses files of the preceding format. This file is located in the windchill_indexes
working directory (./dp/wb_lib.dp). The parser loops through the fields and takes
the first word after "field" as the field name and uses the rest of the line as the field
value.
Everything after the </fields> tag and before the <file> tag is indexed as the
document body. Overriding the custom_getAdditionalMetaData( ) method adds to
this text while overriding the custom_getMetaData( ) method. The <file> and
</file> tags are used to describe one or more content files. The parser sees these
and tells RetrievalWare to process them as children of the document that is
currently being indexed.
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.
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 {
preVisitWrite(level);
postVisitWrite(level);
return true;
}
out.print("<H");
out.print(a_level + 1);
out.print('>');
out.print("</H");
out.print(a_level + 1);
out.print('>');
out.flush();
}
}
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:
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
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.
The preference framework was designed so the USER and DEFAULT contexts
would be the top and bottom level of the preference hierarchy. In this case, the
wt.prefs.delegates.UserDelegate and wt.prefs.delegates.SystemDefaultDelegate
can be used out of the box without any modification. The rest of the hierarchy
should be handled by a customized preference delegate as described in the
remainder of this section.
Preference Hierarchy
An important distinction to make is the distinction between the preference
hierarchy and the preference structure. The preference structure is the data
structure used to store preferences and it is implemented by the preferences
framework. The preference hierarchy is the hierarchy used to describe which
preferences take precedence over other preferences. For example, assume the
following global corporate hierarchy for a company named The Acme
Corporation.
The Acme Corporation consists of two regional divisions: Europe and North
America. Each region can have a variable number of plants. Each plant can have a
variable number of divisions. Finally, each division consists of various users, all
as illustrated in the following figure.
Properties Value
The wt/prefs/delegates/delegates.properties value
wt.prefs.delegates.DelegateOrder is the property that controls the hierarchy in
which delegates are called. For each level in the hierarchy, there should be an
entry in this property. Customized entries should appear as
Delegate Roles
All preference delegates should be extended from the abstract class
wt.prefs.PreferenceDelegate. This class defines the methods that each delegate
must implement within the preferences framework. These methods are as follows:
• public String getLocalizedName(String division, Locale aLocale)
• public boolean isAdministrator(String division, WTUser user)
• public ArrayList getDivisionsAsAdministrator(WTUser user)
• public ArrayList getDivisions(WTUser user)
The getDivisions methods differ in that the getDivisionsAsAdministrator(user)
method should return a list of all the levels in this delegate for which the given
user is responsible or able to administrate. The getDivisions(user) method should
return all the divisions of which the given user is a member.
Using the figure of the corporation shown earlier, if this was a delegate that
managed the tree from Corporation to divisions, a user named Bob is a member of
Division X, Plant B, North American and Corporation. Internally, how the
delegate decides which users are members or administrators of divisions is up to
the developer. The preferences framework is strict in that it expects a well-formed
answer to the preceding methods. If a user is not a member of any division
managed by the delegate, then the ArrayList should be empty, not null. For details
on the implementation of the wt.prefs.delegates.* classes, see their javadoc.
//////////////////////////////////////////////////////////////////////
// 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 ***/ %>
<% /*** 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
<%
// 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>
Topic Page
Customizing Windchill Portal Pages...................................................................4-2
Customizing Colors in HTML and JSP Clients ..................................................4-5
Customizing Localizable Display Names .........................................................4-10
Customizing Local Searches .............................................................................4-12
Customizing the HTML Search ........................................................................4-17
Customizing the Windchill Explorer.................................................................4-23
Customizing Objects Created from the Windchill Explorer .............................4-31
Making Parts Content Holders ..........................................................................4-32
Adding URLs to the Method Server..................................................................4-32
4-1
Customizing Windchill Portal Pages
The out-of-the-box Windchill home pages, also referred to as portal pages, are
deployed using JavaServer Page (JSP) technology. Because each portal page is a
separate JSP page, they are relatively easy to customize. The following files work
together to produce these pages. Edit these files to change the appearance and
functionality of your site’s portal pages.
index.jsp
This is the beginning of the portal pages. It contains references to the
header.jsp and footer.jsp files, which control the appearance of the header and
footer, respectively, on all portal pages.
The header.jsp file contains the PTC logo in the image file logo.gif; you will
probably want to change this at your installation. You can either replace this
file in the portalimages folder or edit the header.jsp file to point to a different
logo image.
WTDefault.css
This file also controls the appearance of portal pages. The definitions in this
file control the font, and the font’s colors and sizes. It is designed so that any
change to this file is propagated to all the portal pages
This file is also used in some Windchill Foundation HTML clients. For
further information, see the section on Customizing Colors in HTML and JSP
Clients later in this chapter.
setup.jsp
This file contains most of the Java code that provides the functionality for
portal pages. It primarily creates strings for URLs so that the portal pages can
link to other parts of the Windchill system. It also handles the processing of
locales so that most text is returned in the correct language.
All .jsp pages include setup.jsp at the top of the file. This content gives the
.jsp pages access to the variables defined in this file (mostly strings). Once
these variables are included, the other pages can make use of them, such as for
printing out a link to the worklist, as shown in the following example:
<%= worklistlink %>
sethome.jsp
This file is called when users click on a link to go to the portal page they want
set as their personal home page (that is, the page they return to when they
click Home). It takes the inc and body arguments passed to it and sets these
values in the user's preferences.
The inc argument determines the links on the left of the user’s home page and
the body argument identifies the page that makes up the body of the home
page. For most pages, the body is set to the search.jsp page. To set your home
page to have a different body, create a link to sethome.jsp with
body=newbody.jsp, where newbody.jsp is the file you want included as the
body of your home page. The same process applies to specifying links using
the inc argument.
Following such a link would cause the index.jsp page to create the common home
page despite the fact that you may have inc and body defined differently in your
preferences.
In this case, the body of the page created would be the extras.jsp page, but the
links on the left-hand side would be whatever is set in your inc preferences.
wt.html.color.bg-msg=#DFDFDF
wt.html.color.bg-navbar=#DFDFDF
wt.html.color.bg-pagetitle=#066699
The style class referred to is one in the WTDefault.css stylesheet, and the color
values are identical to those in the stylesheet for each class.
You can change the colors in most HTML and JSP Windchill PDM clients by
modifying the color values in Windchill/codebase/wt.properties and
codebase/WTDefault.css. If you are using the Windchill Visualization features,
you must also modify the file Windchill/codebase/wtcore/jsp/wvs/style.jsp.
Typically, non-Foundation clients still use hardcoded color values in their HTML
templates. Modifying the colors of such clients requires modification of
individual templates. (For further information, see chapter 7, Customizing the
HTML Client.)
The figures in the remainder of this section show the style classes that are usually
used in HTML and JSP clients.
In the figure that follows, the following style classes are not generally used by
existing clients but are available for use in new clients:
In the following figure, the f-arrow-link style class is not generally used by
existing clients but is available for use in new clients:
b. Inspect the current getDisplayName() values for the WTPart class and its
locker attribute:
getDisplayName() : Part
getDisplayName() : Locked By
3. Build the runtime resource bundles for the customized packages by entering
the following commands:
ResourceBuild wt.part.partModelRB
ResourceBuild wt.locks.locksModelRB
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 chapter on Internationalization and Localization in the
Windchill Application Developer's Guide.
is used to determine the class to search against, the tab text, and the attributes that
are used and displayed. The format string is broken up into records. A one-
character code followed by a colon begins each record; a semicolon and space
combination are used as a separator between records.
The one-character codes are as follows:
C
Specifies a fully qualified class name to query on. This must be the first
record in the format string.
G
Specifies text for the search criteria tabs. All attributes that follow are grouped
on that tab until the next G record.
A
Specifies an attribute used in both the search criteria section and the display
area. Attributes are displayed in the order they appear in the string.
D
Specifies an attribute used in only the display area.
The following is an excerpt from QueryPanelOptions.java:
private static String[][]contents = {
{"All Document Types", "C:wt.doc.WTDocument; G:Search
Criteria; A:number; " +
"A:name; D:versionIdentity; A:title; A:department;
G:More Search Criteria; " +
"A:lifeCycleState; A:modifyTimestamp;
A:createTimestamp; " +
"A:description"},
{"General", "C:wt.doc.General; G:Search Criteria;
A:number; " +
"A:name; D:versionIdentity; A:title; A:type;
G:More Search Criteria; " +
"A:lifeCycleState; A:modifyTimestamp;
A:createTimestamp; " +
"A:description"},
To see the attributes that can be used in local search tasks, refer to the file
customization/localsearch/queryable.xls or look at the Rose model for the class.
The queryable.xls file is an Excel spreadsheet that lists, by class, the attributes that
can be used in the options file.
If you look at the Rose model for a class, attributes listed on the object or, in the
case of versioned objects, attributes on either the master or iteration are supported.
Run an inforeport with the fully qualified class name, for example:
inforeport wt.doc.WTDocument
panel.setParentFrame( query_frame );
// Set the parent frame in
// QueryPanel.
panel.addQueryPanelListener( new QueryListener( query_frame )
);
// Add a listener for the panel.
query_frame.setLayout( new BorderLayout() );
query_frame.add( panel, "Center" );
query_frame.setSize( panel.getSize() );
query_frame.setLocation( getLocation().x + 30,
getLocation().y + 30 );
query_frame.show();
}
For examples of how to use the Chooser task, see the Windchill Application
Developer’s Guide chapter on Developing Client Logic, the section on the
WtChooser bean.
// Load in the values for the drop down list for selecting what to search
against.
clientLocale = locale;
// **Customize --------------------------------------------------------------
--------------
// Add new classes to search to list below.
// Make sure that they are assigned numbers in sequence from 0 to N.
// Set dropDownListCount to N+1.
…
pickList = new String[classCount];
pickList[ALL] =
WTMessage.getLocalizedMessage(RESOURCE,queryResource.ALL,null,clientLocale);
pickList[WTPART] =
WTMessage.getLocalizedMessage(RESOURCE,queryResource.WTPART,null,clientLocale);
…
pickList[MYCLASS] = WTMessage.getLocalizedMessage(RESOURCE,queryResource.
MYCLASS,null,clientLocale);
queryClass[ALL] =
"wt.part.WTPart wt.doc.WTDocument wt.change2.WTChangeIssue
wt.change2.WTChangeRequest2 " +
"wt.change2.WTChangeInvestigation wt.change2.WTAnalysisActivity
wt.change2.WTChangeProposal " +
"wt.change2.WTChangeOrder2 wt.change2.WTChangeActivity2
wt.csm.businessentity.BusinessEntity " +
"wt.effectivity.ConfigurationItem wt.epm.EPMDocument " +
"wt.replication.unit.WTUnit " +
"wt.part.WTProductConfiguration " +
"wt.part.WTProductInstance2 "; // Please remember to keep a space at the
end so that conditionally added items work.
queryClass[WTPART] = "wt.part.WTPart";
…
queryClass[MYCLASS] = "?.?.MyClass";
/**
*
* <BR><BR><B>Supported API: </B>false
*
* @param locale
* @return MySearchAttributeList
**/
/**
*
* <BR><BR><B>Supported API: </B>false
*
* @return MySearchAttributeList
**/
public MySearchAttributeList() {
return;
}
}
In the all-default example, the results are sorted first by the number column and
then by the version column, with the number being in ascending order and the
version in descending order. Currently, the supported number of sort keys is 3,
although theoretically the number of sort keys is limited only by Oracle
performance. No testing beyond 3 keys has been done on the system.
...
} // End of CreateMyReportFrame''
Similarly, you must build GUIs for updating and viewing MyReport objects:
public class UpdateMyReportFrame extends java.awt.Frame {
...
} // End of UpdateMyReportFrame''
} // End of ViewMyReportFrame'
After you build the GUIs to create, update, and view MyReport objects, you must
integrate these GUIs into the Windchill Explorer. This integration is done by
implementing a TaskDelegate.
All create, update, view, and delete tasks are launched through TaskDelegates in
the Windchill Explorer. When an update is invoked on a object, for example, the
Windchill Explorer attempts to locate a TaskDelegate implementation based on
the class of the selected object. If a TaskDelegate is found, the Windchill Explorer
invokes the launchUpdateTask method on that TaskDelegate.
} // End of 'launchViewTask'
identity = localized_message.getLocalizedMessage(
WTContext.getContext().getLocale() );
} else {
identity = object.toString();
}
} // End of 'launchDeleteTask'
} // End of 'MyReportTaskDelegate'
Note: For simplicity in the preceding example, hard-coded strings were used to
initialize the TaskDelegateExceptions. We recommend using resource bundles in
the actual implementation.
if (object == null) {
throw new WTException(RESOURCE,
wt.enterprise.enterpriseResource.COPY_NULL_OBJECT,
null);
try {
MyDocument new_doc = MyDocument.new MyDocument ();
MyDocument orig = (MyDocument) object;
new_doc.setMyAttribute(orig.getMyAttribute());
new_doc.setTitle(orig.getTitle());
new_doc.setDescription(orig.getDescription());
new_doc.setDepartment(orig.getDepartment());
new_doc.setDocType(orig.getDocType());
return new_doc;
}
catch (WTPropertyVetoException wtpve) {
throw new WTException(wtpve, RESOURCE,
wt.enterprise.enterpriseResource.COPY_ATTRIBUTES,
null);
}
//##end newCopy%378E0B7F037Af.body
}
Next, add any custom attributes that must be copied, similar to myAttribute in the
preceding example.
Finally, add the following line to
wt/enterprise/EnterpriseServerDelegate.properties in the codebase directory:
wt.services/svc/default/wt.enterprise.CopyDelegate/null/
mypackage.MyDocument/0=mypackage.CopyMyDocumentDelegate/
duplicate
Note you should actually enter only one line; the indentation here indicates a
continuation of the preceding line, necessary for presentation of lines within the
book.
import wt.httpgw.CGIConstants;
import wt.httpgw.HTTPRequest;
import wt.httpgw.HTTPResponse;
import wt.htmlutil.ProcessTemplate;
import wt.htmlutil.HtmlUtil;
import wt.htmlutil.HTMLTemplate;
import wt.htmlutil.TemplateName;
/**
* This is an example class containing methods to process
* two different
* HTTP Post requests and a method to process an
* HTTP Get request. This class extends HTMLUtil so that
* the static methods
* contained within HTMLUtil do not have to
* be referenced by
* HTMLUtil.methodname. This code is for illustration purposes
* and comes with no guarantee.
**/
public class Example extends HtmlUtil implements CGIConstants{
private static String name = "default";
/**
* This version of the readPost method handles post requests
* with object bodies.
*
* @param req HTTPRequest object we received.
* @param res HTTPResponse object we are sending back.
* @param is InputStream object we received to read from
* (actually req.input_stream).
*
**/
query_string = req.splitQueryString(
req.getProperty(CGI_QUERY_STRING));
post_dir = query_string.getProperty("POST_DIR", ".");
int x = 0;
byte buffer[] = new byte[1024];
String fname = new String();
MPInputStream mis = new MPInputStream(req.inputStream,
req.getProperty(CGI_MULTIPART_BOUNDARY).toString() );
try {
while (mis.hasMoreObjectBodies()) {
if ((fname = mis.getBodyHeader("filename")) != null) {
// replace doublequote with space.
fname = fname.replace('\u0022', '\u0020');
fname = fname.trim();
// need to check if and what kind of dir delimitor.
// client could be different than host system.
int u = fname.lastIndexOf("/");
int d = fname.lastIndexOf("\\");
if ( u < d ) {
fname = fname.substring(fname.lastIndexOf("\\")
+1);
} else if ( u > d ) {
fname = fname.substring(fname.lastIndexOf("/")
+1);
}
// If both u and d where zero, we had no path.
// This example doesn't care about path where
/**
* The GET request handling method. An HTML page is
try {
if (req.isPostRequest()) {
// This Get method follows a
// Post method call.
// Get the
// data set in the Post method.
// Since no
// corresponding POST method
// exists, this method gets the
// data directly.
try {
Properties inputContents =
req.getFormData();
name = inputContents.getProperty ("name");
} catch (Exception e) {
throw new WTException (e);
}
}
PrintWriter out = new PrintWriter
(new BufferedWriter (
new OutputStreamWriter(
resp.getOutputStream())));
/**
* This is a GET request handling method. An HTML page
* is generated
* from a template file.
* The template name was specified on browser input. There
* is no corresponding
* POST method as
* none are allowed.
*
* @param req The HTTPRequest structure.
* @param resp The HTTPResponse structure from which we get the
* output stream.
**/
public static void processGet (HTTPRequest req,
HTTPResponse resp) throws
WTException {
String queryString =
req.getProperty(CGI_QUERY_STRING);
Properties queryStringContents =
req.splitQueryString(queryString);
String name = queryStringContents.getProperty
("Templatename");
try {
// Get the preferred language of the template.
String acceptLanguage =
req.getProperty(req.CGI_ACCEPT_LANGUAGE);
Vector preferences =
LanguagePreference.getAcceptLanguagePreferences(
acceptLanguage);
OutputStream os = resp.getOutputStream();
insertForms is a simple method that reads in the file specified and writes it to the
output stream. If TestDriverForms.html contains the following HTML text:
<FORM method='POST' action=''http://127.0.0.1/Windchill/servlet/WindchillGW/
wt.htmlutil.test.TestPage/processPage''>
Name:<INPUT type=''TEXT'' name=''name'' maxlength=50>
<P><INPUT type=''SUBMIT'' ALIGN=''CENTER''></P>
</FORM>
Note: This is a simple example for illustration purposes. The URL given really
should be generated through a method in a Windchill Script.
out.println (str);
out.flush();
The preferred way to dynamically generate HTML is with the HTML templates.
It lends itself to easy customization and localization.
Topic Page
Customizing service.properties ...........................................................................5-2
5-1
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 chapter titled The Windchill
Development Environment in the Windchill Application Developer’s Guide.)
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 file’s 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
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.
4. Restart the method server in order for the change to take effect.
2. 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.
Topic Page
Overview of Load Utilities..................................................................................6-2
Customizing Loading ..........................................................................................6-4
Creating New Methods for Loading....................................................................6-6
Existing Load Methods .......................................................................................6-9
6-1
Overview of Load Utilities
The wt.load package is a set of framework utilities for loading demonstration or
test data. It can be expanded to load new classes. The following three classes can
be used to run loads:
Demo
Used to load demonstration data.
Developer
Used to load initial users and access control rules. It is typically needed by a
developer for using the Windchill system. The devuser.csv can be used to add
initial users to the system.
LoadFromFile
Callable from both the command line and from other classes. The Demo and
Developer classes call this class to load much of the data that they load.
LoadFromFile is a framework that can be used to load data into your own site
classes. The following source files are included as examples of how to use the
load package: wt.load.Demo.java, wt.load.Developer.java, and
wt.doc.LoadDoc.java.
LoadFromFile in the main or command line call, or the doFileLoad method call
uses the following parameters to load data into the system:
data file
Contains data to be loaded and resides on the MethodServer host. The data
file is a required parameter. If the string is null or not on the command line,
the load fails. It is recommended that you pass the full path name of the file. If
the full path is not provided, however, the method attemps to read the file in
the directory in which the load was started.
map file
Used in the mapping of attribute names to sequence of data in the data file. It
also contains the method to call to load the data. If the string passed is null,
the method tries to use the value of wt.load.defaultMapFile from
wt.properties. If that is also null, the default is wt.home\loadFiles\
csvmapfile.txt where wt.home is from wt.properties. If there is no file to
match, the load fails.
out file
Not currently implemented.
token
Used to delimit fields of data in the data file. If the token string is null, an
attempt is made to get wt.load.defaultToken from wt.properties. If that also
returns null, then ',' is used.
Map File
Following is an example of a map file:
#class,method,real method~attribute 1~attribute 2~….~attribute n
General~create~wt.doc.LoadDoc.createGeneral~user~name~title
~number~type~description~department~saveIn~path~format
~project~domain~lifecycletemplate1
The map file is used to map the specific method call and the data fields to a line in
the data file. The first two fields, class and method, are the keys to the map file.
Two keys are given to each line in the map file to allow multiple definitions for a
given actual class in Windchill. This allows alternate names for one class,
multiple functions for one class, or different input fields. Both class and method
are arbitrary strings. The class value matches the class in the data file. It is used
only to match the map and data files so it can be any string as long as the same
string is used in both. The method value matches the method variable passed
either on the command line or as a parameter to doFileLoad. The real method field
is the fully qualified method name that load calls through introspection with the
values from the data file. The attributes 1 through n match the text used in the real
method. The order in the map file is used to retrieve the values from the data file.
The following are possible scenarios for modifying this file:
• Data for the data file has the data fields in a different order. Edit the
csvmapfile.txt to make the order the same as the data file.
• You want to add a new site class. Create a new line in the map file with a new
class, real method, and new attribute list. Following is an example line added
to csvmapfile.txt for a new class:
NewClass~create~wt.doc.LoadDoc.createNewClass~user~name~title
~number~type~description~department~my_new_attribute~saveIn
~path~format~project~domain~lifecycletemplate
Do not put blank lines in the map file. One or more empty lines between entries
cause the load to fail.
1. The preceding is only one line but wrapped here for readability. Continuation of lines is not accepted.
The # character as the first character of a line indicates a comment and the line is
ignored. Blank lines and spaces at the beginning of a line are ignored. As in the
earlier example, the preceding is only one line but wrapped here for readability.
Continuation of lines is not accepted.
The data file is used to provide the load with data. The first field is the class field,
which was just described under the map file description. The rest of the fields are
strings to be mapped to the attributes listed in the map file. To load different data
than was shipped with Windchill, create a new data file. If a new class is created
as was just described under the map file description, a new data file would have to
be created with records like the following:
NewClass,phg,EGadWork,Econo Gadget R6.1 Work Plan,1,Document,
Work plan for Econo Gadget R6.1,DESIGN,my new attribute value,
/Design/Gadget/Econo Gadget,EGadWork.xls,Microsoft Excel,,,
Note that, if you edit a data file, part numbers must be uppercase.
This vector is used to give more informative messages back to the command
line. If the object that was manipulated by this method does not implement
getIdentity or that information would not be useful in a message to the
command line, a string should be added to the return_object instead; for
example:
String msg = "Type = Content Item, Identity =
" + appData.getFileName();
return_objects.addElement(msg);
There is a utility that resolves the data from the data file and the data from the
command line. For example, to retrieve a value for the new attribute that was
added for NewClass, use the following:
String my_attribute = LoadServerHelper.getValue("my_new_attribute",
nv,cmd_line,LoadServerHelper.REQUIRED);
The first parameter is the string from the map file. The last parameter is used to
indicate if the field is required, not required, or blank okay. If the field is required
or the load should fail, use LoadServerHelper.REQUIRED and check if the return
value is null. LoadServerHelper.getValue generates an error message if the value
is required and the field value is null or an empty string.
If the field is not required and you want the return set to null for no value or empty
strings, use LoadServerHelper.NOT_REQUIRED.
and adds the content file to the document. If you are creating an object that can
hold content (files and URLs) and you want to load multiple content items on
lines following the object in the data file, you must cache the object using the
following constant:
private static String CURRENT_CH_KEY = "Current ContentHolder";
If you want to cache an object for another reason, you must create a unique key
string. It is recommended that you clear your cached object at the beginning of the
next create so that if the create fails, the next operation depending on it will fail
and not corrupt other data. The cache of all objects is cleared after the last data
line is processed.
The load utility creates a transaction block around the processing of each line of
data. If the method returns false, the transaction block is rolled back. If it returns
true, it is committed. The cache is not cleared if the method returns false.
The following is an example of what to add to LoadDoc.java to add the NewClass
example. LoadDoc.java source is provided in wt.doc.
public static boolean createNewClass(Hashtable nv, Hashtable cmd_line,
Vector return_objects) {
if (flag == false)
return false;
try {
LoadServerHelper.removeCacheValue(CURRENT_CH_KEY);
LoadServerHelper.changePrincipal(user);
In Windchill PDM, the majority of HTML clients are produced using a PTC
technology called template processing. A few clients are produced from JSP
pages. PDM Link makes greater use of JSP pages and ProjectLink pages are
almost all generated form JSP pages. Future releases of both PDMLink and
ProjectLink will make use of PTC’s new application framework called DCA.
DCA is described in detail Windchill Client Technology Guide.
This chapter describes how to create and implement HTML clients using template
processing. It covers the basic features used in both WIndchill PDM and
PDMLink. Extensions to template processing features specific to PDMLink are
covered in the Customizing PDMLink Template Processing Clients chapter.
An overview of HTML client development is given first, followed by an example
of creating a view page. The example gives step-by-step instructions but does not
go into detail about general concepts. The sections that follow the example
provide the details on how to implement template processors in general and how
to use the HTML template factory. These sections are considered reference
material for the first example.
Next is another step-by-step example of how to add an action to an HTML client.
Again, this example is followed by reference sections with more detail about form
processing and action processing.
You should go through both of these examples thoroughly before attempting to
write or customize an HTML client. Code segments used in the examples can be
found in the customization/HTMLClient directory, specifically in Example1.doc
and Example2.doc.
7-1
The remaining sections provide both examples and reference information on using
HTML help links, HTML components, tables, and the table service.
Topic Page
Overview............................................................................................................. 7-3
Creating a View Page in the HTML Client with an Association—Example 1 7-14
How to Implement Template Processors .......................................................... 7-23
How to Use the HTML Template Factory........................................................ 7-41
Adding an Action in the HTML Client—Example 2........................................ 7-47
Form Processing and Action Processing........................................................... 7-61
Properties and Property Files ............................................................................ 7-71
Adding an HTML Help Link ............................................................................ 7-85
Overview of HTML Components, Table, and Table Service........................... 7-92
Using HTML Components ............................................................................. 7-102
Using HTML Tables and Custom Tables ....................................................... 7-111
Using the HTML Table Service...................................................................... 7-119
Performing a Multiselect in the HTML Client ............................................... 7-126
Changing the Presentation of the Attributes in the HTML Client .................. 7-133
Setting Color and Style Attributes in HTML and JSP Clients........................ 7-142
HTML Component Implementation ............................................................... 7-146
HTML Table Generation and Table Service Implementation ........................ 7-154
In a Web browser, a user clicks on a link and the URL is sent to the URLProcessor
class. URLProcessor is the gateway into the template processing architecture. In
an HTML client, almost all URLs go through URLProcessor.
URLProcessor calls the TemplateProcessorFactory class.
TemplateProcessorFactory maps information from the URL to entries in the
services.properties file to find the correct instance of the TemplateProcessor
interface to return. Basically, the service.properties file contains a mapping of an
action and possibly an object to a specific TemplateProcessor.
TemplateProcessorFactory then returns the correct TemplateProcessor to
URLProcessor.
URLProcessor also creates and initializes an HTTPState object. This object
contains information from the URL which both the TemplateProcess and
URLProcessor can use. This mechanisn essentially allows state information to be
passed.
BasicTemplateProcessor is a class that contains several service methods you can
use, for example, to get the icon for a business object or a class, and to display the
contents associated with a content holding object.
DefaultTemplateProcessor is the TemplateProcessor subclass we recommend you
extend when you create new template processors. It has the HTTPState cookie
and provides a default implementation of the steps performed by a
TemplateProcessor, thus hiding many of the details of the actual processing of an
HTML template file and the locating of the HTML template file to be used.
DefaultTemplateProcessor works with DefaultHTMLTemplateFactory class.
DefaultHTMLTemplateFactory is similar to TemplateProcessorFactory in that it
looks up a mapping in the htmltemplate.properties file to find the HTML template
file to be processed.
– The class and the specific method in the class that is going to be invoked
to process the URL, for example:
wt.enterprise.URLProcessor/URLTemplateAction?
For this URL, you must have a property that looks like the following:
wt.services/svc/default/wt.enterprise.TemplateProcessor/
ReferencedBy/wt.doc.WTDocument/
0=wt.mystuff.MyTemplateProcessor/
duplicate
Note: See the section, Properties and Property Files for information on how to
add new properties to the system.
Note: See the section, Properties and Property Files for information on how to
add new properties to the system.
The first part of this section has discussed how to add and process pages that
simply present views of information. The remainder of this section will describe
how to support user interaction with forms, how to manipulate forms, and how to
manipulate business objects, for example, creating business objects and checking
them in and out. Generally, these kinds of actions are dependent on access control
and the state of an object.
The URLProcessor class has three methods that are typically used for generating
forms, processing forms, and invoking actions:
generateForm
Creates HTML pages that have HTML forms. This method is invoked to
display a form. It involves using an ActionDelegate to check whether the user
should have access to the action and looking up a TemplateProcessor to
display the form.
processForm
Handles processing of the HTML forms that are returned. This method looks
up a form task delegate, which does the actual processing of the form.
In this URL, the action argument is used to find the ActionDelegate and
FormActionDelegate (described next in this section). Either the oid or class
argument is used to locate the FormActionDelegate (also described next in this
section).
The preceding URL is generated in the HTML template as follows through a call
to generateAction:
<form name="importDocument" enctype="multipart/form-data" action=
<SCRIPT LANGUAGE=Windchill>
getURLProcessorLink method=processForm action=navigateFolders
</SCRIPT>
method=POST>
Before Starting
Before starting this example, open your wt.properties file and add the following
line as the last entry in the file
wt.template.cache.enabled=false
Save and close the file. It is helpful to use this setting temporarily for
development, but it should be left as "True" in a production sytem.
Locate the file customization/HTMLClient/Example1.doc; it contains codes that
you will want to copy to complete this example.
<SCRIPT LANGUAGE=Windchill>
<!--
wt.htmlutil.HtmlUtil createBase
-->
</SCRIPT>
<HEAD>
<STYLE TYPE="text/css">
<!--
FONT,H1,H2 {font-family: <SCRIPT LANGUAGE=Windchill>getWCFontFamily quotes=
none</SCRIPT>}
-->
</STYLE>
</HEAD>
<P>
<BR>
<P>
</TD>
<SCRIPT LANGUAGE=Windchill>
<!--
showResponseHeaders
-->
</SCRIPT>
<P>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
2. In the new template file that contains the preceding code, search for the
Windchill script method createNavigationBar and replace <Action> with a
name of your choice. The name of the action is completely up to you, but it
should have some relation to the page that the link leads to.
3. Search for the HTML comment <!- - Add newPageMethod below here - ->
and add a Windchill script call, newPageMethod. Use the same Windchill
script syntax that is present in the page.
4. Save the template file in any directory under codebase with any name you
like. The only requirement is that the name must have the standard HTML
extension, either .htm or .html.
Note: The newPageMethod does not show the parameters unless you click on
it.
7. Generate the training.clientlab package by giving the
NewPageTemplateProcessor class the focus. You should now have a template
processor, NewPageTemplateProcessor.java, in the package
training.clientlab.
8. The method stub for newPageMethod that was generated by the Rose model
should have the following signature:
public void newPageMethod(Properties parameters, Locale locale,
OutputStream os)
Use the following code (also found in
customization/HTMLClient/Example1.doc under the label newPageMethod
Body) to fill in the body of the method.
java.io.PrintWriter out = getPrintWriter(os, locale);
out.println("<H3>You have Part :");
out.println( ( (wt.part.WTPart)getContextObj() ).getName() );
out.println("</H3>");
out.flush();
Replace <Action> with the name of the action you selected in step 2 of
creating the HTML template.
<Action> is the name of the action you selected in step 2 of Creating the
HTML Template File. Replace <Action Display Name> with the text you
want to appear in the browser as the hyperlinked text.
3. Save the file.
4. Compile. UrlLinkResource now has a new link for Documents in its listing.
At this point, the new page should be available for display.
The Class Explorer Frame should pop up with two classes in the left panel.
6. You can now search under each class presented in the Class Explorer for
available attributes to present in the table of the associations.
7. Select some new attributes for each class and add them to the list of attributes
to display by adding them to the HTML template. You can also remove some
of the attributes that are currently displayed.
Overview of HTTPState
The HTTPState class is used as a cookie to store the context of the template
processing and provide some convenience services. The context of template
processing is defined with the following elements:
• The current action
• The current object (if any)
• The class (if any)
The meanings of the first two variable fields, Context Action and Context
Class, are the same as shown in the preceding step. The third field,
Relative Path from Codebase, identifies the file path of the HTML
template. In this path, you must replace the standard directory separators
with periods ("."). For example, if you have an HTML template located at
the following location on an NT system:
C:Windchill\codebase\templates\myTemplates\MyTemplate.html
you would use the following entry for the relative path in the properties
files:
...0= templates.myTemplates.MyTemplate...
5. Add view-based links to the navigation bar so your new page can be opened
using the following steps:
a. Open the file wt.enterprise.UrlLinkResource.java.
b. You must have a static String that is a reference to your business object.
For purposes of this example, assume that MyPart is the business object.
The entry should look like the following:
public final static String MYPART_ACTIONS = "11";
c. Fill in the method valid( Object object ). The purpose of this method is to
check if the given action is valid on the current class.
d. Fill in the method enableable( Object object ). The purpose of this method
is to check if the given action is currently valid on the given object.
e. Fill in a value for the CONTEXT_SERVICE_NAME that is unique to
your subclass of ActionDelegate.
f. Fill in the method getServiceName to return
CONTEXT_SERVICE_NAME. That is, the single line in this method
should be as follows:
return CONTEXT_SERVICE_NAME;
h. Fill in the stub method URL( Object object ) . First, make a call to the
enable() method in the parent ActionDelegate class, for example:
Boolean validation = enableable(object
if (validation == null || !validation.booleanValue
{
throw new WTException(RESOURCE,
enterpriseResource.ERROR_INITIALIZING,param);
}
wt.services/svc/default/wt.enterprise.URLActionDelegate/
<CONTEXT_SERVICE_NAME>/java.lang.Object/
0/<URLActionDelegate subclass>/singleton
ii. Put the following code in the no-arg constructor of your subclass of
DefaultTemplateProcessor:
getHtmlTemplateFactory().setNameProcessor( this );
htmlTemplateFactory.setState( getState() );
htmlTemplateFactory.setLanguagePreferences( req );
The String "Your desired entry" is returned. The default implementation will have
all occurrences of the period (".") replaced by the slash character ("/") in the String
"Your desired entry".
Note: The String that results after this replacement must represent a relative path
from /codebase/ to some HTML template file.
Available Parameters
The following parameters are available:
PAGE_EXPIRATION
Specifies in milliseconds the expiration time of the HTML page that is
generated. There are set/get methods for this parameter.
PageExpirationResource
String that represents a name in the wt.properties file. If you set this
parameter, DefaultTemplateProcessor looks for the value of this parameter in
wt.properties and, if found, uses it to set the page expiration time.
Overview
The following code represents the default usage of the HTML template factory.
The comments describe the activity represented by the method call that follows.
// The initial construction of the default implementation
// of the AbstractHTMLTemplateFactory
DefaultHTMLTemplateFactory defaultHTMLTemplateFactory =
getHtmlTemplateFactoryStatic();
Default Usage
The standard usage of DefaultHTMLTemplateFactory is represented in the
following examples. These examples cover the three contexts that can occur when
retrieving an HTML template. In these examples, the request object is an instance
of a wt.httpgw.HTTPRequest object.
HTMLTemplate template =
defaultHTMLTemplateFactory.getHTMLTemplate();
You would have to create the following application context service property,
mapping the action and object to a template:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
ObjProps/wt.part.WTPart/
0=templates.myProperties.myPartPropertiesPage
HTMLTemplate template =
defaultHTMLTemplateFactory.getHTMLTemplate();
You would have to create the following application context service property,
mapping the action and object to a template:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
ObjProps/wt.doc.WTDocument/
0=templates.myProperties.myDocumentPropertiesPage
The following HTML template file (or the correctly localized version of it) would
be searched for:
Windchill/codebase/templates/myProperties/
myDocumentPropertiesPage.html
HTMLTemplate template =
defaultHTMLTemplateFactory.getHTMLTemplate();
The following HTML template file (or the correctly localized version of it) would
be searched for:
Windchill/codebase/templates/myProperties/
mySimplePropertiesPage.html
By default, a period (".") in the property is replaced with a slash ("/") and then that
String is used as a relative path to the HTML template file.
HTMLTemplate template =
defaultHTMLTemplateFactory.getHTMLTemplate();
The following HTML template file (or the correctly localized version of it) would
be searched for:
Windchill/codebase/templates/myProperties/
mySimplePropertiesPage.html
By default, a period (".") in the property is replaced with a slash ("/") and then that
String is used as a relative path to the HTML template file.
Before Starting
Before starting this example, open your wt.properties file and add the following
line as the last entry:
wt.template.cache.enabled=false
Note: This property should be set to "false" for development, but would normally
be "true" in production mode.
This method determines whether the current action is valid on the current
object type.
10. In NewActionDelegate, fill in the enable method stub with the following code
(also found in customization/HTMLClient/Example2.doc under the heading
"enable Method"):
if( object == null )
{
throw new WTException( null, "wt.clients.doc.DocRB",
wt.clients.doc.DocRB.NO_DOCUMENT_TO_UPDATE, null );
}
if (!(valid(object).booleanValue())) { //is it Workable
if (!(wt.access.AccessControlHelper.manager.hasAccess(
object,wt.access.WTPermission.MODIFY))) {
String action = wt.util.WTMessage.getLocalizedMessage(
"wt.enterprise.enterpriseResource",
wt.enterprise.enterpriseResource.MODIFY,
null);
Object[] param = { action };
throw new WTException("wt.enterprise.enterpriseResource",
wt.enterprise.enterpriseResource.NOT_PERMITTED,
param);
}
(wt.access.AccessControlHelper.manager.hasAccess(object,
wt.access.WTPermission.ADMINISTRATIVE)) &&
(
(wt.vc.wip.WorkInProgressHelper.isCheckedOut((
wt.vc.wip.Workable)object)) &&
(!wt.vc.wip.WorkInProgressHelper.isCheckedOut((
wt.vc.wip.Workable)object,
wt.session.SessionMgr.getPrincipal()))))))
{
Object[] param = {
((wt.fc.WTObject)object).getDisplayIdentity() };
throw new WTException("wt.enterprise.enterpriseResource",
wt.enterprise.enterpriseResource.CHECKIN_FAILED,
The enable method determines if the current action should be enabled on the
current object based on the current object’s state and the current user’s
permission.
11. In NewActionDelegate, add the following field (also found in
customization/HTMLClient/Example2.doc under NewActionDelegate Field)
in the Rose-generated user.attributes section:
public static final String CONTEXT_SERVICE_NAME = "NEWACTION";
13. In NewURLActionDelegate, fill in the URL method stub with the following
code (also found in customization/HTMLClient/Example2.doc under the
"URL Method"):
Object[] param = {this.getClass().getName ()};
Boolean validation = enableable(object);
if (validation == null || !validation.booleanValue())
{
throw new WTException("wt.enterprise.enterpriseResource",
wt.enterprise.enterpriseResource.ERROR_INITIALIZING,
param);
}
props.put("oid",oid);
Class urlp = Class.forName("wt.enterprise.URLProcessor") ;
url = wt.httpgw.GatewayURL.buildAuthenticatedURL
(urlp.getName(),"generateForm", props);
Replace <DelegateHandle> with the name of the handle you gave your
ActionDelegate in step 11 earlier in this example.
You must replace <DelegateHandle> with the name of the handle you gave
your URLActionDelegate in step 11 earlier in this example.
The ActionDelegateFactory and the URLActionDelegateFactory should now
be able to find your new ActionDelegates in the <DelegateHandle>/<Class>
that you specified in the new property.
See the section, Properties and Property Files for information on how to add
new properties to the system.
<SCRIPT LANGUAGE=Windchill>
wt.htmlutil.HtmlUtil createBase
</SCRIPT>
<HEAD>
<HTML>
<SCRIPT LANGUAGE=Windchill>
<!--
showResponseHeaders
-->
</SCRIPT>
<SCRIPT LANGUAGE=Windchill>
<!--
showResponseExceptions
-->
</SCRIPT>
</SCRIPT>
<TR ALIGN=LEFT>
<TD ALIGN=RIGHT VALIGN=TOP WIDTH=15%
BGCOLOR=<SCRIPT LANGUAGE=Windchill>getWCColor styleClass=
bg-navbar</SCRIPT> CELLPADDING=0 CELLSPACING=0>
<TR><TD>
<TABLE BORDER="0" CELLPADDING="1" WIDTH="500">
<TR><TD ALIGN=LEFT BGCOLOR=<SCRIPT LANGUAGE=Windchill>getWCColor styleClass=
bg-pagetitle</SCRIPT> HEIGHT="30">
<B><FONT SIZE="3" COLOR=<SCRIPT LANGUAGE=Windchill>getWCColor styleClass=
f-pagetitle</SCRIPT> >
<H2>Update Document</H2>
</TD></TR>
</TABLE>
</TD></TR>
<TR><TD>
<TR>
<TD ALIGN=RIGHT>
<B><FONT>Department:
</TD>
<TD>
<SCRIPT LANGUAGE=Windchill>
enumeratedTypeMenu propertyName=department
</SCRIPT>
</TD>
</TR>
<TR>
<TD ALIGN=RIGHT>
<B><FONT>Title:
</TD>
<TD>
<INPUT NAME = "title" TYPE="text" SIZE=50 VALUE="<SCRIPT LANGUAGE=
Windchill>contextualValue propertyName=title</SCRIPT>">
</TD>
</TR>
</TABLE>
</TD>
</TABLE>
</FORM>
</HTML>
2. In the HTML template you just created containing the preceding code, locate
the <Form action=... section and replace the <TASK_ACTION> entry
(shown in bold in the preceding code) with some name relevant to the action
you are performing on this page. The <TASK_ACTION> value will be used
in the next stage of the process to locate the FormTaskDelegate that processes
the HTML form.
3. Save the file under the codebase directory. You now have a new HTML
template file.
Replace <FORM_ACTION>. The correct value comes from the value used to
replace the <FORM_ACTION> entry in the URLActionDelegate’s URL
method in step 13 of the example.
You must also fill in <FORM_TEMPLATE_NAME> with the relative path
of the HTML template that you created in the previous action. You must use
the period (.) as a directory separator and leave off the file extension. For
example, the following path:
templates/ObjectProperties/WTPart.html
See the section, Properties and Property Files for information on how to add
new properties to the system.
7. Compile the new Java file. You now have a new template processor.
setContextAction("<RESPONSE_ACTION>");
return;
d. Add a new class and give it the desired name, for example,
MyFormTaskDelegate, and have it subclass FormTaskDelegate:
See the section, Properties and Property Files for information on how to add new
properties to the system.
The role of the FormTaskDelegate is to perform some desired action based on the
information in the querystring and the Form data. After processing the data and
performing an action, the FormTaskDelegate returns control to the method in
URLProcessor that called it. Prior to returning, the FormTaskDelegate should
ensure that the current context stored in the HTTPState object is current. This is
necessary because URLProcessor uses the HTTPState object to decide how to
generate a response page. The following is a summary of the responsibilities of
the FormTaskDelegate:
• Validate the Form Data/queryString and respond accordingly.
• Perform the desired action.
• Add any message to be passed back and displayed in the response page with
the service methods.
• addToResponseHeaders, addToResponseFooters, and
addToResponseExceptions. (Use addToResponseExceptions to capture non-
terminal exceptions and display them in the response page.)
To generate such a URL dynamically instead of hard coding it, you can use
the following Windchill script call:
<FORM name="myform" action="<SCRIPT
language=Windchill>getURLProcessorLink method=processForm
action=MyAction</SCRIPT>" method=POST>
The result of this call after processing by the Windchill system is as follows,
assuming the context object of the page has an attribute named "number" and
the value of that attribute is 11053:
<INPUT name="number" type="text" value="11053" >
This type of element results in a button with the title of your choice. When
you click the button, the HTML form is read by the browser and sent to the
URL that appears in the action attribute of the FORM tag.
• The other case involves using JavaScript to perform some intermediate steps
before submitting the HTML FORM. This second, and more flexible way to
submit the form, is to have an HTML tag for the button that looks like the
following:
<INPUT type=button VALUE=" Ok " onclick="checkForm(this)">
In this case, a button is presented but, instead of the browser submitting the
form directly, a JavaScript method is called. The JavaScript should look like
the following:
<SCRIPT LANGUAGE="JavaScript1.1">
<!--
function checkForm( button )
...
With a call like this, you can perform client-side validation of the entries.
or
wt.services/rsc/default/<Resource Name>/<Requestor>/<Selector>
| null/<Search Order Number>=<Resource Name>
The first format is used to locate a Java service or delegate class to perform a
function or provide a service. The second format is used to locate a resource file -
-- for example, a HTML template file or an icon image file
Definitions:
Service Type = the type of service or delegate referenced by
this property
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:
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 the
Application Developer’s Guide for more information on xconf files.
If you need to add service property entries for your custom HTML clients, we
recommend you put them in a new properties file or files used only for your
<Property targetFile="codebase/wt.properties"
value="htmltemplate.properties,…,
com/ptc/windchill/pdmlink/tutorials/pdmlinkTutorials.properties,co
m/MyCompany/MyCompany.properties"
name="wt.services.applicationcontext.WTServiceProviderFromProperti
es.customPropertyFiles"/>
Note: The text in italics in this example should be replaced with the existing list
of customPropertyFiles in your wt.properties file. The objective is to add your
new file to the existing comma-separated list of files for that property.
After adding this entry, back up your wt.properties file and rebuild your system
property files by running the command:
xconfmanager –p
Note: Tags you add to site.xconf should be placed within the existing
<Configuration> tag.
Once you have added your property file to the customPropertyFiles list, you can
create and add entries to your properties file directly, or you can create and add
properties to it using the site.xconf file. For example, if you wanted to add a new
<Resource context="default"
name="wt.templateutil.DefaultHTMLTemplate"
serviceProvider="wtCustom"
targetFile="codebase/com/MyCompany/MyCompany.properties">
<Option cardinality="duplicate"
requestor="java.lang.Object" selector="MyAction"
resource="templates.MyCompany.MyTemplate"/>
</Resource>
<Service context="default"
name="wt.enterprise.TemplateProcessor"
serviceProvider="wtCustom"
targetFile="codebase/com/MyCompany/MyCompany.properties”
>
<Option cardinality="duplicate"
requestor="java.lang.Object" selector=”MyAction”
serviceClass="com.MyCompany.MyTemplateProcessor"/>
</Service>
serviceProvider="wtCustom"
targetFile="codebase/com/MyCompany/MyCompany.properties”
>
<Option cardinality="duplicate"
requestor="java.lang.Object" selector="MYACTION"
serviceClass="com.MyCompany.MyNavBarActionDelegate"/>
</Service>
<Service context="default"
name="wt.enterprise.URLActionDelegate"
serviceProvider="wtCustom"
<Option cardinality="duplicate"
requestor="java.lang.Object" selector="MYACTION"
serviceClass="com.MyCompany.MyNavBarURLActionDelegate"/>
</Service>
These four entries will cause the system to add four properties to
the file <WT_HOME>/codebase/com/MyCompany/MyCompany.properties as
follows:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/MyActi
on/
java.lang.Object/0=MyCompany.MyTemplate
wt.services/svc/default/wt.enterprise.TemplateProcessor/MyAction/
java.lang.Object/0=com.MyCompany.MyTemplateProcessor/duplicate
wt.services/svc/default/wt.enterprise.ActionDelegate/MYACTION/
java.lang.Object/
0=com.MyCompany.MyNavBarActionDelegate/duplicate
wt.services/svc/default/wt.enterprise.URLActionDelegate/MYACTION /
java.lang.Object/
0=com.MyCompany.MyNavBarURLActionDelegate/duplicate
If the property file does not exist, the system will create it.
Note that the resource and service class paths should be given relative to
<WT_HOME>/codebase.
For these changes you make to site.xconf to take effect, you must again rebuild
your property files using the command:
<WT_HOME>/bin/xconfmanager -p
We recommend you back up any property files you are modifying before running
this command.
More than one <Option> tag may be included within a <Service> or <Resource>
tag. The “selector” attribute values for ActionDelegates and
URLActionDelegates should be all upper case.
2. Make your new xconf file known to the system by executing the following
command:
<WT_HOME>/bin/xconfmanager-i
codebase/com/MyCompany/MyCompanyTypedServices.properties.xconf
This will add your xconf file to the list of xconf files in
<WT_HOME>/declarations.xconf
3. Execute the directives in your new xconf file by executing the command:
<WT_HOME>/bin/xconfmanager -p
wt.services.applicationcontext.TypeBasedServiceProviderFromProperties.default
PropertyFiles =
com/ptc/core/command/server/delegate/ServerCommandDelegate.properties,com
/ptc/core/meta/type/command/TypeBasedCommandDelegate.properties,. . .
,typedservices.properties,
com/MyCompany/MyCompanyTypedServices.properties
<WT_HOME>/bin/xconfmanager -i
codebase/com/MyCompany/MyCompanyTypedServices.properties.xconf -p
4. Create your custom properties. Assume you would like
MyCompanyTypedServices.properties to contain the following property
mapping the dropdown action list on the Details pages for the soft type
SpecificationDocument to the tree
SPECIFICATION_DOCUMENT_DROPDOWN_ACTIONS in the file
NavigationAndActions.xml:
wt.services/rsc/default/wt.templateutil.objectPropsActionDropDown/DROPDO
WN/WCTYPE|wt.doc.WTDocument|SpecificationDocument/
0=SPECIFICATION_DOCUMENT_DROPDOWN_ACTIONS
This property can be created in one of two ways:
a. You can create the file
<WT_HOME>/codebase/com/MyCompany/MyCompanyTypedServices.
properties and add the property to it by hand.
b. You can add entries to the file
MyCompanyTypedServices.properties.xconf such that the system will
create the properties file and add the properties to it. To do this you
would add the following tag to the xconf file:
<Resource context="default"
name="wt.templateutil.objectPropsActionDropDown"
serviceProvider="typeBased"
targetFile=
"codebase/com/MyCompany/MyCompanyTypedServices.properties">
<Option
requestor=
"WCTYPE|wt.doc.WTDocument|SpecificationDocument"
resource="SPECIFICATION_DOCUMENT_DROPDOWN_ACTIONS"
selector="DROPDOWN"/>
</Resource>
Note: Any tags you add to your .xconf file should be placed within the existing
<Configuration> tag and that more than one <Option> tag may be included within
a <Service> or <Resource> tag.
SubTemplateProcessing
With the formal encapsulation of the state of a template processor (in the
HTTPState object) comes the ability to pass off the template processing to a
subtemplate processor. The main purpose of this service is to allow the
componentization of the HTML templates and consequently the template
processors themselves. This provides code reuse not through inheritance but
through delegation. Thus, when several HTML pages share a common section,
this section can be factored out into a subtemplate and the Windchill script calls in
that subtemplate can be factored out into a subtemplate. This provides better code
reuse, fewer bloated classes near the top of the inheritance hierarchy (such as
BasicTempateProcessor), and easier HTML template maintenance.
There are two ways to using subtemplate processing:
• Calling the subtemplate service directly in the Java code
• Calling the subtemplate service from a Windchill script call
To make the call to the subtemplate service through a Windchill script, you would
make the following call:
processSubTemplate action=<New ContextAction>
The results of both calls is the same. A template processor is retrieved and an
HTML template is retrieved. The template processor and the HTML template are
retrieved using factories that use the current context as represented in the
HTTPState object. The current context object or context class name is used with
that action that was just passed in.
For example, if the Properties page for a WTPart is being generated, the context
object is the WTPart being presented on the page and the current contextAction is
"ObjProps".
Assume the following Windchill script method was encountered in the HTML
template:
processSubTemplate action=showSubParts
The HTML template that would be looked for would be specified by the following
property:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
showSubParts
wt.part.WTPart/0=<Path to HTML template from codebase>
The HTML template returned would be processed by the template processor that
was returned and the Windchill script call would be replaced with the output of
the processing subTemplate.
After the subTemplate service is finished, the contextAction is returned to the
original action, in this case, "ObjProps".
Then you would call the following specialization of the subTemplate service
through the Windchill script call:
processMySubTemplate action=<New ContextAction>
ProcessorService
This service is very similar to the subTemplateProcessing service. The main
difference is that no subtemplates are processed. The Windchill script call results
in a method on a "service" to be invoked. The invoked method in the service
behaves as if it were a method in the TemplateProcessor.
With the ProcessorService, a method can be taken out of a template processor for
general use, or removed from a common parent class. This allows the
TemplateProcessor class to be more cohesive and allow organizing common
services that all TemplateProcessors use. This creates a more componentized,
cohesive, object-oriented code with greater code reuse.
An example of an implementation of the ProcessorService is the HTML table
service (described in more detail later in this chapter). It is a context-based service
which exists outside of any template processor, is very componentized, and
available to all template processors without burdening BasicTemplateProcessor.
Note: You must model this subclass; otherwise the code will be incomplete.
To access your new Service method, make the following Windchill script call:
useProcessorService service=com.MyCompany.CustomProcessorService
method=<ServiceMethod Name>
The only difference between these two calls is the name/value pair
HelpContext=<Help Context Name>, for example, HelpContext=ViewPart.
Including this name/value pair overrides the default HelpContext of the page.
More detail will be given about this in the section Adding a Property for the Help
Page.
In the preceding entry, the value "142" is somewhat arbitrary. The only restriction
on this value is that some other key in the same resource bundle is not using "142"
as its String value. For most resource bundles, the setting of the key’s String value
is at the top of the file and you scroll down to the bottom of the list and choose the
next, unused number.
This differs from the pattern in which localization is done on the HTML
template pages, that is, files are localized directly, as shown in the following
examples:
/wt/clients/prodmgmt/<userinp>help</userinp>/viewpart.htm
/wt/clients/prodmgmt/<userinp>help</userinp>/viewpart<userinp>_
de</userinp>.htm
/wt/clients/prodmgmt/<userinp>help</userinp>/viewpart<userinp>_
fr</userinp>.htm
…
In this case, your entry in the properties files should have the following
relative file path:
wt.clients.prodmgmt.help.viewpart
anchor name
If your help page has anchors in it and you would like your help page to
appear at that anchor, the HTML help service supports this. Assume you have
the anchor VIEWPARTCONTENTS in the following file:
wt/clients/prodmgmt/help_en/viewpart.htm
In this case, you would modify your entry in the properties file as follows:
wt.clients.prodmgmt.help.viewpart#VIEWPARTCONTENTS
you will have to specify that you want to have an icon appear by passing in the
name/value pair ADD_HELP_ICON=true.
To locate the image to present with the help link, the current context of the
template processor is used in conjunction with the
ContextBasedLocalizedResourceSrv (see Javadoc for more details) to find a
localized version of the image. Otherwise, the non-localized version of the image
is returned. ContextBasedLocalizedResourceSrv looks for the following entry in
service.properties to find the correct image file:
wt.services/rsc/default/LocalizedResourceService/
<Help Context>/<Context Object Class>/0=
<Relative Path from Codebase>
Help Context
The action context to use for the help icon. The default is "HELP". To
override this default, pass in the name/value pair in the Windchill script call
HELP_ICON_SELECTOR=<IconAction Context>.
Context Object Class
The current context object of the page.
Relative Path from Codebase
The path to the image relative to the codebase directory. The file separators in
the path must be replaced with period (.). For example, the following relative
path:
wt/clients/images/helphtml.gif
As opposed to the entries for the HTML templates, you do include the file
extension.
One final option with the addition of the an icon to the help link is whether you
would like the icon on the right or the left of the text (if text exists). This can be
controlled by passing in the name/value pair HELP_ICON_POSITION=right/left
in the Windchill script call.
For this to work in Netscape, you must have the button inside the <FORM> and
</FORM> tags. That is, the button must be inside an HTML form block.
Note that the HelpContext parameter is not required unless you would like to
override the default context of the HTML page being generated.
Adding the resource bundle entry and the help page property are the same as
described in the earlier section.
If you set the value to false, the default is to not present the link.
• You have an entry in one of the properties files the corresponds to the context
of the HTML page. That is, there is an entry matching the value of
getContextAction and either getcontextObj or getContextClassName (if
getContextObj() == null).
The Components
The HTML components are styled after the Java UI AWT components. A parent
class has most of the default behavior and defines the base interface for an HTML
component. The class wt.templateutil.components.HTMLComponent plays the
same role that java.awt.Component does. All of the HTML components subclass
HTMLComponent. This mirrors the AWT where all of the UI components
subclass the java.awt.Component class.
Sets the value of the FONT attribute, COLOR, to the value of green.
Some default behavior also defined by the HTMLComponent class should be
inherited by all of the subcomponents. Following are some of those default
behaviors:
• The initialization of tag attributes by default entries in wt.properties
• The processing of the properties passed in the init method call
• The calling of subcomponents during the showSubComponents call
For example, the following entry specifies that the HTML table would have a
border of size=0:
wt.templateutil.component.TABLE.BORDER=0
The HTML tag is retrieved from the subcomponent by defining the method public
String getTag(). The list of tag attributes to be read are set by the public void
setTagListArray() method.
Basic Usage
The factory class, wt.templateutil.components.HTMLComponentFactory, is
responsible for retrieving HTML components based on a String specifying some
context, and a class specifying the class of the object to be presented. For
example, if an attribute of type java.sql.Timestamp is to have its value displayed,
then the following pair:
Context = null
Class = java.sql.Timestamp
should find an HTML component that knows how to present an object that is of
type java.sql.Timestamp in a desired HTML format. The factory looks for these
values in the file /codebase/htmlcomponent.properties. The general entry in the
file /codebase/htmlcomponent.properties looks like the following:
wt.services/rsc/default/wt.templateutil.components.HTMLComponent/
<Context>/<Display Class>/0=<HTML Component class to be used>
The HTML component that is returned has not been initialized. It is simply
instantiated.
The HTMLTable
The role of the HTMLTable class is to print out an HTML table. The HTML table
is based on the JTable in the Java Swing package. The main point is that the
HTMLTable uses the Model-View-Control (MVC) paradigm. The model in this
case is the javax.swing.table.TableModel. The view is presented by the
cooperative effort of the HTMLColumnTableModel, the HTMLTableColumn,
and HTML components. The HTMLTable is the controller and handles the
interaction between the TableModel, the view, and input (such as, settings in an
HTML template).
The following is a brief description of the key classes and their roles in generating
an HTML table:
HTMLTable
This class is the controller of generating the HTML output. It communicates
between the TableModel, which has the data, and the
HTMLTableColumnModel, the view. The values for attributes for the HTML
element, TABLE, are also controlled here.
TableModel
Represents the data model for the data to be presented. The columns and the
individual cells of data within the columns are controlled here.
HTMLTableColumnModel
Represents the view model for the columns that will be presented. The
columns and the order of the columns to present from the TableModel are
maintained here.
HTMLTableColumn
Represents a logical column within the HTMLTable. Sometimes the
HTMLTableColumn is generated as more than one HTML column, but the
information is presented as a single column with a single header. General
attributes of the column can be maintained here. The object to present as the
header is controlled here. The ability to associate a custom header component
and a custom cell component with the column is also available.
Standard Actions
The following are some of the actions that are available through the Windchill
scripts:
SHOW
This call invokes the show method on the HTMLTable instance that this
service is managing.
ADDCOLUMN
This should be called if your implementation of the Swing TableModel
supports adding a new column (the TableModel interface does not define this
action).
DELETECOLUMN
This removes the column from the set of columns to display that
HTMLTableColumnModel maintains. It does not delete the column from
TableModel.
MOVECOLUMN
Exchanges the View position of two columns. The position in the TableModel
is not affected, but the position in the HTMLTableColumnModel is. The
result is that the positions of the two columns are switched in the visual
presentation.
SETTABLEATTRIBUTES
If there are attribute values that you want to pass on to the HTML Table (such
as, the TABLE tag attributes), you can do that with this call.
The preceding actions are a subset of those available in the BasicTableService.
More specialized services are also available in the AssociationListTableService
and the ListContentTableService.
if ( props == null )
{
props = new Properties();
}
DefaultHTMLCellComponent cellComponent1 =
new DefaultHTMLCellComponent();
cellComponent1.init( selector, null, componentFactory, mode,props );
DefaultHTMLCellComponent cellComponent2 = new
DefaultHTMLCellComponent();
cellComponent2.init( selector, null, componentFactory, mode,props );
In the preceding code, the same properties object is passed to the subcomponents
as is used by the parent component. This allows the cascading of the serviceName
and any default values for the tag attributes.
In this example, the getObjectIconImgTag call returns a String with the URL of
the desired icon. Note the call to the super.startComponent(...). After resetting the
value of the tag attribute, the call to the super results in using the
HTMLComponent’s implementation of startComponent that will enumerate
through the tag attributes that are set and present them.
You can also call the setTagValue directly on the HTML component. You
should do this only after the init method is called. The following is some
sample code:
HTMLFontComponent newFont = new HTMLFont();
newFont.init(selector, value, componentFactory, mode, props );
newFont.setTagValue( HTMLFontComponent.COLOR,
BasicTemplateProcessor.getWCColor("f-label"));
• Passing in values on the properties object passed into the init method
(overrides default values)
The syntax used for specifying tag attribute values passed on the properties
object differs from that used for the direct method. When passing in values in
the properties object through the init method, use the following syntax:
props.put(<Element tag>.<Attribute Name>,<Value>, );
For example, the following is a valid entry:
props.put("TD.BGCOLOR",
BasicTemplateProcessor.getWCColor("t1-bg-evenrow"));
Many of the base HTML components have convenience static Strings to deal
with this syntax. Following is an example:
props.put(HTMLTableCellComponent.TD_ALIGN , "RIGHT");
Note, however, that there is not full support of these convenience Strings.
These are the entries with which all HTML components are initialized.
To switch to a different set of default values for your HTML component, you
must set the value of the serviceName field. There are two ways to change the
serviceName so that a custom set of initial values are set: directly setting the new
service name and cascading the new service name.
Note that the default setting for all components is true unless overridden.
Note that the default setting for all components is false unless overridden.
Examples
The following is an example of initializing an instance of
wt.enterprise.table.WTHtmlTable and printing out the table in a step by step
manner:
HTMLTable table = new HTMLTable();
RowDataTableModel tableModel = new RowDataTableModel();
tableModel.setRowDataObjects( resultVector ); //List of Windchill
// Business objects that represent the rows
tableModel.setTableColumns( namesVector ); // List of
// names(attributes) that represent the columns
table.setTableColumnModel(new DefaultHTMLTableColumnModel() );
table.setTableModel(tableModel);
table.createDefaultColumnsFromModel();
table.setOutputStream( os );
table.setLocale( locale );
table.init( null, null, null, null, null ); // For the presentation
// of a stand alone table, the init does not do anything
table.show();
To create this second table, the printRow method was overriden so that each
logical row in the TableModel resulted in two physical rows in the generated
table. The essential part of the code is as follows:
public String printRow( int rowNumber, Object value,
Properties formData )
{
super.printRow(rowNumber, value, formData);
PrintWriter print_writer = getPrintWriter(getOutputStream(),
getLocale() );
print_writer.print( super.printRow (rowNumber, null, formData) );
print_writer.println("<TR>");
// Customized second row of the logical row
...
// Now close the row
print_writer.println("</TR>");
print_writer.flush();
If you would like to see more information of the 00041 change proposal, you
might click on the purple arrow to the right of the Change Proposal to expand the
change proposal. The resulting page looks like the following figure:
The code to provide this expand/contract ability has the following basic form:
public String printRow( int rowNumber, Object value,
Properties formData )
{
super.printRow(rowNumber, value, formData);
PrintWriter print_writer = getPrintWriter(getOutputStream(),
getLocale() );
print_writer.print( super.printRow (rowNumber, null, formData) );
Boolean expand = new Boolean( getFormData().getProperty( EXPAND ));
if (expand.booleanValue() )
{
print_writer.println("<TR>");
// Customized second row of the logical row
// In this case, processing a subtemplate is done to generate the
// values.
startStr.append( "<" );
startStr.append( getTag() );
startStr.append( "" );
After this, your HTMLTable can be manipulated by Windchill script calls using
the API mentioned above. To show your HTMLTable, use the Windchill script
call with action=show.
Once you have registered for this service, you have a number of actions you can
take on the table to modify its presentation. These will be discussed in the
following section on the HTML table service.
Overview
This section gives more detailed instructions on how to use the HTML table
service. For a general overview, see the section earlier in this chapter on the
overview of HTML components, tables, and the table service. For more detailed
information on how the functionality for the HTML table service was actually
implemented in Windchill, see the section on HTML Table Generation and Table
Service Implementation, later in this chapter.
The HTML table service is essentially a Windchill script API to affect the
presentation of HTML tables. The Windchill script call always has the following
format:
tableService action=<Name of Action> <Additional Name/Value Pairs>
The service is an event-based service that has its listeners registered through
wt.properties. More listeners (that is, services) can be created and registered.
Several services are available in Windchill currently. The following three are
discussed in this section:
• BasicTableService
• AssociationListTableService
• ListContentTableService
BasicTableService
This service represents the basic services that you would want for most
HTMLTables. There might be some additional interfaces that you need to
implement in either your HTMLTable subclass or your TableModel
implementation for some of the actions. Default implementations of these
interfaces are available currently.
All of the services available in the BasicTableService and the interfaces required
for some of the services are not discussed in this manual. For a more detailed
description of the Windchill script calls and the interfaces implementations
required to use them, see the Javadoc for these classes. This section simply lists
the actions that are available:
SHOW
This call invokes the show method on the HTMLTable instance that this
service is managing.
ADDCOLUMN
You can call this if your implementation of the Swing TableModel supports
adding a new column (the TableModel interface does not define this action).
Note that each line of the Windchill script should begin with "tableService". If
you cut and paste the preceding code without removing the additional line wraps,
you will get exceptions. In particular, the lines that begin with
"OTHERSIDECLASS" and "linkattributes" are wrapped lines.
The following is an example of using the AssociationListTableService that uses a
subclass of BaseQueryService -- RelevantChangeables specifically -- to perform
the navigation. A UML diagram of the RelevantChangeables is presented below
the Script calls.
<SCRIPT LANGUAGE=Windchill>
<!-
tableService action=initAssociationNavigation BASEQUERYSERVICE=
RelevantChangeables ROLE=theChangeable2
LINKCLASSNAME=wt.change2.RelevantAnalysisData
OTHERSIDECLASS=wt.change2.
tableService action=setAssociationTable ASSOCIATIONTABLE=
wt.change2.htmlclient.
As before, note that each line of the Windchill script should begin with
"tableService". If you cut and paste the preceding code without removing the
additional line wraps, you will get exceptions. In particular, the lines that begin
with "ROLE" and "table." are wrapped lines.
The following figure is a UML diagram showing the structure of the
BaseQueryService. The QueryServiceProvider can locate a modeled subclass of
BaseQueryService using the name of the class only. If you have not modeled the
class, the QueryServiceProvider requires the fully qualified class path for the
class.
ListContentTableService
This service is an implementation of an HTML table service that provides special
support for presenting the contents of a ContentHolder. The content is retrieved
from the current context object of the TemplateProcessor instance making the
Windchill script calls. For example, if you are looking at the properties page for a
WTPart, the context object is the WTPart whose properties are being displayed.
This is also the object from which the list of content is retrieved.
The primary function of this service is to allow the retrieval of the contents -- both
UrlData and ApplicationData -- and present those two sets of contents in two
tables. One table is for the UrlData and one table is for the ApplicationData. The
presentation and display characteristics of the tables are controlled separately. The
tables can look the same or they can look different. The tables can be presented
one after the other or in different parts of the page.
After this call, the URLData contents and the ApplicationData contents are
available to be displayed. There is a call to initialize the HTMLTable object for
each type of content. This allows the two tables to be controlled, both in style and
position, separately.
For URLData, the following call initializes a WTHtmlTable to present the
URLData:
tableService action=initURLDataTable URLDATAATTRIBUTES=
urlLocation, description
Note that each line of the Windchill script should begin with "tableService". If
you cut and paste the preceding code without removing the additional line wraps,
you will get exceptions. In particular, the lines that begin with
"APPLICATIONDATAATTRIBUTES" and "RESOURCEBUNDLE" are
wrapped lines.
The following actions are supported in the AssociationListTableService:
INITIALIZECONTENTS
This call takes the current context object of the template processor and, if the
context object is a context holder, the ApplicationData and the URLData are
retrieved.
INITAPPLICATIONDATATABLE
This call initializes an instance of a WTHtmlTable with the
RowDataTableModel and the ApplicationData. Windchill script calls can
now be made to affect the presentation of the table. This call should be made
only after the INITIALIZECONTENTS action is called.
<SCRIPT LANGUAGE=Windchill>
<!-
tableService action=initAssociationNavigation ROLE=uses
LINKCLASSNAME=wt.part.WTPartUsageLink OTHERSIDECLASS=
wt.part.WTPartMaster
tableService action=initAssociationTable othersideattributes=name,
number,type linkattributes=modifyTimestamp,quantity
USECHECKBOXTABLE=true
tableService action=setHeaderFromResource COLUMNNAME = checkBox
RESOURCEBUNDLE=wt.clients.change2.Change2RB
RESOURCEKEY=REMOVE
tableService action=show
-->
</SCRIPT>
</FORM>
The following is a skeleton implementation of the code that will process the
information sent back from the table generated by the preceding steps. The
method, processSelections, is responsible for processing the resulting list of
objects. The entry will be part of defining how the response page is generated.
public void processAction( ContentHTTPStream contentStream )
throws Exception
{
try
{
selections.addElement(ref.getObject());
}
}
return;
}
catch (WTException wte)
{
wte.printStackTrace();
addToResponseFooters((LocalizableMessage)wte);
setContextAction( "CreateAssociationFailed" );
}
<SCRIPT LANGUAGE=Windchill>
<--
tableService action=initializeContents
tableService action=initURLDataTable USECHECKBOXTABLE=true\
URLDATAATTRIBUTES=urlLocation,description
tableService action=show
-->
</SCRIPT>
<SCRIPT LANGUAGE=Windchill>
<!--
tableService action=INITAPPLICATIONDATATABLE USECHECKBOXTABLE=true
APPLICATIONDATAATTRIBUTES=fileName,format,fileSize,
modifyTimestamp,createdBy
tableService action=show
-->
</FORM>
Overview
Currently, if a name/value pair display of an attribute on the current Context
Object of the page is desired, the following lines of HTML code are used:
<TR>
<TD ALIGN=RIGHT>
<B>
<SCRIPT LANGUAGE=Windchill>
<!--
objectPropertyName propertyName=lifeCycleState
-->
</SCRIPT>:
</B>
</TD>
<TD>
<SCRIPT LANGUAGE=Windchill>
<!--
objectPropertyValue propertyName=lifeCycleState
-->
</SCRIPT>
</TD>
</TR>
This process for displaying the name/value pair can be overridden in two ways:
• Go into the existing source code and make changes or override certain
methods in your template processor (this method is not preferred).
• Use the HTML components and create a component to handle generation of
the HTML for you (this method is preferred).
The remainder of this section discusses the steps involved in creating an
HTML component and using it to override the default name/value display
generation.
In this case, the <Class of Attribute> refers to the return type of the getter
method for the attribute. The current default entry is as follows:
wt.services/rsc/default
/wt.templateutil.components.HTMLComponent/NAME/
java.lang.Object/0= wt.templateutil.components.NameComponent
In this case, the Class of Attribute refers to the return type of the getter
method for the attribute.
One current default entry is as follows:
wt.services/rsc/default/wt.templateutil.components.HTMLComponen
t/ null/java.lang.Object/0
=wt.templateutil.components.DefaultBusinessComponent
When overriding the name display, the <Class of Attribute> value refers to the
return type of the getter method. If you want to write some generically available
component that is based solely on the <Service_Name> and does not select based
on class, you could set the <Class of Attribute> equal to java.lang.Object.
When overriding the value display, the <Class of Attribute> value refers to the
return type of the getter method.
The primary methods to override are the init method and the startElement
method, and possibly the showSubComponents. The init method is
overridden so that a subcomponent can be added. Then, when the
showSubComponents method is called, the added subcomponent will
generate HTML. The subcomponent will generate the correct text which will
appear as the hyperlinked text in the link. The startcomponent will be
overridden to generate the correct link by setting the value of the href attrbute.
(The source file is attached at the end of this section.)
After creating the source for wt.templateutil.components.MyLinkComponent,
compile it.
3. Add an application context service property (all on one line) with the
following form:
wt.services/rsc/default/
wt.templateutil.components.HTMLComponent/
MyLink/wt.state.State/
0=wt.templateutil.components.MyLinkComponent
import java.lang.String;
import wt.templateutil.components.HTMLLinkComponent;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;
import java.util.Properties;
import wt.htmlutil.HtmlUtil;
import wt.httpgw.GatewayServletHelper;
import wt.templateutil.processor.PageContext;
import wt.templateutil.processor.HTTPState;
import wt.templateutil.table.WTAttribute;
import wt.util.WTException;
import wt.util.WTMessage;
import wt.util.WTProperties;
/**
*
* This class is a demonstration of how to implement adding a link to an
* attribute that is being displayed in an Object Properties page. This
* extends the wt.templateutil.components.HTMLLinkComponent class because
* the main purpose of this class is to wrap the display value in a link.
*
* @version 1.0
**/
static
{
try
{
WTProperties properties = WTProperties.getLocalProperties();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
throw new ExceptionInInitializerError(t);
}
/**
* This method overrides the default implementation to add a subcomponent
* to this component.
* The subcomponent will be responsible for presenting the text to be
* displayed in the
* link in the Object Properties page.
*
* @param selector The String used by the HTMLComponentFactory
* @param value The object used by the HTMLComponentFactory
* @param componentFactory The current instance of the
* HTMLComponentFactory, if available
* @param mode Can be used to indicate is the current mode is
* View or Update
* @param props The Properties object passed in by the Windchill
* Script call.
**/
public void init( String selector, Object value, HTMLComponentFactory
componentFactory, String mode, Properties props )
{
if (VERBOSE)
{
System.err.println("\n\n MyLinkComponent : in init \n\n");
}
/**
* This method is responsible for generating the starting tag for an
* HTML Element.
* In the case of a link, the starting tag would begin as,
* <a href=...>. This
* method is responsible for generating this starting tag.
*
* @param value The object of current interest
* @param formData The formData from the HTTP Request
* @param os The OutputStream of the HTTP Response
* @param locale The current Locale of the HTML Template
if (VERBOSE)
{
System.err.println("\n\n MyLinkComponent : in startComponent \n\n");
}
// Set the name/values pairs to appear on the Query String on the URL
try
{
Windchill Stylesheet
The color, font, and other style attributes of Windchill PDM page elements can be
set by referencing the style classes in the Windchill stylesheet, WTDefault.css,
which is located in Windchill/codebase. For further information on the application
of style classes, see the section on Customizing Colors in HTML and JSP Clients
in chapter 4.
<HEAD>
.
.
.
<LINK rel="stylesheet" type="text/css" href="WTDefault.css">
.
If the HTML template does not have a createBase call, the href attribute should
contain the stylesheet path relative to the current page, for example:
../../WTDefault.css
This script call has a required parameter "style class" to indicate the style class
name of the desired color and an optional parameter "quotes" to indicate whether
single, double, or no quotes are desired around the color hexadecimal number
string written to the page.
Following is an example of usage:
<BODY BGCOLOR=<SCRIPT LANGUAGE=Windchill>getWCColor styleClass=
bg-body</SCRIPT> TEXT=<SCRIPT LANGUAGE=Windchill>getWCColor
styleClass=f-body</SCRIPT> >
This method can also be called recursively to override default colors used by the
Windchill HTML Table Service. For example:
<SCRIPT LANGUAGE=Windchill>
<!--
showObjectSearch
tableService action=setHeaderAttributes COLUMNNUMBER=
ALL th.ALIGN=left font.size=2 recurse.th.bgcolor=
"wt.enterprise.BasicTemplateProcessor getWCColor styleClass=
bg-hilite1"
tableService action=show
-->
</SCRIPT>
In a similar manner, the font face attribute can be generated with the following
script call:
public void getWCFontFamily(Properties parameters, Locale locale,
OutputStream os)
This does not have a style class parameter but does have an optional "quotes"
parameter.
For example:
<HEAD>
<STYLE TYPE="text/css">
<!--
P,FONT,B {font-family: <SCRIPT LANGUAGE=
Windchill>getWCFontFamily quotes=none</SCRIPT>}
-->
</STYLE>
</HEAD>
The corresponding method to get the font face property value is:
public static String getWCFontFamily()
Overview
The HTMLComponent class is the interface that all HTML UI components must
implement.
This class represents the calls to be made to initialize and present the UI
component, and it provides the structure for embedding UI components within
other UI components. It also provides some default implementations for
initializing and printing the HTML component.
The option exists to override the default values, either through the script calls or
programmatically overriding the values.
This technique was used on the premise that most of the time, if a default value is
to be overridden, it will be from a script call in an HTML template. The name and
values pairs of the Windchill script calls are passed in a Properties object. By
passing in this properties object, override values can be passed in for presentation.
Note: Calling the setTagValue method before calling the init method is not
recommended. The init method overrides any preset values.
HTMLTable
This is the controller in the Model-View-Control (MVC) paradigm. It is
responsible for communicating between the TableModel, the data, and the HTML
View, the generated page. The HTMLTable acts as a proxy for the TableModel
and the HTMLTableColumnModel. This can be seen in the UML model by
looking at how the HTMLTable implements all of the methods in both the
TableModel and the HTMLTableColumnModel. This is how the HTMLTable
provides communication between the TableModel and the
HTMLTableColumnModel. The implementation follows the implementation of
the JTable.
One difference is that there is no event handling because there is no direct user
interaction with the UI. However, after Servlets and JSP are used more
commonly, the URLs might take on a much more event-based context because the
Session context will allow the HTMLTable presented in a Web page to exist
between HTTP requests.
The role of the HTMLTable, like the JTable, is to perform the following
functions:
• Coordinate the communication of the TableModel and the
HTMLTableColumnModel.
• Coordinate the rendering of the HTML Table by looping over the columns
and rows of the HTMLTableColumnModel using the data in the TableModel.
• Provide a default mapping between the data classes in a given cell of the
TableModel and the HTML component used to render the data in the table. In
this case, the HTMLComponentFactory is used instead of a CellRenderer.
HTMLTableColumn
HTMLTableColumn is a base implementation of an object that represents a
column in an HTML table. It maintains the following:
• (Optionally) A header object that is used to generate the title of the column in
the HTML page.
• (Optionally) The HTMLComponent to present the title of the column based
on the value of the header object.
• (Optionally) The HTMLComponent to present the values in the TableModel
for this column.
HTMLComponentFactory
HTMLComponentFactory is the class that is responsible for deciding what
HTMLComponent to use to generate the HTML, based on a value(object) from a
cell in the TableModel. The selection of the HTMLComponentFactory is based on
the class type of the object in the TableModel cell and a String that represents
some context about how the HTML component is to be selected.
The HTMLComponent that is returned from the HTMLComponentFactory is then
used to generate the HTML code to send back to the browser.
Topic Page
Directory Structure ..............................................................................................8-2
Properties and Property Files ..............................................................................8-3
Template Processing Extensions for PDMLink ..................................................8-5
Creating a Table in a Template Processor.........................................................8-34
Common Customizations ..................................................................................8-46
8-1
Directory Structure
The HTML templates, java files, and other files used in PDMLink template
processing are primarily located in the following directories under WT_HOME:
• codebase/templates/HTMLtemplateutil
Templates and javascript common to multiple PDMLink pages -- for
example, the files used to generate the page header, page footer, etc.
• codebase/com/ptc/core/HTMLtemplateutil/server/processor
Processor and delegate classes used to generate and process HTML common
to multiple PDMLink pages - for example, page header and footer, wizard
components, and buttons
• codebase/templates/pdmlink
• Templates specific to each HTML client, organized by functional area
• codebase/com/ptc/windchill/pdmlink/*/server/processors
Processor and delegate classes used to generate and process PDMLink client
pages, organized by functional area
• codebase/wt/templateutil/components
Java classes for components and features that are used primarily for
PDMLink --- for example, the PDMLinkHTMLTable and the actions
dropdown menus, as well as classes used for Windchill PDM features.
• codebase/com/ptc/core/ui
Contains the stylesheet solutions.css used for template processing pages
• codebase/com/ptc/core/ui/images
codebase/wtcore/images
codebase/wt/clients/images
Image files used for PDMLink and other applications
If you must create new templates for your customizations, we suggest you put
them in a new directory under <WT_HOME>/codebase/templates such as
<WT_HOME>/codebase/templates/<MyCompany>, where MyCompany is a
name of your choosing. This will prevent them from being deleted if you reinstall
or upgrade PDMLink. Your site's template directory must be under the
<WT_HOME>/codebase/templates directory.
If you modify out-of-the-box templates you should keep a copy of your modified
templates in a directory outside of <WT_HOME>/codebase because files in
codebase may be deleted if you reinstall or upgrade your PDMLink installation.
If you create new Java processors or delegates for your customizations, we
suggest you put the source code in a new directory used only for your
Template Framework
In general, PDMLink makes greater use of subtemplates than Windchill PDM.
The skeleton template for a typical PDMLink view page follows. Note that
Windchill script method calls must be on one line in practice. They are shown on
multiple lines below only for display in this document.
<html>
<script language=Windchill>
<!--
processSubTemplate action=GetMetaInfo
-->
</script>
<script language=Windchill>
<!--
useProcessorService method=getBaseTag
service=com.ptc.core.HTMLtemplateutil.server.processors.UtilProces
sorService
-->
</script>
<!- The following inserts style sheet links onto the page-->
<script language=windchill>
<!--
useProcessorService method=getCSSLink
service=com.ptc.core.HTMLtemplateutil.server.processors.UtilProces
sorService
-->
</script>
<title><!-- your title goes here --></title>
</head>
<script language=windchill>
<!--
useProcessorService method=getBodyTag
service=com.ptc.core.HTMLtemplateutil.server.processors.UtilProces
sorService
-->
</script>
<!-The following creates the page banner, including Learn, Help and
other links; search component, tabs, second-level navigation bar
under the current tab, and the context title bar under the second-
level navigation bar-->
<script language=windchill>
<!--
processSubTemplate action=CreateBanner
-->
</script>
<script language=windchill>
<!--
processSubTemplate action=CreateFooter
-->
</script>
</body>
</html>
HTML wizards share some of this framework but do not have the banner and
footer components.
Action Configuration
The file codebase/wt/templateutil/NavigationAndActions.xml defines the
following lists of navigation links and actions:
• The links shown in the navigation bar on Details pages
• The actions available in the actions dropdown list on Details pages
• The actions available in the Actions column of a table for an object
• The actions available in the Multiselect actions header of a table
• The actions available in the Context-specific actions header of a table
• The tabs in wizards
Most of these features are shown in the following part Details page:
<NAVIGATION_TREE>
<Name>PR_Details_Actions</Name>
<Links>
<Link>
<Name>Update_PR</Name>
<Action>Update_PR</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.change.server.processors.detailsResource
</Resource_Bundle>
<Resource_Key>0</Resource_Key>
<Links/>
</Link>
<Link>
<Name>Create_New_ECR</Name>
<Action>Create_New_ECR</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.change.server.processors.detailsResource
</Resource_Bundle>
<Resource_Key>2</Resource_Key>
<Links/>
</Link>
<Link>
<Name>Copy</Name>
<Action>Copy</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.core.HTMLtemplateutil.server.processors.processorsResource
</Resource_Bundle>
<Resource_Key>3</Resource_Key>
<Links/>
</Link>
<Link>
<Name>Delete_PR</Name>
<Action>Delete_PR</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.change.server.processors.detailsResource
</Resource_Bundle>
<Resource_Key>48</Resource_Key>
<Links/>
</Link>
com.ptc.windchill.pdmlink.change.server.processors.detailsResource
</Resource_Bundle>
<Resource_Key>55</Resource_Key>
<Links/>
</Link>
</Links>
</NAVIGATION_TREE>
Each action or link in a navigation tree is enclosed in a <LINK> tag. The tags
within a <LINK> node are as follows:
• Name - Used on HTML templates and in processor classes to reference a
particular node. May be any descriptive name for the action, unique within
the tree, but is typically the same as the action name.
• Action - The string used to look up an ActionDelegate and
URLActionDelegate that will determine if the action should be listed for a
specific object/user and create the URL for the link, respectively.
• Tree_Action_Delegate - currently not used
• Method (optional) - If your action invokes a template processing URL, this is
the method in wt.enterprise.URLProcessor that should be called. The default
is URLTemplateAction. See the section ActionDelegates and
URLActionDelegates for more information.
• In_Minimum_List - currently not used
• Resource_Bundle - The *.rbInfo file that contains the string that should be
displayed on the page for this link
• Resource_Key - The number assigned to the string for this link in the *.rbInfo
file
• Links (second level) - currently not used
<Property name="wt.templateutil.components.navigationbar.file"
overridable="true" targetFile="codebase/wt.properties"
value="$(wt.codebase.location)$(dir.sep)com$(dir.sep)
MyCompany$(dir.sep)NavigationAndActions.xml"/>
where the attribute "value" is the path to your customized file. In this example,
the path is
<WT_HOME>/codebase/com/MyCompany/NavigationAndActions.xml.
Once you have added this tag, you must regenerate your site's property files using
the command:
<WT_HOME>/bin/xconfmanager -p
Associates the HTTPState object from the template processor generating the link
with the ActionDelegate.
public void setActionName(String action)
throws WTPropertyVetoException
6. Open the Specification for your new delegate and go to the Windchill tab.
Under Java Properties, set Serializable to None.
7. Generate the package.
10. In the static.initialization section of the file add one new variable as shown in
bold below:
//##begin static.initialization preserve=yes
public static final String CONTEXT_SERVICE_NAME =
"<YOUR_ACTION_NAME>";
//##end static.initialization
13. Modify the valid() method as appropriate for your action. This method should
return true or false depending on whether the action is valid based on the type
of the current object.
14. Modify the enableable() method as appropriate for your action. This method
determines if the action should be enabled based on the current object's state
and the current user's permissions.
15. Complete the getContextServiceName() method as shown in bold below:
public String getContextServiceName() {
package com.ptc.windchill.pdmlink.doc.server.processors;
import java.lang.Boolean;
import java.lang.Object;
import java.lang.String;
import wt.templateutil.processor.HTTPState;
import wt.templateutil.processor.NavBarActionDelegate;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
//##begin UpdateDocumentNavBarActionDelegate%3F89BF3400F2.doc
preserve=no
/**
*
"com.ptc.windchill.pdmlink.doc.server.processors.processorsResourc
e";
private static final String CLASSNAME =
UpdateDocumentNavBarActionDelegate.class.getName();
//##end static.initialization
try {
if (object instanceof Workable) {
return new
Boolean(WorkInProgressHelper.isCheckedOut((Workable)object,
SessionHelper.manager.getPrincipal()));
}
else {
return new
Boolean(AccessControlHelper.manager.hasAccess(object,
AccessPermission.MODIFY));
}
}
catch (Exception e) {
return new Boolean(false);
}
//##end enableable%3645CEB702CE.body
}
return CONTEXT_SERVICE_NAME;
//##end getContextServiceName%36DFF3B50157g.body
}
//##end setContextServiceName%36DFF7E101E4s.body
}
Given the name/value pairs from the query string of the URL,
determines whether the URL was generated by the URL() method of
this delegate.
Sets the integer string of the link label in the *.rbInfo file.
8. Open the Specification for your new delegate and go to the Windchill tab.
Under Java Properties, set Serializable to None.
9. Generate the package.
10. Open the .java file generated for your new NavBarURLActionDelegate in an
editor.
11. In the user.imports section of the file, import the class
NavBarURLActionDelegateHelper shown in bold below:
//##begin user.imports preserve=yes
import wt.templateutil.processor.NavBarURLActionDelegateHelper;
//##end user.imports
12. In the user.attributes section of the file, add a new variable called helper
shown in bold below:
//##begin user.attributes preserve=yes
//##end user.attributes
13. Replace the body of the method isURLProvider() with code appropriate to
your action. The input argument query Value Map contains the name/value
pairs from the query string of a URL (that is, the parameters following the ? in
Object object ) {
return helper.isURLProvider(queryValueMap,object);
//##end isURLProvider%3C425D9802AF.body
this.helper.setResourceKey(key);
//##end setResourceKey%3C425DDE005Ds.body
//##begin setResourceBundleStr%3C425E15036Bs.body
preserve=yes
this.helper.setResourceBundleStr(resourceBundle);
//##end setResourceBundleStr%3C425E15036Bs.body
//##end setState%3C425E5A02BFs.body
this.helper.setMethod(method);
//##end setMethod%3C425E96002Es.body
return this.helper.getActionName();
//##end getActionName%3649F3EC032Cg.body
throws WTPropertyVetoException {
actionNameValidate( a_ActionName );
this.helper.setActionName(a_ActionName);
//##end setActionName%3649F3EC032Cs.body
19. Complete the URL() method so that it returns a URL string which will
execute your action. In this method , you should call the enableable() method
of the NavBarActionDelegate to check whether the current user is permitted
to execute your action. If the action is not enabled, a URL value of null
should be returned.
If your action should invoke a template processing page or delegate, you can
use the NavBarURLActionDelegate helper to help you construct the URL as
follows:
if (enableable(object).booleanValue()) {
helper.setOidAdded(true);
return gwURL;
The method above will produce a template processing url similar to the following:
http://<yourServerMachine>/<webappname>/servlet/WindchillAuthGW/
wt.enterprise.URLProcessor/URLTemplateAction?
action=<yourActionName>&oid=<reference to input object>
If the URL to execute your action is not a simple template processing URL you
will have to write your own method body to construct it. For example, if you want
your action to call a javascript method to open a new window and launch a
template processing Create Document wizard within that window, your URL()
method might look something like this:
"scrollbars=yes,status=yes,toolbar=no,resizable=yes\')";
}
Note: The above URL makes use of the javascript method "launchWindow()"
which should already be included on most PDMLink template processing pages
by virtue of calling the Windchill script method getBodyTag() and which can be
used to launch a new window within a ProE embedded browser or a standalone
browser.
return this.helper.getURLLabel(locale);
//##end getURLLabel%3655D19701F4g.body
21. .In the user.operations section of the file add a constructor method to the class
as shown in bold below:
//##begin user.operations preserve=yes
public CheckInDocumentNavBarURLActionDelegate() {
//##end user.operations
// Generated UpdateDocumentNavBarURLActionDelegate%3F89BFE5023A:
Sun 10/12/03 15:58:45
/* bcwti
*
* Copyright (c) 2003 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.pdmlink.doc.server.processors;
import java.lang.Object;
import java.lang.String;
import java.util.HashMap;
import java.util.Locale;
import
com.ptc.windchill.pdmlink.doc.server.processors.UpdateDocumentNavB
arActionDelegate;
import wt.templateutil.processor.HTTPState;
import wt.templateutil.processor.NavBarURLActionDelegate;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
//##end user.imports
//##begin UpdateDocumentNavBarURLActionDelegate%3F89BFE5023A.doc
preserve=no
/**
*
* <BR><BR><B>Supported API: </B>false
* <BR><BR><B>Extendable: </B>false
*
"com.ptc.windchill.pdmlink.doc.server.processors.processorsResourc
e";
private static final String CLASSNAME =
UpdateDocumentNavBarURLActionDelegate.class.getName();
private String actionName = null;
private String classURL = null;
return this.helper.getActionName();
//##end getActionName%3649F3EC032Cg.body
}
actionNameValidate( a_ActionName );
this.helper.setActionName(a_ActionName);
//##end setActionName%3649F3EC032Cs.body
}
"actionName"),"200"};
throw new WTPropertyVetoException(
"wt.introspection.introspectionResource",
wt.introspection.introspectionResource.UPPER_LIMIT,
args,
new java.beans.PropertyChangeEvent(this,"actionName",
actionName,
a_ActionName));
}
}
return classURL;
//##end getClassURL%3649F452000Fg.body
}
CLASSNAME,"classURL"),"200"};
throw new WTPropertyVetoException(
"wt.introspection.introspectionResource",
wt.introspection.introspectionResource.UPPER_LIMIT, args,
new java.beans.PropertyChangeEvent(this,
"classURL",classURL,a_ClassURL));
}
}
(!WorkInProgressHelper.isWorkingCopy((Workable)object)) ) {
object =
WorkInProgressHelper.service.workingCopyOf(
(Workable)object);
}
ReferenceFactory rf = new ReferenceFactory( );
String oidStr =
rf.getReferenceString((Persistable)object);
URLFactory urlFactory =
this.helper.getState().getURLFactory();
HashMap map = new HashMap();
map.put("action","UpdateDocument");
map.put("oid", oidStr);
URL url=
GatewayServletHelper.buildAuthenticatedURL(urlFactory,
"wt.enterprise.URLProcessor","generateForm",map);
String gwURL = url.toExternalForm();
String windowProperties =
"width=600,height=400,directories=no,location=no," +
"scrollbars=yes,status=yes,toolbar=no,resizable=yes";
jsUrl = "javascript:launchWindow(\'" + url +
",\'UpdateDocWindow\',\'" + windowProperties +
"\')";
}
catch (Exception e) {
throw new WTException(CLASSNAME +
".URL() - exception creating link to
UpdateDocument");
}
}
return jsUrl;
//##end URL%3645CF0A0157.body
}
wt.services/svc/default/wt.enterprise.ActionDelegate/
<YOUR_ACTION>/java.lang.Object/0=
wt.templateutil.processor.DefaultNavBarActionDelegate/duplicate
If the url that should be generated for your action is a simple template processing
url without an oid parameter on the query string, you can use the
wt.templateutil.processor.DefaultNavBarURLActionDelegate for your action.
You would add the following property for your action:
wt.services/svc/default/wt.enterprise.URLActionDelegate/
<YOUR_ACTION>/java.lang.Object/0=
wt.templateutil.processor.DefaultNavBarURLActionDelegate/
duplicate
If the url that should be generated for your action is a simple template processing
url with an oid parameter referencing the current context object on the query
string, you can use the
wt.templateutil.processor.ObjectPropsNavBarURLActionDelegate class for your
action. You would add the following property to your custom properties file for
your action:
wt.services/svc/default/wt.enterprise.URLActionDelegate/
<YOUR_ACTION>/java.lang.Object/0=
wt.templateutil.processor.ObjectPropsNavBarURLActionDelegate/
duplicate
Actions Column
Multiselect Checkbox Column Show/hide Column Icon
Tables
The tables on PDMLink template processing pages are implemented using the
same underlying components and services as those of Windchill PDM, described
in the chapter Customizing the HTML Client in this manual. Some modifications
and enhancements were made to those components for PDMLink, however.
These include the following:
• Style changes to implement PDMLink look and feel
In the picture above, the inner bracket on the right shows the extent of the table
and the outer bracket shows the extent of the expand-collapse section. Creation of
an expand-collapse section is not covered in this guide.
PartDocHelper.service.getAssociatedUpdateableDocuments(part);
Vector rowDataObjects = new Vector();
while (result.hasMoreElements()) {
rowDataObjects.addElement(result.nextElement());
}
// Set the attributes (columns) to display for each object
Vector columnVector = new Vector();
columnVector.addElement("name");
columnVector.addElement("number");
columnVector.addElement("displayType");
columnVector.addElement("containerName");
columnVector.addElement("modifyTimestamp");
table.setMultiSelectActionNavBarName("REMOVE_DOC_RELATION_ACTION")
;
List multiSelectActionList = new ArrayList();
multiSelectActionList.add("RemoveDocRelation");
//getHTMLTableService().setHtmlTable( table );
out.flush();
}
Note: This table has a multiselect actions bar with one action named Remove. It
does not have a context-specific actions bar. If one were desired, it could be
added in much the same way as the multiselect actions bar with code similar to the
following:
For either actions bar you select those links in a tree you want to display using the
multiSelectActionList.add() or actionList.add() methods.
<script LANGUAGE=Windchill>
<!--
tableService ACTION=initAssociationNavigation USEMASTER=true
ROLE=alternates LINKCLASSNAME=wt.part.WTPartAlternateLink
OTHERSIDECLASS=wt.part.WTPartMaster
tableService ACTION=initAssociationTable PDMLINKTABLE=true
NAME=AlternatesTable OTHERSIDEATTRIBUTES=number,name,containerName
USECHECKBOXTABLE=true
tableService ACTION=enableColumnCollapse isEnabled=true
tableService ACTION=enableSorting isEnabled=true
tableService ACTION=defineActionBar
MULTISELECTACTIONNAVBAR=Alternates_MultiSelectActions
MULTISELECTACTIONLIST=DeletePartAlternate
ACTIONNAVBAR=Alternates_ContextActions
ACTIONLIST=AddPartAlternate
tableService ACTION=setColumnAttributes NAME=number,name,containerName
RESOURCEBUNDLE=com.ptc.windchill.pdmlink.part.server.processors.processorsResource
RESOURCEKEY=CONTEXT
tableService ACTION=show
-->
</script
The things that distinguish the above sequence of table service calls from a basic
Windchill table are:
• The attribute PDMLINKTABLE for the initAssociationTable action indicates
a PDMLinkHTMLTableModel should be used
• The USECHECKBOXTABLE, as in Windchill, indicates a checkbox column
should be added to the table. For PDMLink, this column will have an "All"
checkbox at the top.
• The action "enableColumnCollapse" enables collapsing of columns. Column
collapsing is on by default so this action call can be omitted if you want
collapsing enabled. If you want to disable column collapsing, you must
include this call and set isEnabled to false.
• The action "enableSorting" enables sorting by column. Sorting is on by
default so this action call can be omitted if you want sorting enabled. If you
want to disable sorting, you must include this call and set isEnabled to false.
• The action "defineActionBar" defines the multiselect actions and context-
specific actions to be displayed on the actions bar at the top of the table
• The "name" attribute for the call to initAssociationTable provides a unique
name for the table that is used for column sorting and hiding
• As when creating a table programmatically, if you enable column sorting and
collapsing you must include some javascript on your template (see Sorting By
Column and Column Collapsing below).
• You must enclose your table within an HTML <FORM> element if your table
has a checkbox column.
<SCRIPT LANGUAGE=Windchill>
<!--
tableService ACTION=initializeContents
tableService ACTION =initapplicationdatatable
APPLICATIONDATAATTRIBUTES=
fileName,format,fileSize
name=AttachmentsTable PDMLINKTABLE=true
SUPPRESSACTION=true
tableService ACTION =setHeaderFromResource POSITION=0
RESOURCEBUNDLE=
com.ptc.windchill.pdmlink.doc.server.
processors.processorsResource
RESOURCEKEY=FILE_NAME
tableService ACTION =setHeaderFromResource POSITION=1
RESOURCEBUNDLE=
com.ptc.windchill.pdmlink.doc.client.
clientRB
RESOURCEKEY=FORMAT
tableService ACTION =setHeaderFromResource POSITION=2
RESOURCEBUNDLE=
com.ptc.windchill.pdmlink.doc.server.
processors.processorsResource
RESOURCEKEY=FILE_SIZE
tableService ACTION =setHeaderFromResource POSITION=2
RESOURCEBUNDLE=
com.ptc.windchill.pdmlink.doc.server.
processors.processorsResource
RESOURCEKEY=UPDATE_STAMP
tableService ACTION =setHeaderFromResource POSITION=2
RESOURCEBUNDLE=
com.ptc.windchill.pdmlink.doc.server.
processors.processorsResource
RESOURCEKEY=CREATOR
tableService ACTION =setTableAttributes table.WIDTH=100%
tableService ACTION =show
Also the no actions bar is presented at the top of the table because there is no call
to defineActionBar.
<Name>RemoveDocumentRelation</Name>
<Action>RemoveDocRelation</Action>
<Method>processForm</Method>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.change.client.changeRB
</Resource_Bundle>
<Resource_Key>21</Resource_Key>
<Links/>
</Link>
Actions Column
By default, an Actions column will be added to PDMLinkHTMLTables. If the
first column of the table is an object icon column, the actions column will be the
second column in the table. Otherwise, it will be the first column.
An Actions column only makes sense if each row of the table represents a
PDMLink object for which you would like to make actions available from the
table. If you do not want an Actions column to appear, you can do so
programmatically by calling the following method:
PDMLinkHTMLTable.setPresentActionsIconColumn(false)
tableService action=INITAPPLICATIONDATATABLE
APPLICATIONDATAATTRIBUTES=fileName,format,fileSize
sort=0 asc=false name=AttachmentsTable PDMLINKTABLE=true
SUPPRESSACTION=true
Like other service lookups based on object type, if a mapping is not found for a
given type the system will look recursively for a mapping for the parent type. If a
mapping for a lower level parent is not found, an object inheriting from WTObject
will receive the actions list specified by the tree
WTOBJECT_TABLE_ACTIONS as a result of the of the following entry in the
file codebase/com/ptc/windchill/pdmlink/templateutil/HTML.properties:
wt.services/rsc/default/wt.templateutil.iconTableActions/
TABLEACTIONS/wt.fc.WTObject/0=WTOBJECT_TABLE_ACTIONS
The section How to Add an Action to the Actions Column of a PDMLink Table
explains in more detail how to modify the actions displayed for a given object
type.
Sorting by Column
If you have enabled sorting by column in your table, you must include the
following javascript and form element on the template that displays the table:
<script language=JavaScript>
<!--
function submitColumnSort( action )
{
var cform = window.document.forms.sortby;
cform.sortby.value=action;
cform.submit();
}
-->
</script>
The form element must be placed outside of any other form element on the page.
<script language=JavaScript>
<!--
function submitColumnCollapse( action )
{
var cform = window.document.forms.collapse;
cform.collapse.value=action;
cform.submit();
}
-->
</script>
The form element must be placed outside of any other form element on the page.
Common Customizations
How to Add an Action to the Actions Dropdown Menu on a PDMLink Details Page
This section gives an example of how to add an action to the actions dropdown
menu on a Details page. Assume that you would like to add the action Revise to
the dropdown menu for parts after the Associate Document action (see below).
<27>.constant=REVISE
3. If you have not already done so, create a customized version of the file
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml as
described in the section Actions Configuration above.
<NAVIGATION_TREE>
<Name>WTPART_DROPDOWN_ACTIONS</Name>
<Links>
<Link>
<Name>Tools</Name>
<Action>Tools</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.doc.server.serverResource
</Resource_Bundle>
<Resource_Key>25</Resource_Key>
<Links/>
</Link>
<Link>
<Name>ASSOCIATEDOCS</Name>
<Action>ASSOCIATEDOCS</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.doc.server.serverResource
</Resource_Bundle>
<Resource_Key>18</Resource_Key>
<Links/>
</Link>
<Link>
<Name>Revise</Name>
<Action>CustomRevise</Action>
<Method>invokeAction</Method>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.MyCompany.CustomResource
</Resource_Bundle>
<Resource_Key>27</Resource_Key>
<Links/>
</Link>
7. Create new property file entries so the system can find the ActionDelegate
and URLActionDelegate associated with your action. Note that the action
name must be upper case in your property entries. See the section titled
Properties and Property Files in the chapter Customizing HTML Client for
how to add new properties.
wt.services/svc/default/wt.enterprise.ActionDelegate/CUSTOMREVI
SE/java.lang.Object/0=custom.ReviseNavBarActionDelegate/duplica
te
wt.services/svc/default/wt.enterprise.URLActionDelegate/CUSTOMR
EVISE/
java.lang.Object/0=custom.ReviseNavBarURLActionDelegate/duplica
te
At the end of this property entry is the name of the tree containing the Actions
dropdown list for WTDocuments:
"WTDOCUMENT_DROPDOWN_ACTIONS."
2. If you have not already done so, create a customized version of the file
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml as
described in the section Actions Configuration above.
3. Open your custom NavigationAndActions.xml file and copy the
NAVIGATION_TREE named WTDOCUMENT_DROPDOWN_ACTIONS.
Paste the copy into your file and rename the copy
SPECIFICATION_DOCUMENT_DROPDOWN_ACTIONS. Your new
tree may be placed anywhere in the file as long as it is between existing trees.
4. Go to the bottom of the tree for
SPECIFICATION_DOCUMENT_DROPDOWN_ACTIONS and delete the
<Link> section named SetLifeCycleState. Your file should now look similar
to the following:
<NAVIGATION_TREE>
<Name>WTDOCUMENT_DROPDOWN_ACTIONS</Name>
<Links>
<Link>
<Name>DISCUSS_PLM</Name>
<Action>DISCUSS_PLM</Action>
<Method>invokeAction</Method>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.doc.server.serverResource
</Resource_Bundle>
<Resource_Key>19</Resource_Key>
<Links/>
</Link>
<Link>
<Link>
<Name>RenameObject</Name>
<Action>RenameObject</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>wt.doc.docResource</Resource_Bundle>
<Resource_Key>90</Resource_Key>
<Links/>
</Link>
.
.
.
<Link>
<Name>EXPORT</Name>
<Action>EXPORT</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.clients.export.
server.processors.processorsResource
</Resource_Bundle>
<Resource_Key>1</Resource_Key>
<Links/>
</Link>
</Links>
</NAVIGATION_TREE>
5. Create a typed services property entry mapping your soft type name to your
new actions dropdown tree:
wt.services/rsc/default/wt.templateutil.objectPropsActionDropDown/
DROPDOWN/
WCTYPE/wt.doc.WTDocument/SpecificationDocument/0=SPECIFICATION_DOC
UMNENT_DROPDOWN_ACTIONS
See the section called Properties and Property Files in the chapter
Customizing the HTML Client for more information about adding new
property entries.
6. Restart your Method Server. Details pages for Specification Documents
should now display an actions dropdown list without a Set Life Cycle State
action.
28.constant=VERSIONS_AND_ITERATIONS
The name of the tree containing the navigation bar list is at the end of this
entry: WTDOCUMENT_NAVBAR_ACTIONS.
5. Delete the Versions and Iteration History links and add a Versions and
Iteration History link to the WTDOCUMENT_NAVBAR_ACTIONS tree in
your custom NavigationsAndActions.xml file as follows. Note that your new
action name must be unique within your PDMLink system.
<NAVIGATION_TREE>
<Name>WTDOCUMENT_NAVBAR_ACTIONS</Name>
<Links>
.
.
.
<Link>
<Name>ViewBaselinesForObject_plm</Name>
<Action>ViewBaselinesForObject_plm</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.baseline.server.
processors.baselineResource
wt.services/svc/default/wt.enterprise.URLActionDelegate/VERSION
SANDITERATIONS/wt.doc.WTDocument/0=com.MyCompany.VersionsAndIte
rationsNavBarURLActionDelegate/duplicate
See the section Properties and Property Files in the chapter Customizing the
HTML Client for how to add custom property entries.
8. Create one or more HTML templates for your new page. In this case, you
might want to just copy and then modify the existing template for the
Versions Details page:
codebase/templates/pdmlink/doc/AllVersionsFrame.html. The modification
would consist of adding an IterationHistory table, as shown in the template
codebase/templates/pdmlink/doc/IterationHistoryFrame.html.
9. Create a property file entry mapping your new action to the correct HTML
template. Assuming the path to your new template is
<WT_HOME>/codebase/templates/MyCompany/VersionsAndIterations.htm
l, this entry would look like:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/Ver
sionsAndIterations/wt.doc.WTDocument/0=templates.MyCompany.Vers
ionsAndIterations
See the section Properties and Property Files in the chapter Customizing the
HTML Client for how to add custom property entries.
10. Since your new template doesn't need any Windchill script methods other
than those in DefaultTemplateProcessor, the latter can be used as your
template processor. Create a property file entry to map your new action to
this template processor:
wt.services/svc/default/wt.enterprise.TemplateProcessor/
VersionsAndIterations/wt.doc.WTDocument/
0=wt.templateutil.processor.DefaultTemplateProcessor/ duplicate
See the section Properties and Property Files in the chapter Customizing the
HTML Client for how to add custom property entries.
11. Restart the Method Server. You should now see an All Versions and
Iterations item in the navigation bar.
2. At the end of this property entry is the name of the tree containing the Actions
dropdown list for WTDocuments:
"WTDOCUMENT_NAVBAR_ACTIONS."
3. If you have not already done so, create a customized version of the file
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml as
described in the section Actions and Configuration above.
4. Open your custom NavigationAndActions.xml file and copy the
NAVIGATION_TREE named "WTDOCUMENT_NAVBAR_ACTIONS."
Paste the copy into your file and rename the copy
SPECIFICATION_DOCUMENT_NAVBAR_ACTIONS. Your new tree
may be placed anywhere in the file as long as it is between existing trees.
5. Delete the links for Versions and Iteration History and add the new link
called VersionsAndIterations into the tree for
SPECIFICATION_DOCUMENT_NAVBAR_ACTIONS:
<NAVIGATION_TREE>
<Name>SPECIFICATION_DOCUMENT_NAVBAR_ACTIONS</Name>
<Links>
<Link>
<Name>RelatedParts</Name>
<Action>ObjProps</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
See the section called Properties and Property Files in the chapter
Customizing the HTML Resource for more information about adding new
property entries.
Complete steps 6-11 described in the section How to Add a Link to a Details Page
Navigation Bar above.
To add an Update action to the actions cell for each Problem Report
(wt.change2.WTChangeIssue) you would do the following:
1. Discover the NAVIGATION_TREE in NavigationAndActions.xml
containing the table action links for Problem Reports. This can be done by
searching the directories in <WT_HOME>/codebase for .properties files
containing the string "iconTableActions." Your search results should look
similar to the following:
com\ptc\core\foundation\admin\admin.properties(29):
wt.services/rsc/default/wt.templateutil.iconTableActions/
TABLEACTIONS/wt.folder.cabinet/0=CABINET_TABLE_ACTIONS
com\ptc\windchill\cadx\propfiles\HTML.properties(677):
wt.services/rsc/default/wt.templateutil.iconTableActions/
TABLEACTIONS/wt.fc.WTObject/0=WTOBJECT_TABLE_ACTIONS
com\ptc\windchill\pdmlink\doc\doc.properties(209):
wt.services/rsc/default/wt.templateutil.iconTableActions/
TABLEACTIONS/wt.doc.WTDocument/0=WTDOCUMENT_TABLE_ACTIONS
com\ptc\windchill\pdmlink\doc\doc.properties(210):
wt.services/rsc/default/wt.templateutil.iconTableActions/TABLEACTI
ONS/wt.doc.WTDocumentMaster/
0=WTDOCUMENTMASTER_TABLE_ACTIONS
.
.
.
2. Because you only want the Update action to be shown for Problem Reports,
and not all WTObjects, you will need to make a new NAVIGATION_TREE
for Problem Report table actions. If you have not already done so, create a
customized version of the
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml file as
described in the section Actions Configuration earlier in this chapter.
3. In your custom NavigationAndActions.xml file, copy the
NAVIGATION_TREE for WTOBJECT_TABLE_ACTIONS. Paste the
copy into the file and name the copy
"PROBLEM_REPORT_TABLE_ACTIONS." In your new tree, add a
<Link> tag for the update action. In this case, the Update action will invoke
the same ActionDelegate and URLActionDelegate as the Update action in the
dropdown list on the ProblemReport Details page so we can just copy the
<LINK> node from the PR_Details_Actions NAVIGATION_TREE. Your
new tree should look similar to the following:
<NAVIGATION_TREE>
<Name>PROBLEM_REPORT_TABLE_ACTIONS</Name>
<Link>
<Name>Details</Name>
<Action>ObjProps</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.core.HTMLtemplateutil.server.
processors.processorsResource
</Resource_Bundle>
<Resource_Key>22</Resource_Key>
<Links/>
</Link>
<Link>
<Name>Update_PR</Name>
<Action>Update_PR</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.ptc.windchill.pdmlink.change.server.
processors.detailsResource
See the section called Properties and Property Files in the chapter
Customizing the HTML Client for more information about adding custom
properties.
5. If necessary, create an icon image for your new action and the property entries
to map your action to your icon image. In this case, we will use an existing
icon: <WT_HOME>/codebase//com/ptc/core/ui/images/update.gif. This icon
is already used for the update action for WTDocuments, as indicated by the
following property entries in the file
<WT_HOME>/codebase//com/ptc/windchill/doc/doc.properties:
wt.services/svc/default/wt.fc.IconDelegate/UpdateDocument/
wt.doc.WTDocument/0=wt.fc.ActionIconDelegate/duplicate
wt.services/svc/default/wt.fc.ActionIconDelegate/UpdateDocument/
wt.doc.WTDocument/0=com.ptc.core.ui.images.update.gif
To use these same images for Problem Reports, you can add the following
custom properties:
wt.services/svc/default/wt.fc.IconDelegate/Update_PR/
wt.change2.WTChangeIssue/0=wt.fc.ActionIconDelegate/duplicate
wt.services/svc/default/wt.fc.ActionIconDelegate/Update_PR/
wt.change2.WTChangeIssue/0=com.ptc.core.ui.images.update.gif
See the section called Properties and Property Files in the chapter
Customizing the HTML Client for more information about adding custom
properties.
To add a Display Related Parts action to the multiselect action bar you would do
the following:
1. Discover the NAVIGATION_TREE in NavigationAndActions.xml
containing the multiselect action links for this table. There is no formula for
finding the tree --- it will require searching the file for text likely to be
contained in the tree name. Often, trees for multiselect action bars have the
text "multiselect" in the name so searching on that string will lead you to the
<NAVIGATION_TREE>
<Name>DocumentReferences_MultiSelectActions</Name>
<Links>
<Link>
<Name>DocumentRemoveReference</Name>
<Action>DocumentRemoveReference</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>com.ptc.windchill.pdmlink.doc.
server.processors.processorsResource
</Resource_Bundle>
<Resource_Key>91</Resource_Key>
<Links/>
</Link>
</Links>
</NAVIGATION_TREE>
If your search for files containing the tree name was not successful, you can
assume the table of interest is defined in a java class and is not customizable.
3. Once you have found the relevant NAVIGATION_TREE and template, you
are ready to add your new action. Select a unique name for your new action.
In this case, we will use "DisplayPartsForReferencesDocs."
4. Create an entry in an .rbInfo file for the label for this action. For example,
assume you have a .rbInfo file called
<27>.constant=DISPLAY_RELATED_PARTS
6. If you have not already done so, create a customized version of the file
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml as
described in the section Action Configuration earlier in this chapter.
7. Add a <LINK> for this action to the
DocumentReferences_MultiSelectActions tree in your custom
NavigationAndActions.xml file as follows:
<NAVIGATION_TREE>
<Name>DocumentReferences_MultiSelectActions</Name>
<Links>
<Link>
<Name>DocumentRemoveReference</Name>
.
.
.
<Links/>
</Link>
<Link>
<Name>DisplayPartsForReferencesDocs</Name>
<Action> DisplayPartsForReferencesDocs</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>com.MyCompany.CustomResource
</Resource_Bundle>
<Resource_Key>27</Resource_Key>
<Links/>
</Link>
</Links>
</NAVIGATION_TREE>
DisplayPartsForReferencesDocs
actionNavBar=DocumentReferences_TableActions
actionList=DocumentAddReference
Note: When upgrading PDMLink you will have to merge your customizations
into the out-of-the-box template if it has changed in the new release. See the
chapter, Windchill Software Maintenance and Best Practices in the Windchill
System Administrator’s Guide.
9. Create an icon for your new action and map your action name to it by creating
the appropriate properties. In this case, our new icon image file is
<WT_HOME>/codebase/com/MyCompany/images/displayRelatedParts.gif,
so the property entries would look as follows:
wt.services/svc/default/wt.fc.IconDelegate/DisplayPartsForReferenc
esDocs/ wt.doc.WTDocument/0=wt.fc.ActionIconDelegate/duplicate
wt.services/svc/default/wt.fc.ActionIconDelegate/
DisplayPartsForReferencesDocs/ wt.doc.WTDocument/
0=com.MyCompany.images.displayRelatedParts.gif
See the section Properties and Property Files in the chapter Customizing the
HTML Client for more information about adding new property entries.
wt.services/svc/default/wt.enterprise.ActionDelegate/
DISPLAYPARTSFORREFERENCESDOCS/java.lang.Object/
0=wt.templateutil.processor.DefaultNavBarActionDelegate/duplicate
For the table action bars, the requestor object for the ActionDelegate and
URLActionDelegate must be java.lang.Object.
See the section Properties and Property Files in the chapter Customizing the
HTML Client for more information about adding new property entries.
11. You will need to create a template and template processor for the new page to
be invoked by this action and then create properties to map your action to
these artifacts. If you template is named
<WT_HOME>/codebase/templates/MyCompany/RelatedPartsForReferences
Docs.html and your template processor is named
<WT_HOME>/codebase/com/MyCompany/RelatedPartsForReferencesDocs
Processor.class the property entries would be as follows:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
DisplayPartsForReferencesDocs /wt.doc.WTDocument/
0=templates.MyCompany.RelatedPartsForReferencesDocs
wt.services/svc/default/wt.enterprise.TemplateProcessor/
DisplayPartsForReferencesDocs/ wt.doc.WTDocument/
0=com.ptc.MyCompany.RelatedPartsForReferencesDocsProcessor/duplica
te
See the section Multiselect Action Bar earlier in this chapter for how to
extract the objects that were checked from the form data in your template
processor.
12. Restart the Method Server. You should now see your new link in the actions
bar:
<NAVIGATION_TREE>
<Name>DocumentReferences_TableActions</Name>
<Links>
<Link>
<Name>DocumentAddReference</Name>
<Action>DocumentAddReference</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
If your search for files containing the tree name was not successful, you can
assume the table for interest is defined in a java class and is not customizable.
3. Once you have found the relevant NAVIGATION_TREE and template, you
are ready to add your new action. Select a unique name for your new action.
In this case, we will use "DisplayPartsForReferencesDocs" as we did in the
previous example.
4. Create an entry in an .rbInfo file for the label for this action. For example,
assume you have a .rbInfo file called
/src/com/MyCompany/CustomResource.rbInfo containing 26 of your custom
UI text strings. You would add an entry to that file similar to the following:
<27>.constant=DISPLAY_RELATED_PARTS
6. If you have not already done so, create a customized version of the file
<WT_HOME>/codebase/wt/templateutil/NavigationAndActions.xml as
described in the section Action Configuration earlier in this chapter.
7. Add a <LINK> for this action to the DocumentReferences_TableActions tree
in your custom NavigationAndActions.xml file as follows:
<NAVIGATION_TREE>
<Name>DocumentReferences_TableActions</Name>
<Links>
<Link>
<Name>DocumentAddReference</Name>
.
.
.
</Link>
<Link>
<Name>DisplayPartsForReferencesDocs</Name>
<Action>DisplayPartsForReferencesDocs</Action>
<Tree_Action_Delegate/>
<In_Minimum_List>true</In_Minimum_List>
<Resource_Bundle>
com.MyCompany.CustomResource
</Resource_Bundle>
<Resource_Key>2</Resource_Key>
<Links/>
</Link>
</Links>
</NAVIGATION_TREE>
actionNavBar=DocumentReferences_TableActions
actionList=DocumentAddReference,DisplayPartsForReferencesDocs
9. Create an icon for your new action and map your action name to it by creating
the appropriate properties. If your new icon file were
<WT_HOME>/codebase/com/MyCompany/images/displayRelatedParts.gif,
your property entries would look as follows:
wt.services/svc/default/wt.fc.IconDelegate/DisplayPartsForReferencesDocs/
wt.doc.WTDocument/0=wt.fc.ActionIconDelegate/duplicate
wt.services/svc/default/wt.fc.ActionIconDelegate/ DisplayPartsForReferencesDocs/
wt.doc.WTDocument/
0=com.MyCompany.images.displayRelatedParts.gif
See the section Properties and Property Files in the chapter Customizing the
HTML Client for more information about adding new property entries.
0=wt.templateutil.processor.objectpropsNavBarURLActionDelegate/
duplicate
See the section Properties and Property Files in the chapter Customizing the
HTML Client for more information about adding new property entries.
11. You will need to create a template for the new page to be invoked by this
action and the template processor that will be used for it and then create
properties to map your action to these artifacts. If you template is named
<WT_HOME>/codebase/templates/MyCompany/RelatedPartsForReferences
Docs.html and your template processor is named
<WT_HOME>/codebase/com/MyCompany/RelatedPartsForReferencesDocs
Processor.class the property entries would be as follows:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
DisplayPartsForReferencesDocs /wt.doc.WTDocument/
0=templates.MyCompany.RelatedPartsForReferencesDocs
wt.services/svc/default/wt.enterprise.TemplateProcessor/
DisplayPartsForReferencesDocs/ wt.doc.WTDocument/
0=com.ptc.MyCompany.RelatedPartsForReferencesDocsProcessor/duplicate
Your new template processor might have a Windchill script method, called by the
template, to query for all like documents related to the current ContextObject and
then query fro all the parts related to the documents in the list. It could then
present the results in a table or other format of your choosing.
12. Restart the Method Server. You should now see your new link in the actions
bar:
Topic Page
Adding a Search Component...............................................................................9-2
Overriding an Object’s Life Cycle State Property ..............................................9-6
Searching for Soft Types and Attributes .............................................................9-7
The SearchableAttributes.properties File ............................................................9-8
Adding Actions to an Object in the Search Results Table ..................................9-9
Adding a New Type to the Search User Interface.............................................9-10
9-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. The
componentId is used to define the types that can be searched for within the search
component, as well as the container types that a search can be constrained within.
For example the following entries would create a search component with a
componentId of “PDMLink.exampleSearch” within the PDMLink solution.
The following search component example will constrain its searches within
Products and Libraries and search for Change Issues and Change Requests.
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.
• The value Foundation indicates that this search component can be used with
any Windchill solution that is installed, because Foundation is installed with
every Windchill solution.
• The value containerSearch is the key to the component. Each object type is
given a unique numerical value as well.
You can also define for a search component the container types to which the
search should be constrained. An example that already exists is the sandbox1
picker constraints that are defined for 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 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 PDM or
PDMLink) available to a project, and vice versa.
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 Administrator’s 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.
<ActionList id="actionList.tableRowOperations">
<Insert ref="<action id>"/>
</ActionList>
</Context>
To add a new action to an object, you must create the action and then add it to the
actionList.tableRowOperations list. Following is an example:
<Context type="<objectType>">
<ActionList id="actionList.tableRowOperations">
<Insert ref="<action id>"/>
<Insert ref="action.NewAction"/>
</ActionList>
<Action id="action.NewAction">
<Extend ref="someAction" />
</Action>
</Context>
There may also be situations where displaying the action is dependent on some
condition being set a certain way. You can handle this by using draw handlers or
if conditions. Refer to the Windchill Client Technology Guide for details on how
this is done. Following is an example:
<ActionList id="actionList.tableRowOperations" >
<Insert ref="<action.ConditionalAction>">
<DrawHandler class="<path to handler>">
<Check value="%[<some attribute>]==true"/>
</DrawHandler>
</Insert>
</ActionList>
property.xml File
Each object type has a property.xml file that defines the attributes that can be used
in the search. These properties are inherited from all superclasses and interfaces
that are defined.
search.xml File
The search.xml file defines the configurations for laying out the object-specific
search page to include the search criteria and results tables. The configurations
inherit the parent’s class configurations if none are specified for the object type.
Following are the elements to use for specific purposes in the search.xml file.
• <LayoutRow id="layoutRow.nameNumber">
This LayoutRow is used to define an object’s identifying attributes, such as
name or number, directly below the keyword field, if one exists.
• <ElementGroup id="elementGroup.objectSpecificAttributes">
This ElementGroup defines the object attributes that are displayed on the
search page below the object type picker. Usually, they do not contain the
object’s identifying attributes, such as name or number.
• <ElementGroup id="elementGroup.layoutRow.softAttributes" />
This ElementGroup is defined for Typeable objects to allow the search page
to render the soft attributes that are defined for an object type. If you do not
want to show the “More Attributes Link”, include this line to override it.
• <CompositeTable id="compositeTable.searchResults">
This table defines the search results table for each object type. It can be
overridden or extended, depending on the new objects attributes that you want
to display.
• <ElementGroup id=
":elementgroup.nameAndImage.compositeTableColumns">
This column is used to define the name and image column for an object type.
property.xml File
In this file, define the properties that are specific to the new object type. All
properties already defined in parent classes can be used by the new type as well.
Follwing is an example property file that defines the attributes for Projects.
Characters shown in bold type are of particular relevance to this discussion.
<?xml version="1.0" standalone="no"?>
<!—Define the repository package that this class belongs, this should be the
directory under conf->
<Repository package="com.ptc.windchill.projectlink.project2">
<!—Set up the context for the the Synonym, in this case “Project2”. This will be
used in other files to define the context for this object. The value must equal the
actual type name of the object ->
<Context>
<Synonym id="Project2" value="wt.projmgmt.admin.Project2"/>
</Context>
<!—Define the properties within the context of the synonym defined above. The id
<ElementGroup id="elementGroup.objectSpecificAttributes">
<Extend ref="persistable:elementGroup.objectSpecificAttributes"/>
<!-- Empty Spacer Row -->
<Insert ref=":layoutRow.spacer"/>
<!—Each LayoutRow must have a unique ID within this context->
<LayoutRow id="rowAttr1">
<Insert ref=":property.businessLocation" sticky="%[context#sticky]"/>
<Insert ref=":property.businessUnit" sticky="%[context#sticky]"/>
</LayoutRow>
<!-- Empty Spacer Row -->
<Insert ref=":layoutRow.spacer"/>
<LayoutRow id="rowAttr2">
<Insert ref=":property.containerInfo.description"
sticky="%[context#sticky]"/>
<Insert ref=":property.riskDescription"/>
</LayoutRow>
<!-- We don't want to display the "Show More Attributes" link for this type, so
we're overriding the default with an empty elementgroup -->
<!—This layout row defines the object identity items that you see at the top of the
page, in most cases it is name and number, but in this case its name and scope->
<!-- Layout Rows -->
<LayoutRow id="layoutRow.nameNumber">
<Insert ref=":property.name" sticky="%[context#sticky]"/>
<Insert ref=":property.scope" sticky="%[context#sticky]"/>
</LayoutRow>
<!—The table below defines the search results table for this object type.-.
<!-- Tables -->
<!-- Search Results table for this object type -->
<CompositeTable id="compositeTable.searchResults">
<Extend ref="search:compositeTable.searchResults.base"/>
<Insert ref=":elementgroup.nameAndImage.compositeTableColumns"/>
<CompositeColumn show=":actionList.tableRowOperations"
if="%[context#isPicker]!=true">
<Label
resource="[##]com.ptc.core.foundation.persistable.client.persistableResource:ACTION
S_LBL"/>
</CompositeColumn>
<CompositeColumn show=":property.containerName">
<Label
resource="[##]com.ptc.core.foundation.persistable.client.persistableResource:CONTAI
NER_LBL"/>
action.xml File
This file defines the actions in the actions column, as well as the actions
associated with the name link for an object. See customizing actions for a detailed
description of this file.
<?xml version="1.0" standalone="no"?>
<Repository package="com.ptc.windchill.projectlink.project2">
<ActionList id="actionList.tableRowOperations"
actionListType="horizontal">
<Insert ref="hyperlink.view.detailPage"/>
</ActionList>
</Context>
</Repository>
Topic Page
Overview ...........................................................................................................10-2
Prerequisite Knowledge ....................................................................................10-2
Change Objects and Their Relationships ..........................................................10-3
HTML Hidden Input Form Fields .....................................................................10-4
Expand and Collapse Functionality...................................................................10-4
Generating the Change Management User Interface ........................................10-6
Changing the Look of the User Interface ........................................................10-18
Processor/Template Reference Tables ............................................................10-31
Adding an Attribute to WTChangeRequest2 ..................................................10-34
Change Management Delegates ......................................................................10-43
10-1
Overview
This chapter describes how the change management user interface is generated
and gives examples of how to customize the user interface to fit your
requirements. (Chapter 9, Customizing Solutions, also describes how to
customize change management workflow process templates.)
The following general topics are included:
• Prerequisite knowledge that you are assumed to have.
• A brief description of each of the change objects and how they work in
relationship to one another.
• A description of the use of HTML hidden input form fields to help control an
object’s mode (create, update, or view), as well as an object’s expand state
(expanded or collapsed). Throughout this chapter, expand state refers to
whether an object is expanded or collapsed and should not be confused with
life cycle state.
• A description of the template processors and HTML templates that are used to
generate the change management user interface and how they work together.
Although the user interface is rendered as one page, many subtemplates are
used to generate the output. The form task delegates that perform user actions
in the user interface are also described.
• An explanation of how to make changes to the look of the user interface and
some examples.
• An example of how to add an attribute to a change request.
• A description of the change management delegates.
Prerequisite Knowledge
These topics and examples assume you are familiar with standard HTML,
template processing, subtemplate processing, table service, task delegates, and
context properties (object, action, and form data). For further information on these
topics, see Chapter 7, Customizing the HTML Client.
You must be familiar with the following classes:
• wt.templateutil.processor.GenerateFormProcessor
• wt.enterprise.BasicTemplateProcessor
• wt.templateutil.processor.FormTaskDelegate
• wt.templateutil.table.BasicTableService
• wt.templateutil.processor.SubTemplateService
The name of the hidden form field reflects the object ID and the value indicates
that it should be expanded. During processing of the form data, when the object
with the ID wt.change2.WTChangeOrder2:2371479 is set as the context object,
the processor knows by the form data property and value pair that the full detail of
the object must be displayed. An object that is collapsed does not have an
associated hidden form field.
When a user clicks the Accept link, these form fields are used to determine the
type of the new object and its parent.
The hidden form field named update is used to indicate which object is to be
presented in update mode. When the page is loaded initially, the value for this
field is empty. If the user selects an Update link for an object, Javascript (found in
DefaultChangeTask.html) is used to set the value of the update form field equal to
the object ID, as shown in the following example:
<INPUT Type=hidden NAME="update"
VALUE="OR:wt.change2.WTChangeActivity2:2371601">
The existence of this hidden form field instructs the template processor to render
the object so that the user is able to update its attributes. The processor knows by
the update hidden form field that the update template, rather than a read-only view
template, should be used to output the form fields for the object. When the page is
regenerated with update mode, this hidden form field is added to the source with
the value equal to the object ID.
Template Processors
The change management user interface is made possible using template
processing, subtemplate processing, and the table service. (For further
information on these topics, see chapter 7, Customizing the HTML Client.) The
change request is considered the organizing object which leads the generation of
the page.
The reminder of this section describes the template processors used, in
combination with various templates, to generate specific aspects and parts of the
change management page:
• ChangeManagementFormProcessor, which initiates generation of the page
and ensures the proper change request is set as the context object.
• DefaultChangeTaskProcessor, which helps control which sections of the
page (Request, Investigate, Propose, and Implement) are generated and the
order in which they are presented on the page.
• ChangeRequestProcessor, which helps generate the Request section of the
page.
• ChangeInvestigationProcessor, which helps generate the Investigate section
of the page.
• ChangeProposalProcessor, which helps generate the Propose section of the
page.
• ChangeOrderProcessor, which helps generate the Implement section of the
page.
• AnalysisActivityProcessor, which helps generate the expanded view of an
analysis activity.
• ChangeActivityProcessor, which helps generate the expanded view of a
change activity.
Triggering from a Local Search, the Change Manager Page, or the Windchill Explorer
The starting points for generation of the change form are the template processor
ChangeManagmentFormProcessor, in combination with the
ChangeManagementForm.html template. Selecting any change object can trigger
the generation of the change form, but a change request always leads the
generation of the page. Therefore, the first step performed by
ChangeManagementFormProcessor is to determine if the context object is an
instance of a change request. If it is not, the change request for the change object
is found and set as the context object.
This processor and template combination is the shell for the entire change form.
Windchill script calls within the ChangeManagementForm.html template produce
output that displays the page title, adds the form tag (name, action, method), and
triggers the next processor and template combination. Also included in
ChangeManagementForm.html is the Javascript used when loading and unloading
the page.
The object-specific information visible to the user (for example, change request
attributes, a list of change proposals, and so on) is generated using subtemplates.
A Windchill script call in the ChangeManagementForm.html template triggers the
method displayChangeTask (which is defined in
ChangeManagementFormProcessor). The displayChangeTask method
immediately invokes DefaultChangeTaskProcessor, which determines which
sections are generated and the order in which they are presented on the page (as
described later in this section).
By removing this script call, you prevent the entire Investigate section from being
generated. However, the other sections -- Request, Propose, and Implement -- are
not affected and still appear.
The four script calls in DefaultChangeTask.html invoke four different processors:
ChangeRequestProcessor, ChangeInvestigationProcessor,
ChangeProposalProcessor, and ChangeOrderProcessor. The following figure
illustrates the four sections and the processor/template combination that is used to
generate each.
Note that DefaultChangeTaskProcessor and DefaultChangeTask.html are not
referenced in the figure. Although they contribute to the generation of the user
interface, they do not generate code that is visible to the user. Instead, they are
responsible for the order in which the sections are displayed; they initialize the
hidden form fields (create_parent, create_class, and update); and they contain
client-side Javascript.
ChangeInvestigationProcessor
The Windchill script call displayChangeInvestigationSection from the
DefaultChangeTask.html template invokes the method
displayChangeInvestigationSection in DefaultChangeTaskProcessor. This
method sets the context action to ChangeInvestigationSection and then calls a
subtemplate service to find the appropriate processor for that action:
ChangeInvestigationProcessor.
ChangeInvestigationProcessor, in combination with the
ChangeInvestigationSection.html template, generates the Investigate section of
the page. This section includes the header line, the New Change Investigation
link, and the list of change investigations for the change request.
ChangeOrderProcessor
The Windchill script call displayChangeOrderSection from the
DefaultChangeTask.html template invokes the method
displayChangeOrderSection in DefaultChangeTaskProcessor. This method sets
the context action to ChangeOrderSection and then calls a subtemplate service to
find the appropriate processor for that action: ChangeOrderProcessor.
ChangeOrderProcessor, in combination with the ChangeOrderSection.html
template, generates the Implement section of the page. This section includes the
header line, the New Change Order link, and the list of change orders for the
change request.
The method displayChangeOrderTable is used to query for all the change orders
and write a header line for each row returned. If the current row is to be in
expanded form, the context action (ViewChangeObject or UpdateChangeObject)
is changed according to the mode for that object (using the form data, as explained
earlier in this chapter under HTML Hidden Input Form Fields, to determine if the
object is in update mode).
The first parameter is the value HTML form action; that is, the URL where the
information is to be submitted. The second parameter contains the value of the
Windchill URL processor action. The third and fourth parameters contain the
context object/context class and the object ID/class combination. For example, if a
change order is in update mode, the Accept link will look similar to the following:
<A HREF="javascript:processForm('http://galleberg.mn.ptc.com/
wtcgi-bin/wtauthcgi.exe/wt.enterprise.URLProcessor/processForm',
'UpdateChangeObject', 'oid',
'OR:wt.change2.WTChangeOrder2:2521002' )">
Accept
<IMG SRC="http://galleberg.mn.ptc.com/Windchill/wt/clients/
images/actnlink.gif" ALT="Accept changes" BORDER=0></A>
The remainder of this section describes the task delegate for each of the three
actions:
• CreateChange<object>Delegate
• UpdateChange<object>Delegate
• DeleteChange<object>Delegate
The delegate gets the values for the input data, creates a new instance of the class,
and then saves the new object. Upon completing these tasks, the change
management user interface is repainted with the new object expanded and scrolled
into view.
UpdateChange<object>Delegate
In update mode, the Accept link triggers the appropriate form task delegate for the
object to be updated. The Accept link contains the action UpdateChangeObject
and the oid of the object to update. Following is an example of the structure of an
Accept link for updating a change order:
<A HREF="javascript:processForm('http://SiteWindchillServer.Com/
wtcgi-bin/wtauthcgi.exe/wt.enterprise.URLProcessor/processForm',
'UpdateChangeObject', 'oid',
'OR:wt.change2.WTChangeOrder2:2417705' )">
Accept
<IMG SRC="http://SiteWindchillServer.Com/windchill/wt/clients/
images/actnlink.gif" ALT="Accept changes" BORDER=0></A>
The delegate gets the values for the input data and then saves the object. Upon
completing these tasks, the change management user interface is repainted
reflecting the changes to the object.
DeleteChange<object>Delegate
In view mode, the Delete link triggers the appropriate form task delegate for the
object to be deleted. The Delete link contains the action DeleteChangeObject and
the OID of the object to delete. Following is an example of the structure of a
Delete link for deleting a change order:
<A HREF="javascript:processForm('http://SiteWindchillServer.Com/
wtcgi-bin/wtauthcgi.exe/wt.enterprise.URLProcessor/processForm',
'DeleteChangeObject', 'oid',
'OR:wt.change2.WTChangeOrder2:2417705' )">
Delete
<IMG SRC="http://SiteWindchillServer.Com/windchill/wt/clients/
images/actnlink.gif" ALT="Delete the Change Order" BORDER=0></A>
Upon completing the tasks, the change management user interface is repainted
without the deleted object.
Changing Text
This section describes how to change the text that is displayed for section headers,
table headers, and attribute labels. The text displayed in the user interface is
generated by script calls in the templates. Resource bundles are used to produce
localized text.
To change the text for a section header, you must change the resource bundle that
contains the text used for headers, wt\clients\change2\change2RB.java. In this
resource bundle, you will see entries for each of the resource keys, as shown
below in the left column. Make the changes to the desired text entries in the right
column.
{REQUEST, "Request"},
{INVESTIGATE, "Investigate"},
{PROPOSE, "Propose"},
{IMPLEMENT, "Implement"},
A Windchill script call is used to insert each header into the generated page.
Following is the script call found in ChangeInvestigationSection.html that
generates the Investigate header text:
<SCRIPT LANGUAGE=Windchill>
<!--
getLocalizedMessage resourceKey=INVESTIGATE
resourceClass=wt.clients.change2.Change2RB
-->
</SCRIPT>
The script calls for the other sections are similar. The resourceKey parameter
value indicates the entry in the resource bundle which contains the text to display.
The templates contain Windchill script calls for each attribute that is displayed.
Most of these attributes use the following syntax:
<SCRIPT LANGUAGE=Windchill>
<!--
objectPropertyName propertyName=name
-->
</SCRIPT>
The value Name is displayed as the label for the name field.
Changing Font
This section describes how to change the font attributes for several elements.
These attributes include size, face, and color. These attributes are applied to
HTML elements within the templates so most changes can be made quickly and
easily. Information displayed within a table requires changes to table service
script calls within the templates.
To change the background color of the navigation bar (on the left side of the
page), find the section similar to the following and change the value of the
BGCOLOR attribute in the <TD> tag:
<TD ALIGN=RIGHT VALIGN=TOP WIDTH=15% BGCOLOR=#9B599B
CELLPADDING=0 CELLSPACING=0>
<P> </P>
<TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=0>
<TR ALIGN=RIGHT>
<TD>
<SCRIPT LANGUAGE=Windchill>
<!--
createGlobalNavigationBar currentPage=CMForm
-->
</SCRIPT>
</TD>
</TR>
</TABLE>
</TD>
The background color is specified by the row tag, <TR bgcolor=#ccccb4>. You
make the change for the background color in this tag. Any hexidecimal or text
value is allowed for the value (red, blue, #dddfef).
To change the background color, find the similar section and change the value of
the BGCOLOR parameter to the new color. Either hexidecimal or text values can
be used.
</SCRIPT>
Again, change the value for the class parameter to the new class,
site.change2.SiteChangeInvestigation.
3. When in create mode in the user interface, the user is presented with two
options: Accept or Cancel. The URL associated with the Accept link includes
the type of object that is to be created. In the following script call, found in the
template UpdateChangeInvestigation.html (noted in the processor/template
reference tables), change the class parameter value from
wt.change2.WTChangeInvestigation to the new class,
site.change2.SiteChangeInvestigation.
<SCRIPT LANGUAGE=Windchillgt;
<!--
getAcceptLink class=wt.change2.WTChangeInvestigation
resourceClass=wt.change2.htmlclient.htmlclientResource
altKey=ACCEPT_CHANGES img=wt/clients/images/actnlink.gif
-->
</SCRIPT>
// Get the object that represents the row from the table model.
RowDataTableModel tm = (RowDataTableModel)getTableModel();
row_source =
(WTObject)tm.getRowDataObjects().elementAt(rowNumber);
//Add the form data (HTML hidden form field) that indicates
//that the object display should be expanded
formData.put(object_reference,"expand");
8. Change the parameter values in the table service calls in the HTML templates
to use the standard HTML components or your site-specific classes, if you
have customized them. In ChangeOrderSection.html,
ViewChangeOrder.html, and UpdateChangeOrder.html, make the following
changes:
a. Change the parameter:
tableService action=SETSERVICENAME
SERVICENAME=wt.change2.htmlclient.ImageLinkStringCellComponent
to the following:
tableService action=SETSERVICENAME
SERVICENAME=wt.templateutil.components.HTMLTableCellComponent
to the following:
tableService action=ADDCOLUMN NAME=displayIdentity
COLUMNCLASS=wt.templateutil.table.HTMLTableColumn
The following example explains the calls used to generate the Change Activity
Attachment(s) table shown in the preceding figure. These lines of code were taken
from ViewChangeActivity.html.
The first script call is used to get URL data associated with the object. Although
this is supported, it does not apply to the current version of Change Management.
<TR valign=top>
<TD>
<SCRIPT LANGUAGE=Windchill>
<!--
tableService action=initializeContents
tableService action=initURLDataTable
URLDATAATTRIBUTES=urlLocation,description
tableService action=setHeaderAttributes
The following script call is used to display the attachments table for the object.
(The line numbers in bold on the left correspond to notes following the code
sample; they are not part of the code.)
<SCRIPT LANGUAGE=Windchill>
<!--
Line 1 tableService action=INITAPPLICATIONDATATABLE
//APPLICATIONDATAATTRIBUTES=fileName,format,fileSize,
//modifyTimestamp,createdBy
Line 2 tableService action=setHeaderFromResource POSITION=4
RESOURCEBUNDLE=wt.enterprise.enterpriseResource
RESOURCEKEY=UPDATED_BY
Line 3 tableService action=setHeaderAttributes name=ALL
font.SIZE=2 th.align=left font.color=white
Line 4 tableService action=setColumnAttributes name=ALL
font.SIZE=2 td.bgcolor=#e3e3cf td.align=left
Line 5 tableService action=setTableAttributes table.width=90%
Line 6 tableService action=show
-->
</SCRIPT>
</TD>
</TR>
Line 1 indicates the type of data to be displayed and the attributes to be displayed.
Line 2 sets the column header text according to values in the indicated resource
bundle.
Line 3 sets the attributes values.
Line 4 sets the column attributes.
Line 5 sets the table attributes.
Line 6 generates the table given the preeding information.
Action Links
ViewChangeProposal.html/
ChangeProposalProcessor
UpdateChangeRequest.html/
ChangeRequestProcessor
CreateChangeRequest.html/
ChangeRequestProcessor
Expandable/Collapseable Objects
ViewChangeOrder.html/
ChangeOrderProcessor
ViewChangeInvestigation.html/
ChangeInvestigationProcessor
UpdateChangeProposal.html/
ChangeProposalProcessor
ViewChangeProposal.html/
ChangeProposalProcessor
Directory Structure
Save the Java files you create in the /Windchill/src/customization/SiteChange2
directory or its subdirectories and then Visual Café will compile the class files
into the /Windchill/codebase/customization/SiteChange2 directory or its
subdirectories.
You can save the HTML files and properties files in the
/Windchill/src/customization/SiteChange2 directory or its subdirectories and then
manually copy them to the /Windchill/codebase/customization/SiteChange2
directory or its subdirectories. An alternative would be to save them in the
/Windchill/codebase/customization/SiteChange2 directory or its subdirectories;
then you do not have to copy them manually.
You can make copies of existing HTML files to use as a starting point by copying
from the /Windchill/codebase/templates/change2 directory.
The following directory structure is suggested. You will need to create many of
these directories. If you choose a different directory structure, some steps in this
customization example will need to be modified.
/Windchill/codebase/customization/SiteChange2/
SiteChange2.properties
SiteChange2Resource.class
SiteChangeRequest.class
SiteChangeRequest.ClassInfo.ser
This script creates the tables needed to support your new objects. Note that if you
rerun this script, you may get errors creating primary keys, but they can be
ignored.
if ((getJustification() == null)
|| (getJustification().equals(""))) {
throw new InvalidAttributeException(RESOURCE,
SiteChange2Resource.NO_CR_JUSTIFICATION, null );
}
– The initialize method (only a stub was generated for you) should call
super.initialize (name):
super.initialize( name );
If you forget to do this, you will get a message at runtime that a name
must be provided for the change request.
You will also need to put the following in the user.imports section:
import java.net.URL;
import java.util.Properties;
import wt.httpgw.GatewayURL;
import wt.util.WTContext
4. For SiteCreateChangeRequestDelegate:
– The createChangeItem should be as follows:
Properties props = getFormData(); String name =
props.getProperty("name");
setContextObj(SiteChangeRequest.newSiteChangeRequest(name))
You will also have to add the following to the user.imports section:
import customization.SiteChange2.SiteChangeRequest;
import java.util.Properties;
to the end of the existing line in wt.properties. This line lists all the properties
files that are included in the main properties file and you should not add or
remove any others except SiteChange2.properties.
2. Copy ChangeManagementHome.html from
/Windchill/codebase/templates/change2, naming the copy
SiteChangeManagementHome.html, so that when Create Change Request is
selected, a SiteChangeRequest is created rather than a WTChangeRequest2.
– Change the call to create the URL in the HTML file so a
SiteChangeRequest is created rather than a WTChangeRequest2.
– Add the following line to SiteChange2.Properties so that we find the new
home page for change management:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/
ChangeManagementHome/java.lang.Object/
0=customization.SiteChange2.clients.SiteChangeManagementHome
This gets the label for "justificaton" from your new resource file.
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;
}
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 cabinet
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.
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
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 Windchill Application Developer’s Guide.
Topic Page
Customizing Document Management ...............................................................11-2
Customizing Life Cycle...................................................................................11-14
Customizing Workflow ...................................................................................11-16
11-1
Customizing Document Management
. . .
<!-- add hidden fields from other tabs here -->
. . .
<!-- hidden fields holding values for creating structure links -->
<INPUT name = "removeStructure" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=removeStructure</SCRIPT>">
<INPUT name = "structure" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=structure</SCRIPT>">
</TD>
</TR>
<TR>
<TD align=right>
<B><FONT FACE=arial,helvetica><<SCRIPT LANGUAGE=
Windchill>getResourceString textToken="docNumberLbl"
textResourceBundle=wt.clients.doc.DocRB</SCRIPT></FONT></B>
</TD>
<TD>
<INPUT name = "Number" type="text" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=Number</SCRIPT>">
</TD>
</TR>
<TR>
<TD align=right>
<B><FONT FACE=arial,helvetica><<SCRIPT LANGUAGE=
Windchill>getResourceString textToken="docNameLbl"
textResourceBundle=wt.clients.doc.DocRB</SCRIPT></FONT></B>
</TD>
<TD>
<INPUT name = "Name" type="text" size=50 value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=Name</SCRIPT>">
</TD>
</TR>
<TR>
<TD align=right>
<B><FONT FACE=arial,helvetica><<SCRIPT LANGUAGE=
Windchill>getResourceString textToken="newAttributeLbl"
textResourceBundle=myPackage.myRB</SCRIPT></FONT></B>
The following is an example of a new attribute using an excerpt from the Create
action’s Structure tab:
TR>
<TD>
<APPLET name=formApplet code="wt/boot/BootstrapApplet.class"
width=0 height=0 archive="wt/security/security.jar">
<PARAM name="boot_jar" value="docmgr.jar">
<PARAM name="boot_class" value="wt.clients.doc.WTDocumentApplet">
. . .
</APPLET>
. . .
<!-- hidden fields that hold values from General tab -->
. . .
<INPUT name = "Number" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=Number</SCRIPT>">
<INPUT name = "Name" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=Name</SCRIPT>">
<INPUT name = "newAttribute" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValuev
propertyName=newAttribute</SCRIPT>">
<!-- hidden fields holding values for creating dependsOn links -->
<INPUT name = "removeDependency" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=removeDependency</SCRIPT>">
<INPUT name = "removeComment" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=removeComment</SCRIPT>">
<INPUT name = "dependsOn" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=dependsOn</SCRIPT>">
<INPUT name = "dependencyComment" type="hidden" value=
"<SCRIPT LANGUAGE=Windchill>contextualValue
propertyName=dependencyComment</SCRIPT>">
There are also operations that must be performed on the client because they
involve out-of-the-sandbox processing. They must be executed on the client
where the content or files are to be uploaded from or downloaded to. The client-
side customization points are put in wt.doc.DocumentContentProcessing (shown
in the preceding figure), which is also provided as source. The methods in
DocumentContentProcessing are called through a combination of a property in
wt.properties and reflection so they can be changed to a custom method easily.
The property in wt.properties currently defaults to the following setting:
wt.doc.contentProcessingDelegate=wt.doc.DocumentContentProcessing
Steps 1, 3, and 4 are the customization points that can be modified by overriding
the class or method listed. In Step 4, the method that is called by POSTCREATE
by default is DocumentContentProcessing.postCreate. This is currently a stub
method that was created to allow customer sites to do content processing on the
client, other than the primary content of the document being created. The primary
content for the document being created is handled through the primary content
bean so no customization is allowed. In Steps 1 and 3, the
WTDocumentDelegate.createDocument and
WTDocumentDelegate.postCreateDocument are not stub methods but they can be
overridden, as described earlier, to add additional customized processing on the
server.
The wt.doc.DocumentFormData class is a wrapper of a Hashtable that is used to
pass data between the methods. Any fields added to the hidden fields of the three
HTML files that make up the create forms and the create processing file should be
available from the DocumentFormData instance passed into these methods (see
the section titled Customizing the HTML Client earlier in this section for
information on customizing these forms). To see the values that are available, use
the DocumentFormData.getDocumentAttributes method to get the entire
Hashtable to output the available values.
By default, the property is true if it is not set in wt.properties, and all of the
primary content from the structure is downloaded. This property also applies to
both Java and HTML clients, and Get Content Java and HTML.
throws WTException {
template = WTDocument.newMyWTDocument();
return template;
In order for the methods in the new delegate class to be called while creating a
document template for a MyWTDocument modeled subtype, a new property entry
needs to be added to codebase\com\ptc\windchill\enterprise\
EnterpriseServerFactoryDelegate.properties which should look like this (needs to
be on one line) -
wt.services/svc/default/com.ptc.windchill.enterprise.templates.Tem
platesObjectDelegate/null/wt.doc.MyWTDocument/0=com.ptc.windchill.
enterprise.templates.doc.server.TemplatesMyWTDocumentDelegate/dupl
icate
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
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" ]
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).
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
Template Robot
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 synch robot at 1b.
1b) The Synch 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 3a) This conditional router checks the
the change issue has been immediately state of the associated change request.
disassociated with the change request. If it is in state Completed, the
If so, the workflow cycles back to 1a; workflow continues to 3b (the end of
otherwise, it continues to the synch the process). If it is in state Cancelled,
robot at 2b. the workflow loops back to a point
near the beginning of the process.
Otherwise, the workflow continues to
the synch robot at 3b.
Template Robot
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 Synch on
Request Submit only).
This robot has been replaced with a conditional router followed by the synch
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.
Template Robot
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 Synch 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 synch robot. The synch 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.
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.
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.
This chapter describes how to enable support for custom parts and how to
customize automatic part generation for the Pro/ENGINEER, CATIA, and
CADDS workgroup managers.
Topic Page
Enabling Support for Custom Parts...................................................................12-2
Customizing Automatic Part Generation ..........................................................12-5
12-1
Enabling Support for Custom Parts
In the Workgroup Managers for Pro/ENGINEER, CATIA, and CADDS, you can
enable support for custom parts, which extend wt.part.WTPart. However, a
custom part must be modeled before any changes are made to the Workgroup
Manager. (For information on extending the Windchill object model, see the
Windchill Application Developer’s Guide and relevant chapters of this manual.)
These Workgroup Managers permit use of custom parts in most operations,
including Download, Checkout, Checkin, Associate, Disassociate, Open
Structure, and so on. However, the operations used to create parts, New Part and
Parts for Documents (automatic part generation), are specific to WTPart.
Additionally, when you view the properties of a custom part, new modeled
information will not be displayed. The properties page will display any IBAs you
may have added to the custom part.
Automatic custom part generation is supported through the File>Parts for
Documents menu command available within the Workspace Browser. To enable
automatic custom part generation when using this command, however, you must
either create or modify your automatic part creator. For more information, see
Automatic Part Generation, later in this chapter.
Note: In this section, wt.part.MYWTPart is used as an example of a custom part.
2. Regenerate the wmpref.jar bootstrap file. (For more information about the
bootstrap file, see the Windchill System Administrator’s Guide.)
Note: The Data Source value must be windchill. The ID value must be the
class name of the custom part (in this case, MYWTPart). The relative path
name specified for the Icon value should be the value specified when the
custom part was modeled (in this case, wt/clients/images/mywtpart.gif).
4. Copy the custom part image file, with the same relative path name as under
${WT_HOME}/codebase, to ${WT_HOME/codebase/cfg/default/gifs. For
example, the following file:
${WT_HOME}/codebase/wt/clients/images/mywtpart.gif
6. Stop and restart the registry server in order to make the changes available to
the Workgroup Manager client.
The interface methods are called during execution of the File>Parts for
Documents command, for any selected CAD Document (EPMDocument) with
no associated parts. The implementer returns an instance of WTPart,which is an
existing part or new part, or null (null is a valid return for either method). If a new
part is returned, it must be unique.
AutoPartCreator=com.ptc.epm.commands.autopart.
DefaultAutoPartGenerator
As shown in the following example, modify this value to name your automatic
part creator:
[general]
AutoPartCreator=com.ptc.epm.commands.autopart.MyAutoPartGenerator
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 ...........................................................................................................13-2
Basic Report Example .......................................................................................13-2
Import and Export of Report Templates..........................................................13-11
Customization Details .....................................................................................13-15
13-1
Overview
Reports are generated by applying presentation information to query result data.
Queries are built using the Windchill QueryBuilder 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.
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
QueryBuilder user interface, as follows. (For detailed usage instructions, use
the QueryBuilder online help.)
a. From Report Manager, click the New button. The QueryBuilder 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.
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 Cabinet
Attribute Name
Operator =
Value System
Description Optional.
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
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. If you have difficulty with this URL, try the site URL www.w3.org.
2. If you have difficulty with this URL, try the site URL www.w3.org.
3. If you have difficulty with this URL, try the site URL www.xslinfo.com.
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.
• 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. If you have difficulty with this URL, try the site URL www.xml.com.
5. If you have difficulty with this URL, try the site URL www.w3.org.
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.
Element Description
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.
Customizing Macros
Customizing macros uses the standard Windchill application services delegation
mechanism (for further information, see Chapter 5, Customizing
service.properties). 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.
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 Foldered
Attribute thePersistInfo.modifyStamp
Operator >
Note that the time cutoff macro now appears in the drop-down list.
d. Save the query.
4. Execute the report.
To customize the list of QueryBuilder 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.
Topic Page
Creating a Listener Service ...............................................................................14-2
14-1
Creating a Listener Service
A listener is a type of Windchill service. It has no methods that can be called by
clients, but instead registers a listener object that listens for events and responds to
them.
This example creates the projectaux (Project Auxiliary) package, which
implements the projectaux service. The projectaux service listens for an event that
signifies the creation of a project, and then creates a folder for that project in the
cabinet containing the project object.
This section describes how to create the service, test it, and add additional events.
Import Statements
//##begin user.imports preserve=yes
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import wt.events.KeyedEvent;
import wt.events.KeyedEventBranch;
import wt.events.KeyedEventListener;
import wt.fc.PersistenceHelper;
import wt.fc.Persistable;
import wt.fc.ObjectReference;
import wt.fc.PersistenceServerHelper;
import wt.fc.PersistenceManagerEvent;
import wt.folder.FolderHelper;
import wt.project.Project;
import wt.services.ManagerService;
import wt.services.ManagerServiceFactory;
import wt.services.ServiceEventListenerAdapter;
import wt.services.ManagerException;
import wt.util.WTProperties;
import wt.util.WTContext;
import wt.util.WTPropertyVetoException;
//##end user.imports
/*
* Internal Listener class
*/
class ProjectAuxEventListener extends ServiceEventListenerAdapter {
if ( keyedEvent.getEventType( ).equals(
PersistenceManagerEvent.POST_STORE ) ) {
processPostStoreEvent( ( Persistable )target );
}
}
}
FolderHelper.service.createSubFolder(newSubFolderName);
}
}
//##end user.operations
To add more events to your listener service, perform the following steps:
1. In the performStartupProcess() method, register the event listener by calling
the addEventListener() method again. You can use the same listener instance
as before, just specify a different event. For example, you might want to listen
for two events, as follows:
getManagerService( ).addEventListener( listener,
PersistenceManagerEvent.generateEventKey(
PersistenceManagerEvent.POST_STORE ) );
Topic Page
About the xconfmanager Utility........................................................................15-2
About the Windchill Command ........................................................................15-5
15-1
About the xconfmanager Utility
The xconfmanager is a command line utility that you can run to add, remove, or
modify properties in any Windchill property file. With one exception, the
following files are managed by Windchill Information Modeler and should not be
edited manually or edited with the xconfmanager:
• associationRegistry.properties
• classRegistry.properties
• descendentRegistry.properties
• modelRegistry.properties
The xconfmanager utility saves your changes in the site.xconf file and provides an
option to generate updated property files using the updates in the site.xconf file.
The site.xconf file contains the changes made to Windchill property files starting
with the installation and continuing with each use of the xconfmanager utility 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 xconfmanger utility and
management of the Windchill property files is documented in the Windchill
System Administrator’s Guide in the Administering Runtime Services chapter.
Anyone with write access to the XCONF and property files under the Windchill
installation directory can successfully run the xconfmanager utility. The
xconfigmanger is executed from the command line from within a windchill shell
See About the windchill Command chapter for more information about the
windchill shell.
The syntax of xconfmanager command is as follows:
xconfmanager {-FhuwvV} {-r <product_root>} {-s <property_pair>
{-t <property_file>}} {--reset <property_names>}
{--undefine <property_names>} {-d <property_names>} {-p}
For the purposes of modifying Windchill properties, you will primarily use the set
(s), targeFile (t), and propagate (p) parameters.
• set is used to define the property and new property value. See the Formatting
Property Value Guidelines section (below) for information about formatting
the <property_pair) value.
• targetFile is used to specify the directory location of the property file. If the
file name or path contains spaces, you must enclose the <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.
• propagate is used to propagate the changes made to the XCONF files into the
property file being modified in order to keep the XCONF and the property
files in synch with one another.
• To display the current settings for a property, execute the following command
from the windchill shell:
xconfmanager -d <property_names>
On a UNIX system, you can use doubles quotes or you can escape the space
character with a backslash. For example, use the following:
-s wt.inf.container.SiteOrganization.name=ACME\ Corporation"
On UNIX, dollar signs are usually interpreted by shells as variable prefixes. To set
a property value that has a dollar symbol in it, use single quotes around the
argument so that it is not interpreted by the shell or use backslash to escape the
dollar symbols. For example, use either of the following:
or
-s wt.homepage.jsp=
‘\$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp
Other than escaping arguments so that the command line shell does not
misinterpret them, the values should not need to be escaped any further to be
compatible with XML or property file syntaxes. The xconfmanager escapes
property names and values automatically if necessary.
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 Actions
Action Description
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.
Topic Page
The Three Applets .............................................................................................16-2
Advantages and Disadvantages .........................................................................16-2
The File Selection Applet..................................................................................16-3
The Upload Applet ..........................................................................................16-11
The Download Applet .....................................................................................16-31
16-1
The Three Applets
File selection applet
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
wt\clients\util\http\UploadApplet.java
Content download applet
wt\clients\util\http\DownloadApplet.java
File Selection
There are two ways to choose one or more files for upload in Windchill.
1. Launch a file browser from the Windchill UI and navigate to the desired
file(s).
2. Drag one or more file icons from the desktop or Windows Explorer onto a
drop target in the Windchill UI.
Button look:
<param name="buttonLook" value="true">
Hyperlink-with-icon look:
<param name="buttonLook" value="false">
<param name="imageFilename" value="wtcore/images/attach_add.gif">
<param name="multiSelect" value="true">
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.
Note: Due to restrictions on the number of characters that can be sent at once, the
FileChooserDropApplet requires Javascript that supports receiving long filepath
strings in multiple chunks. As of 7.0, other file selection applets do not support
this ability and are thus limited in the total combined length of filepaths they can
return in a single browse/drop.
function setPathFromApplet(newValue,fileSep,pathComplete) {
appletString = appletString + newValue;
if ( pathComplete != null && pathComplete == "true" ) {
window.focus();
var endPos = newValue.indexOf( DELIM, 0 );
if ( endPos >= 0 ) {
function setPath(newValue,fileSep,pathComplete) {
appletString = appletString + newValue;
if ( pathComplete != null && pathComplete == "true" ) {window.focus();
submitNewAttachments(CheckFilePathSeparators(appletString,fileSep) );appletString =
"";
}
}
FileChooserDropApplet
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.
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>
if ( !cancelled ) {
alert( uploadFailureMessage );
}
</SCRIPT>
Topic Page
The EnumeratedType Class................................................................................A-2
Creating an EnumeratedType Subclass..............................................................A-3
Editing the Resource Info for an Enumerated Type...........................................A-7
Localizing an Enumerated Type.......................................................................A-10
Extending an Enumerated Type .......................................................................A-11
The Enumerated Type Customization Utility ..................................................A-12
GUI Usage of an Enumerated Type .................................................................A-13
A-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().
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.
Modeled constants are Static and Final. A value definition for each modeled
constant will be generated in the resource info file.
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.
# <key>.value=
# <key>.comment=
# <key>.argComment<n>=
# <key>.constant=
# <key>.customizable=
# <key>.deprecated=
# <key>.abbreviatedDisplay=
# <key>.fullDisplay=
# <key>.shortDescription=
# <key>.longDescription=
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 class’s 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
• 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
For information on locales, and codes for languages and countries, see the
Javadoc for java.util.Locale.
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.
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.
To see the changes you have made after using the utility, perform the following
steps:
1. Restart the method server.
2. Rebuild the wt.jar file 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.)
To test new values that impact GUIs, you may want to run in an environment
without a wt.jar file so you can see the changes without downloading the new file.
This appendix lists the extendable classes 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, the
Windchill Application Developer’s Guide, and in the Windchill Javadoc.
Topic Page
PDM Business Information Classes ................................................................... B-2
Enterprise Business Information Classes ........................................................... B-2
Windchill Services ............................................................................................. B-2
Foundation Classes............................................................................................. B-3
PDM Auxiliary Business Information Classes................................................... B-3
Business Logic Classes ...................................................................................... B-3
Server Development Classes .............................................................................. B-4
Client Development Classes............................................................................... B-5
B-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-the-
box PDM objects, start by extending these classes. For an overview of these
classes, see the Windchill Application Developer’s Guide chapter on the
enterprise layer.
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
Windchill Services
The following extendable classes represent the Windchill plug-and-play
interfaces. For more information, see the Windchill Application Developer’s
Guide chapter on Windchill services.
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