All pages
1 of 6

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Dynamic Field Data Transformation

CopyStorm/Restore has the ability to transform data in the CopyStorm backup database prior to writing it to the target Salesforce. Built-in data transformers include:

  • Scramble — replace each letter with a different letter, replace each number with a different number.

  • Email Scrambler — build a new email address of the same size but with random letters & digits.

  • Email Append Invalid — append “.invalid” to an email address.

  • Asterisk — replace the source data with “******”.

  • Random Dictionary Substitution — for Names, Countries, Cities, Streets…etc

  • Lorem Ipsum — replace a block of text to the infamous “Lorem ipsum dolor sit amet, consectetur adipiscing…”

  • Random Date/Time — replace a date or date/time with a random date or date/time within the same year.

Read more about built-in transformers in the

If the built-in transformers are insufficient for your needs the instructions in this article can be used to add a new transformer to CopyStorm/Restore. The approach described in this article is the same as what CopyStorm/Restore does internally.

To add a dictionary transformer that substitutes values from a provided list of values, you can create or update update the TransformerRegistry.xml file with a tag:

<Transformers> <Dictionary name=”My Transformer Name” file=”/path/to/a/file.txt”/>

This will add two new transformers:

  • Random: My Transformer Name

  • Uniform: My Transformer Name

These transformers will replace the input text with a value taken from the text file (one value per line). The Random transformer will replace each input value with a random line from the text file. The Uniform transformer will replace each input value with a line from the text file, always replacing the same input text with the same value from the text file.

The first step is to build a Java class implementing “com.capstorm.copystormrestore.transform.ITransformer”. The code below contains the implementation of the Asterisk transformer:

The parameters to the transform() method are:

Parameter
Description

The method must return the value to insert / update in Salesforce.

Once the class has been created, package it into a jar and put the jar into the “lib” subdirectory of the CopyStorm/Restore installation. CopyStorm/Restore will only find your class if it is installed in this directory.

For CopyStorm/Restore to discover a field transform it must be declared in a file named “TransformerRegistry.xml” and placed into a directory where CopyStorm/Restore looks for configuration files (for example, the “config” sub-directory of the CopyStormRestore installation).

The TransformerRegistry.xml file should look like the following:

Where:

  • “name” is the value that will appear in the CopyStorm/Restore GUI.

  • “class” is the full path to the class built in the first step.

To set up a build and test environment for a new transformer in Eclipse:

  • Create a new Java project.

  • Update the new project’s path to reference all jar files in the “lib” sub-directory of CopyStorm/Restore.

For other development environments, including building and testing on the command line, make sure that all the required Jars are on your Java class path.

If this is to much for your team send an email to and they will be happy to arrange a small service contract.

public class AsteriskTransformer implements ITransformer {
    @Override
    public String transform(String table, String column, int columnWidth, String recordId, String value) {
        if( StringUtils.isBlank(value)) { return value; }
        return StringUtils.repeat("*", value.length());
    }
}

table

The name of the table containing the column to transform.

column

The name of the column to transform.

columnWidth

<Transformers>
    <Transformer name="Asterisk" class="com.capstorm.copystormrestore.transform.AsteriskTransformer" />
</Transformers>

To Add a Dictionary Transformer

To Implement a Custom Transformer

Step 1: Build a Java Class That Implements a Transformer

Step 2: Create an XML Configuration File

Other Details

Fields to Restore Editor article.
sales@capstorm.com

The maximum width of the column value.

recordId

The Salesforce Id of the record being processed.

value

The current value of the column. This may be null.

How to Manage Table Groups

CopyStorm/Restore organizes tables into groups based on the probability of a table being directly selected for a restore. There are a number of groups predefined by CopyStorm/Restore:

Group Name
Description

Common

Tables that are typically used to drive a restore. A table is put into this group if it is added to the restore set and not also a member of another group.

Less Common

It is possible to add tables to an existing group or to create additional groups by editing the file “SalesforceTableFamilies.xml” in the “config” subdirectory of the CopyStorm/Restore installation. The default file contains documentation detailing how to add new records.

Several sample entries are included below.

All of the GEOCACHE custom tables begin with the prefix “geocache__” — this was determined by looking at the registered package prefix in Salesforce. The following XML will put all GEOCACHE tables into the Package group:

The following XML will create a new Group named “MyProject”, containing three tables:

Tables that are typically only restored because they are referenced by another table.

Uncommon

Tables that are typically not restored. Many of these are restored automatically on a sandbox refresh.

Custom

Contains all custom object tables (i.e. tables not created by Salesforce).

Package

Contains custom objects from well-known 3rd party packages. Not all packages are known by CopyStorm/Restore — please contact to add a new one to the built-in group.

System

Contains tables that are almost never restored. Most of these tables are restored automatically on a sandbox refresh.

Future

Contains tables that are not currently available to be restored but will be in the future. Tables in this group tend to have obscure, non-standard restore rules.

Not Restorable

Contains tables that cannot be restored using the Salesforce API.

<SalesforceTableFamily name="Package">
    <Pattern rule="geocache__.*" />
</SalesforceTableFamily>
<SalesforceTableFamily name="MyProject" >
    <Pattern rule="masterList__c" />
    <Pattern rule="masterSubList__c" />
    <Pattern rule="cookieJar__c" />
</SalesforceTableFamily>

Add All Tables in the Package From GEOCACHE to the Package Group

Place All Tables From My Project Into a New Group Named “MyProject”

support@capstorm.com

How to Set Table Specific Processing Options

There are a number of occasions that require table specific processing rules. This section describes how to augment the built-in table specific processing rules in CopyStorm/Restore.

The most common case requiring a table specific rule is a need to limit the number of records sent to Salesforce in a single batch. The default value, 200, may be too large for specific tables because of complex INSERT / UPDATE triggers causing the “Too Many DML Statements” error to be thrown by Salesforce.

CopyStorm/Restore supports overriding or extending the default table processing rules by editing a file named “TableRuleRegistry.xml” in a subdirectory “config” of the root CopyStorm/Restore directory. By default, CopyStorm/Restore includes a template TableRuleRegistry.xml with a large block comment explaining usage.

Several common overrides are included below.

The following sample TableRuleRegistry.xml file will cause CopyStorm/Restore to limit all writes to Salesforce to ten or fewer records:

The following sample TableRuleRegistry.xml file will cause CopyStorm/Restore to limit all inserts / updates to the Case table to five or fewer records.

<TableRules>
    <TableRule name="default" restoreBatchSize="20" />
</TableRules>

Limit All Salesforce Writes to Ten Records at a Time

Limit All Contract Record Writes to Five at a Time

<TableRules>
    <TableRule name="Case" restoreBatchSize="5" />
</TableRules>

Configuration Files

CopyStorm/Restore supports saving a restore set configuration in two formats:

  • Plain-text XML.

  • Encrypted text using 256-bit DES encryption.

Both formats allow saving Salesforce and database credentials — passwords are always encrypted. A CopyStorm/Restore session can be completely restored using the File / Open operation.

The “Save” dialog allows the selection of a directory and file name, as well as options to Encrypt and Save Passwords:

The plain-text XML version of the file is not intended to be edited by hand, as it is fairly complex. If problems arise from hand-editing a configuration file, Capstorm may not supply support.

How To Use a Text Field As a Reference Field

While it is best practice to store Salesforce Reference Ids in Reference Fields, there are a handful of situations where a Reference Id may be stored in a Text field.

By default, CopyStorm/Restore will use Reference Field metadata to determine whether or not a field contains a Reference Id, and which table(s) the Id may reference. In cases where Reference Ids are stored in Text fields CopyStorm/Restore can be configured to treat the field as a Reference Field, which will cause CopyStorm/Restore to:

  • Take the reference information into account when determining the table restore order.

  • Use CopyStorm/Restore’s Old Id to New Id mapping to ensure referential integrity when uploading field values for the Text field.

To configure CopyStorm/Restore to treat a Text field as a Reference field:

  1. Create a file [CopyStormRestore]/config/CopyForceMetadata.xml

  2. Use the following template to populate the file:

<CopyForceMetaData>
<!--
Treat the field Contact.TextField__c as a reference field which:
- Contains references to either the Account or Contact table.
- Uses a relationship name of MyCustomRelationship.
-->
	<FieldRule table="Contact" field="TextField__c" relatedToTable="Account,Contact" relationshipName="MyCustomRelationship"/>
</CopyForceMetaData>

How to Setup Complex Mapping Rules

Migrating data from a Salesforce instance to an unrelated Salesforce instance the mapping between system tables can be complex and mapping rules are needed to control how records in a CopyStorm backup map to records in a target Salesforce.

This article review two types of mapping rules:

  • Simple column value mapping rules.

  • Complex mapping rules.

The Basics

All mapping rules provide a map of Ids in the CopyStorm backup to corresponding Ids in the target Salesforce.

For example:

  • If a User record in CopyStorm has the same email address as a record in the target Salesforce, map the CopyStorm User.Id to the Salesforce User.Id.

Mapping rules are stored in a configuration file named “DefaultRecordMapRule.xml”, stored in any of the normal places for CopyStorm/Restore configuration files. It contains two types of supported entries:

  • ColumnBasedBuilder — a mapping rule determining a match between two records based on the value of one or more columns.

  • FunctionBasedBuilder — a mapping rule determining a match between two records based on user supplied Java code, using any technique to determine if records match.

The built-in DefaultRecordMapRule.xml looks like:

A Simple Column Value Mapping Rule is used when a CopyStorm and Salesforce record should be considered the same if one or more columns in the two records match. For example, the following rule indicates that two User records are the same if the records contain the same email address:

A rule indicating that Record Types match if they are for the same SObject and have the same Name is:

A Function Based Rule uses arbitrary Java code to build an Id mapping between CopyStorm records and Salesforce records. For example:

  • The built-in Pricebook2 function rule ensures that the standard pricebook in the CopyStorm backup maps to the standard pricebook in the target Salesforce.

  • The built-in Organization function rule ensures that the Salesforce Org Id in the CopyStorm backup maps to the Org Id of the target Salesforce.

There are two steps required to add a new Function Based Rule to CopyStorm/Restore:

  1. Write a Java class implementing the rule and store the implementation in a jar within the “lib” sub-directory of the CopyStorm/Restore installation.

  2. Add a “FunctionBasedBuilder” XML entry to the “DefaultRecordMapRuleBuilder.xml” file.

For example, this is the function based rule for Organization built into CopyStorm/Restore:

Simple Column Value Mapping Rules

Function Based Rule

 <DefaultRecordMapRuleBuilders>

    <!-- Column Based Builders match records based just on the values of one or more columns. -->
    <ColumnBasedBuilder tableName="User" columns="Email" /> 
    <ColumnBasedBuilder tableName="Profile" columns="Name" /> 
    <ColumnBasedBuilder tableName="UserRole" columns="Name" /> 
    <ColumnBasedBuilder tableName="Group" columns="Name" /> 
    <ColumnBasedBuilder tableName="RecordType" columns="Name,SObjectType" />

    <!-- Function based builders require custom code to build a mapping. -->
    <FunctionBasedBuilder tableName="Pricebook2" class="Pricebook2RecordMapRuleBuilder" /> 
    <FunctionBasedBuilder tableName="Organization" class="OrganizationRecordMapRuleBuilder" />

</DefaultRecordMapRuleBuilders>
<DefaultRecordMapRuleBuilders>
    <ColumnBasedBuilder tableName="User" columns="Email" />
</DefaultRecordMapRuleBuilders>
<DefaultRecordMapRuleBuilders>
    <ColumnBasedBuilder tableName="RecordType" columns="Name,SObjectType" />
</DefaultRecordMapRuleBuilders>
public class OrganizationRecordMapRuleBuilder extends AbstractDefaultRecordMapBuilder {

    private static String ORGANIZATION = "Organization";

    /**
    * Build a list of rules that map from CopyStorm record ids to ids in the target Salesforce.
    *
    * @param session -- connection to the target Salesforce.
    * @param dataSource -- connection to the source CopyStorm database.
    * @returns list of rules mapping CopyStorm ids to Salesforce Ids
    */
    @Override public List buildRules(Session session, DataSource dataSource) throws Exception {
        CopyForceTableFactory copyForceTableFactory = CopyForceTableFactory.getInstance(); 
        List results = new ArrayList(); 

        //
        // If the CopyStorm backup does not include the Organization table then we have no way of determining the original organization id.
        //
        if( !copyForceTableFactory.isTableDefined(dataSource, ORGANIZATION )) { return new ArrayList(); } 

        JdbcTemplate jdbcTemplate = new JdbcTemplate( dataSource ); 
        ICopyForceTable csTable = copyForceTableFactory.getTable(dataSource, ORGANIZATION ); 
        List csOrgs = jdbcTemplate.queryForList( "SELECT Id FROM " + csTable.getCopyForceName()  , String.class ); 

        if( 1 != csOrgs.size()) { return results; } 

        RecordMapRule rule = new RecordMapRule(ORGANIZATION, "Id"); 
        rule.getValueMap().put(csOrgs.get(0), session.getUserInfo().getOrganizationId()); 
        results.add(rule); 
        return results;
    }
}