Advanced Customization > Business Logic Customization > Packages Customization > Customization for Downgrading Deliveries
  
Customization for Downgrading Deliveries
This section describes different use cases and corresponding actions to be taken to incorporate changes in the information model exchanged during replication.
Usecase: Handling Meta Data Changes across Windchill releases
If there are changes in the DTD in the latest version of Windchill releases, perform following actions:
1. Compare the DTDs to identify the changes.
* 
The location of the DTD files is as follows:
Windchill 11.1 M020: Windchill/loadXMLFiles/standard11_1.dtd
2. Identify the XSL transformation pattern for the changes. For more details about the scenarios and examples, refer XSL Transformation Scenarios.
3. Update the release specific XSL template and check in corresponding folders of respective source variant.
4. Extract them to release specific folder present in codebase/registry.
* 
XSL templates are created based on DTD element structure defined in source DTD. You have to modify the respective XSLs. Do not alter the inclusions.
5. Create a downgrade delivery to ensure that the custom object is included.
For more information, see Create a package.
Example
Attribute Attr1 is newly added to WTPart DTD in Windchill 11.2.0.0. During the creation of downgrade deliveries for Windchill 11.1 M020 Attr1 should be filtered as part of XSL changes. You need to update OOTB checked in WTPart.xsl present in $(wt.codebase.location)/registry/XSLRepo/11.1.M020/WTPart.xsl.
All other contents of WTPart.xsl must be retained as is. Only Attr1 copy must be replaced with new XSL script as mentioned in XSL Transformation Scenarios.
Usecase: Handling Unsupported Objects
If an object is not supported for downgrade in a particular Windchill release, configure the xxx_filter.properties file to specify the elements of objects to be filtered or removed during the creation of downgrade deliveries, where XXX refers to the module name of the application developers.
Filtering an Object from Downgrade Delivery
ELEMENT1 is a element of wt.TestObject object which was added in Windchill 11.2.0.0 release, but wt.TestObject is not supported with Windchill 11.1 M020. Before creating downgrade deliveries in Windchill 11.2.0.0 for Windchill 11.1 M020 configure the tagsToFilter property in xxx_filter.properties to filter ELEMENT1. The xxx_filter.properties file is located at $(wt.codebase.location)\registry\transformationEngine\filter\11.1.M020\xxx_filter.properties
tagsToFilter=ELEMENT1
Usecase: Handling Unsupported Soft Types
If a soft type is not supported for downgrade in a recent Windchill release, add transformation filter with XPath to filter a soft type while downgrading.
Filtering a Soft Type from Downgrade Delivery
To filter a soft type org.rnd.ComputerPart from Windchill 11.2.0.0 while downgrading to Windchill 11.1 M020, add transformation filter with XPath as:
externalTypeId=WCTYPE|wt.part.WTPart|org.rnd.ComputerPart
Transformation XPath filter is configured in the following location:
$(wt.codebase.location)/registry/transformationEngine/filter/11.1.M020/xpath_filter.xml
<?xml version =”1.0" encoding="UTF-8" standalone="yes"?>
<AdvancedXpathFilter xmlns=”http://www.ptc.com/AdvancedXpathFilter”>
<xpathFilterGroup>
<xpath>//WTPart/externalTypeId==”WCTYPE|wt.part.WTPart|org.rnd.ComputerPart”</xpath>
</xpathFilterGroup>
</AdvancedXpathFilter>
XPATH Based Filter Performance Considerations
XPATH based filters require indexes to be created based on the selected XPATHs. This prevents insertion and deletion cost for XMLDOCUMENT table which is used during the downgrade process. To use the capability of parameter XPATH based index, perform the following step from the Windchill shell.
windchill wt.pds.tools.xdb.CreateIndex <dbUser> <dbPassword> [debug]
Where,
dbUser — DB schema user
dbPassword — DB password
debug — Optional parameter to run in debug mode
When this command runs without any parameter, it displays the usage message.
* 
Run this tool in the offline mode.
Run this tool for OOTB XPATH filter and Customization filters.
The indexes on XMLDocument table are checked to verify this tool.
This tool is supported only for Oracle Database in the Windchill 11.2.0.0 release.
Check the SQL plan, the query which uses XPATHs, to verify the XDB index usage during XPATH filter.
Refer to Oracle administrative information on XDB Index for mode details.
Defining the XPath Filter for AND and OR Conditions
Condition for AND:
Create a $(wt.codebase.location)/registry/transformationEngine/filter/11.1.M020/WTPart_xpath_filter.xml
Specify the Xpath filter condition within the <xpathFilterGroup></xpathFilterGroup>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AdvancedXpathFilter xmlns="http://www.ptc.com/AdvancedXpathFilter" >
<xpathFilterGroup>
<xpath>//WTPart/view="Design"</xpath>
<xpath>//WTPart/externalTypeId="WCTYPE|wt.part.WTPart|com.ptc.ptcnet.wt.part_type1"</xpath>
</xpathFilterGroup>
</AdvancedXpathFilter>
Condition for OR :
Create a $(wt.codebase.location)/registry/transformationEngine/filter/11.1.M020/WTPart_xpath_filter.xml
Specify the individual OR conditions in Separate  <xpathFilterGroup></xpathFilterGroup>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AdvancedXpathFilter xmlns="http://www.ptc.com/AdvancedXpathFilter" >
<xpathFilterGroup>
<xpath>//WTPart/externalTypeId="WCTYPE|wt.part.WTPart|com.ptc.ptcnet.wt.part_type1"</xpath
</xpathFilterGroup>
<xpathFilterGroup>
<xpath>//WTDocument/ObjectID/localId =”wt.doc.WTDocument:200425”</xpath>
</xpathFilterGroup>
</AdvancedXpathFilter>
Adding Dependency Filter
Dependency filter is a Java based filter used to filter any set of dependent objects which are not valid to exchange if any of its required objects are filtered out either by xpath or property based filtering.
This example shows filtering WTPartUsageLink if any WTPart is filtered.
XMLFilterEntry
By default, for all root tags, default XML filter entry carries information about localId and ufid. But usagelinkfilter entry must contain its role A and role B information also when it is queried.
Example
package com.ptc.transformation.filter.test;

import com.ptc.transformation.core.TransformationException;
import com.ptc.transformation.filter.DefaultXMLFilterEntry;

public class WTPartUsageLinkFilterEntry extends DefaultXMLFilterEntry {
public static final String USES_OBJECT_REFERENCE_UFID = "/uses/ObjectReference/ufid";
public static final String USED_BY_OBJECT_REFERENCE_UFID = "/usedBy/ObjectReference/ufid";
private static final long serialVersionUID = 1L;

@Override
public void initialize(String rootTag) throws TransformationException {
super.initialize(rootTag);
// Capture RoleA and RoleB also as part of filter entry
getIdentityEntries().put(getRootTag() + USED_BY_OBJECT_REFERENCE_UFID, null);
getIdentityEntries().put(getRootTag() + USES_OBJECT_REFERENCE_UFID, null);
}
}
This overrides the initialize method to add few more tags as part of identity keys.
WTPartUsageLinkFilter entry can be configured through Windchill service delegate factory pattern as shown below:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">
<Configuration targetFile="codebase/service.properties">
<Service context="default" name="com.ptc.transformation.filter.DependencyFilter">
<Option cardinality="duplicate" requestor="java.lang.Object" selector="UsageLink" serviceClass="com.ptc.transformation.filter.test.UsageLinkFilter" />
</Service>

Service context="default" name="com.ptc.transformation.filter.XMLFilterEntry">
Option cardinality="duplicate" requestor="java.lang.Object" selector="WTPartUsageLink" serviceClass="com.ptc.transformation.filter.test.WTPartUsageLinkFilterEntry" />
/Service>

Service context="default" name="com.ptc.transformation.core.TransformationFilter">
Option serviceClass="com.ptc.windchill.transform.util.TestTransformationFilter" requestor="java.lang.Object" selector="xpath_filter" cardinality="duplicate" />
/Service>
</Configuration>
You can configure your entries in your module specific service configuration.
UsageLinkFilter
Usage link filter is a sample Dependency filter which filters WTPartUsageLink if any WTPart role A or WTPart with master ufid is in role B.
Example
package com.ptc.transformation.filter.test;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.ptc.transformation.core.TransformationContext;
import com.ptc.transformation.core.TransformationException;
import com.ptc.transformation.filter.DefaultDependencyFilter;
import com.ptc.transformation.filter.DependencyFilterPriority;
import com.ptc.transformation.filter.FilterIdentityKey;
import com.ptc.transformation.filter.XMLFilterEntry;
import com.ptc.transformation.filter.XMLLookUpService;

import wt.util.WTException;
import wt.util.WTPropertyVetoException;

@FilterIdentityKey(keys = { "WTPart"})
public class UsageLinkFilter extends DefaultDependencyFilter {
public static final String ROOT_TAG = "WTPartUsageLink";
public static final String usedByPath = "WTPartUsageLink/usedBy/ObjectReference/ufid";
public static final String usesPath = "WTPartUsageLink/uses/ObjectReference/ufid";

@Override
public Collection<XMLFilterEntry> execute(Collection<XMLFilterEntry> inputEntries, TransformationContext context)
throws TransformationException {
Collection<XMLFilterEntry> usageLinkEntries = new HashSet<>();
Set<String> masterUfids = new HashSet<>();
Set<String> ufids = new HashSet<>();
for (XMLFilterEntry xmlFilterEntry : inputEntries) {
for (Map.Entry<String, String> entry : xmlFilterEntry.getIdentityEntries().entrySet()) {
String key = entry.getKey();
if (key.contains("/masterUfid")) {
masterUfids.add(entry.getValue());
}
if (key.contains("/ufid")) {
ufids.add(entry.getValue());
}
}
}

XMLLookUpService service = XMLLookUpService.getInstance(context);
Map<String, Collection<String>> filterEntries = new HashMap<>();
if (!ufids.isEmpty())
filterEntries.put(usedByPath, ufids);
if (!masterUfids.isEmpty())
filterEntries.put(usesPath, masterUfids);
try {
usageLinkEntries = service.getXMLFilterEntries(ROOT_TAG, filterEntries);
} catch (WTException | WTPropertyVetoException e) {
throw new TransformationException(e);
}
return usageLinkEntries;
}

@Override
public int getPriority() {
return DependencyFilterPriority.LINK_OBJECT_PRIORITY;
}
}
This configures annotation called FilterIdentityKey as shown below:
package com.ptc.transformation.filter;

import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;

@Retention(RUNTIME)

public @interface DependentOn {
FilterIdentityKey[] value() default {};
}
This defines the required dependent tags and additional filter identity required for its processing. In this case, it requires masterUfid as part of Part filter identity key, so it gets annotated as shown below:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configuration SYSTEM "xconf.dtd">
<Configuration targetFile="codebase/service.properties">
<Service context="default" name="com.ptc.transformation.filter.DependencyFilter">
<Option cardinality="duplicate" requestor="java.lang.Object" selector="UsageLink" serviceClass="com.ptc.transformation.filter.test.UsageLinkFilter" />
</Service>

<Service context="default" name="com.ptc.transformation.filter.XMLFilterEntry">
<Option cardinality="duplicate" requestor="java.lang.Object" selector="WTPartUsageLink" serviceClass="com.ptc.transformation.filter.test.WTPartUsageLinkFilterEntry" />
</Service>

<Service context="default" name="com.ptc.transformation.core.TransformationFilter">
<Option serviceClass="com.ptc.windchill.transform.util.TestTransformationFilter" requestor="java.lang.Object" selector="xpath_filter" cardinality="duplicate" />
</Service>
</Configuration>
For more information on customization of dependency filter , refer to Windchill Dependency Filtering for Downgraded Deliveries.
Handling Filter Configurations
You can find the filter configurations at the locations listed below.
Xpath based filter changes — $(wt.codebase.location)/registry/transformationEngine/filter/<releaseId>/xpath_filter.xml
Removal of XML files based on element name — $(wt.codebase.location)/registry/transformationEngine/filter/11.1.M020/filter.properties
Add elements to be removed in comma separated values.
Handling Batch Size During Transformation
You can use the property com.ptc.transformation.batchSize configured in $(wt.codebase)/wt.properties to control the batch size of the number of XMLs that get processed during transformation. This property controls the in-memory InputSource handling of XMLs that get processed before, during and after the transformation during the element handler process. The default value is 10000.
Additionally, configure the following properties in wt.properties to specify the cache and batch size for the number of XML files to be retained in memory. The property file is located at Windchill/codebase
com.ptc.transformation.dom.cache=100
com.ptc.transformation.batchSize=10000
Based on the allocated heap value you can configure the file number in these properties.