Manual Task Synchronization Configuration (Advanced)

This section documents the steps required to configure Tasktop Sync manually. Note that this section assumes that you are familiar with the Tasktop Sync UI, terminology, and concepts described in the previous sections. If you are configuring Tasktop Sync for the first time, or creating a task mapping which does not require complicated logic, then we recommend you configure your mappings as described in the Task Synchronization Configuration section.

Manually configuring Tasktop Sync follows these steps:

  1. Create task repositories. In this step you create connections to each of the repositories you want Tasktop Sync to be aware of.
  2. Create changes and initialization queries for each repository. In this step you create the queries which define which tasks in your repository are visible to Tasktop Sync for synchronization.
  3. Setup the synchronizer configuration file. In this step you specify several runtime characteristics of Tasktop Sync and explicitly specify which repositories are synced and how they are synced. There are several subparts to this step:
    1. Create person mappings between repositories (optional). In this step you configure the user identification mappings between repositories. This step is required only when your repositories use different user IDs for the same user.
    2. Define task mappings between repositories. In this step you specify how a task in one repository is synced to its proxy task in another repository. This step also has several subparts.
  4. Configure logging (optional, maintenance section).
  5. Define sync history trimming policy (optional, maintenance section).

Before you begin configuration, we recommend that you first skim this section in its entirety to get an idea of how Tasktop Sync is configured. Then read the sections of Certified Connectors that apply to your setup, since parts of the configuration will differ depending on which vendors you use.

Repository Connections

The first step in configuring Tasktop Sync is to set up connections to the repositories that Tasktop Sync will connect to. This section describes how to manually create repository connections for use. Note that repository connections will have already been created if you created a task mapping using the Quick Start Wizard and task mapping editor tools provided in Tasktop Sync.

Right-click in the Sync Tasks view and select “Add Task Repository...”, or click the “Add Task Repository...” button in the top right corner of the view, to initiate repository creation. Follow the on-screen instructions to create the repository. Note the value you use in the Server: field of the repository as you will need to use this value to specify which repositories should be synchronized.

Once you have filled out that form, we strongly recommend that you validate your credentials before finishing; press the Validate Settings button to make sure that you can connect to the repository.

Custom Authentication

Repositories can be configured to use custom authentication e.g. single sign-on systems. To configure such an authentication you can use the “Additional Settings” section within the repository dialog.

The first thing to do is to select the Authentication of your choice e.g. “CA Single Sign-On (Login Form)”. “Standard Authentication” is the default and requires no additional configuration.

After selecting the authentication you need to provide input for the required fields. In the case of “CA Single Sign-On (Login Form)” this is a URL.

Authentication Settings

Some authentications need to fetch additional settings dynamically. For this reason the “Connect...” button needs to be pressed after entering values for the required fields. The next step is to fill out the additional settings that appear after connecting by following the on screen instructions.

Once you have filled out that form, we strongly recommend that you validate your credentials before finishing; press the Validate Settings button to make sure that you can connect to the repository.

Create Queries

Note that queries may have already been created if you created a task mapping using the Quick Start Wizard and task mapping editor tools provided in Tasktop Sync.

You need to specify two queries for each configured repository: the initialization query and the changes query. These queries define the tasks which come to Tasktop Sync as input. For example, if you only want defects to synchronize but don’t care about test cases, then you would set up your queries to return only defects.

To create queries, go to the Sync Tasks view and right-click on the repository that you would like to create a query for and select “New Query...”, or click the “New Query...” button in the top right corner of the view.

At this point, you will get a wizard which walks you through creating a query for the specified repository. As an example here is the first page of the HPE QC / ALM new query wizard:
Add query wizard for HPE QC / ALM

It is possible to use a query that you have saved on the server. We advise doing so when possible. In such cases, the first page of the query-building wizard will say something like “Create query using a favorite filter”. Select that radio button. You will then be able to choose from named queries from the repository server:
Selecting a favourite query in HPE QC / ALM

Otherwise, select the radio button that says something like “Create query using a form” from the first page of the wizard and fill out the form to create a query for that repository.

Note: Depending on your task repository’s capabilities, there may be a restriction on the tasks you wish to sync which cannot be specified with a query. This is a normal situation, and Tasktop Sync provides finer-grained tools for selecting which tasks should be synced (discussed in the attribute mapping section). However, you should create queries which capture as few extraneous tasks as possible, in order to reduce communication bandwidth usage between Tasktop Sync and the repository server.

Initialization Query

The initialization query is designed to be used to determine all of the tasks you are interested in synchronizing in a repository so that you can easily synchronize all existing tasks of interest in a new installation of Tasktop Sync, or can reinitialize synchronization between two repositories if you change your synchronization mappings. As such, the initialization query is only run manually, never automatically.

Under ideal conditions, you will run the initialization query once, when you are doing your initial synchronization, and if necessary again if you change your synchronization configuration. For your initialization query, we advise using a query that is guaranteed to get every last task that might possibly be of interest, even if the query is computationally expensive.

Changes Query

While the initialization query is run manually and only a few times, the changes query is run frequently to determine which tasks have changed recently and require synchronization. The changes query is run automatically at a configurable time interval or a cron schedule in the synchronizer.xml.

Because it is run so frequently, it should be designed more carefully than the initialization query to run quickly and to return as small a number of tasks as possible while still returning all the tasks of interest. While you should only get recently-changed tasks, “recent” is a relative term. The farther back in time your query extends, the more tasks will be found. This means that there is less danger of omitting relevant tasks (for example, because a server went down for longer than the last query execution) but that it will take longer to run. We recommend that your changes query get tasks which have changed in the past day.

synchronizer.xml

The file synchronizer.xml is the main configuration file, specifying the overall runtime characteristics of the synchronizer as well as all task mappings and user mappings. It is stored in the Tasktop Sync working directory.

The primary way to configure the synchronizer.xml file is via the Task Mapping Editor. Before proceeding with this section, please read the Task Synchronization Configuration section, as it discusses the specifics of the form and function of the synchronizer.xml file itself.

You can access the synchronizer.xml configuration file for editing by clicking on the gear icon in the right of the title bar of the Services view.

Open synchronizer.xml button in the Services view

Note that we recommended that you do not edit the synchronizer.xml file, or files referenced by synchronizer.xml, in external editors. Tasktop Sync assumes the UTF-8 character encoding of the configuration files. Editing these files outside of a UTF-8 environment may cause Tasktop Sync to work incorrectly. Extra care must also be taken when pasting content into the configuration files.

The synchronizer.xml file has four main sections, where you specify

The task mappings section can be further broken down into two sections:

Below is an example of a synchronizer.xml file which synchronizes three task attributes (summary, description, and owner) between an HPE QC / ALM repository and an IBM Rational Team Concert repository. The individual elements of the file are discussed afterwards.

<sync-model
   default-hide-query-progress="false"
   worker-threads="5"
   default-query-interval-minutes="0"
   pause-on-start="false"
   xmlns="http://tasktop.com/xml/ns/sync/model"
   version="4.0.0">
   
   <person-mapping name="PersonMap" mapping-path="person-map.xml"/>
   
   <task-mapping id="1"
                 display-name="Defects"
                 conflict-notification-policy="Log"
                 person-mapping="PersonMap">
     
     <!-- HPE QC / ALM Repository -->
     <repository proxy-creation-trigger="all"
                 auto-comment-user="developer1"
                 id="com.tasktop.sync.QC"
                 url="http://qc.example.com:8080/qcbin;SYNCHRONIZER;ProjectArea">
         <scope>
             <field id="itemType" value="BUG"/>
         </scope>
         <source>
             <query name="initialization" value="Tasktop Sync - HPE QC / ALM - All Defects"/>
             <query name="changes" value="Tasktop Sync - HPE QC / ALM - Recently Modified Defects"/>
         </source>
         <proxy-storage store="attribute" attribute-id="BG_USER_01"/>
     </repository>
     
     <!-- IBM Rational Team Concert Repository -->
     <repository proxy-creation-trigger="all"
                 auto-comment-user="tester1"
                 id="com.tasktop.sync.RTC"
                 url="https://rtc.example.com:9443/ccm">
          <scope>
              <field id="itemType" value="task"/>
              <field id="project"  value="RTCProjectName"/>
          </scope>
          <source>
              <query name="initialization" value="Tasktop Sync - IBM Rational Team Concert - All Defects"/>
              <query name="changes" value="Tasktop Sync - IBM Rational Team Concert - Recently Modified Defects"/>
         </source>
         <proxy-storage store="task-relations"/>
     </repository> 
     
     <!-- Specification of comment mappings between repositories ..?
     <comment-mapping>
         <repository sync-incoming-comments="true" comment-content-type="text/html" />
         <repository sync-incoming-comments="true" comment-content-type="text/plain;markup=RTCRichText" />
     </comment-mapping>
     
     <!-- Specification of task attribute mappings between repositories -->
     <attribute-mapping key="BG_DESCRIPTION"/>
     <attribute-mapping key="BG_SUMMARY"/>
     <attribute-mapping>
        <attribute-key key="BG_RESPONSIBLE" caster="person"/>
        <attribute-key key="BG_RESPONSIBLE" caster="person"/>
     </attribute-mapping>
   </task-mapping>

    <job name="StatisticsEmail" type="StatisticsEmail" schedule="0 0 0 * * ?"/>
    <job name="MetricsEmail" type="MetricsEmail" schedule="0 0 0 1 * ?"/>

    <statistics-notification>
        <email address="statsUser1@example.com"/>
        <email address="statsUser2@example.com"/>
    </statistics-notification>

    <error-notification include-synchronization-errors="true" include-synchronization-conflicts="true" include-query-errors="true">
        <email address="errorUser@example.com"/>
    </error-notification>
</sync-model>

Run Characteristics

The run characteristics are specified in the root node of synchronizer.xml: the sync-model element. It contains several attributes which you may configure as desired:

Attribute Value Type Description Default
pause-on-start true or false Specifies whether Tasktop Sync should be paused when it starts. false
default-query-interval-minutes non-negative decimal Specifies how many minutes to wait between changes queries. If you wish to synchronize continuously, set this attribute to “0”. For longer delays, set it higher. Either this, or the default-query-schedule should be specified. 1.0
default-query-schedule a cron expression Specifies when to run the changes queries. Either this, or the default-query-interval-minutes should be specified. 0/30 * * * * ?
worker-threads positive integer Specifies how many threads to allocate to processing synchronizations. 5
default-hide-query-progress true or false Specifies whether or not the Progress view is used when the queries are run. false
update-repository-configurations-on-start true or false Specifies whether or not to update the repository configuration of every repository referenced by a task mapping when Tasktop Sync starts up. true
repair-proxy-associations true or false If true, Tasktop Sync will make a best effort to automatically repair missing proxy associations. Tasktop Sync will only be able to repair proxy associations on tasks if the synchronization information for those tasks exists in Tasktop Sync’s cache. Note that this functionality is required for normal functioning of Tasktop Sync. true
attachment-limit integer Specifies the maximum number of attachments Tasktop Sync will post to a single task. When a task with more than this number of attachments is encountered then synchronization of attachments will be aborted and a warning will be written to the log. Synchronization of other attributes will continue normally. A negative number indicates an unlimited number of attachments. 100
maximum-submissions-per-sync integer Specifies the maximum number of times Tasktop Sync will submit changes per synchronization when using scripted attribute handlers that are configured to submit multiple times. If a task synchronization submits changes more often than this number, the synchronization will enter the error state. 15

Person Mapping Definitions (Optional)

It is common for a person to have different identities on each repository they use. For example, a person may be identified by a username in one repository and by an email address in another. Person mappings can be used to map between a person’s identities in different repositories when determining, for example, the owner or reporter. (Note that you will need to define a person caster for any attributes which should use the person mapping. See Using Person Mappings below.)

The person-mapping element declares a person mapping for use in the rest of the configuration file. It specifies the path to the file containing the definition of the person mapping. In our above example we have the following definition:

<person-mapping name="PersonMap" mapping-path="person-map.xml"/>

This creates a person mapping named “PersonMap” which is specified in the file “person-map.xml” in the working directory. Once a person mapping has been defined in this way, it is available for use in all following task-mapping clauses. See Person Mapping Files for their structure and syntax. You will need to write a person mapping file for each person mapping you define.

When you declare a person mapping in the synchronizer.xml file, the Tasktop Sync Services view will display a node for this mapping. Double-clicking the node will create a sample person mapping file and open it for editing.

The default-person-id in the repository element specifies the default identity which will be used for that repository, when Tasktop Sync encounters a person identity not included in the mapping.

Task Mapping Specification

Each task mapping specifies a mapping between two repository items which the synchronizer should keep in sync. Task mappings are specified in the task-mapping element.

There are three parts to a task-mapping. The first is the specification of behaviour that applies to the entire task mapping, the second defines the repositories together with properties that should participate in task synchronization, and the third part defines the mapping between individual task attributes in each of the repositories.

There are four options that are set as attributes on the task-mapping element that govern some global behaviour of the mapping:

Attribute Value Type Description
id A unique value Specifies a unique system ID for this mapping. Once tasks have been synced using this mapping, this value should not be changed.
display-name Any text Specifies a descriptive name for the mapping.
conflict-resolution-policy no-sync, repository-1-dominates, or repository-2-dominates Specifies which conflict resolution policy to use. “1” and “2” refer to the order the repositories are specified in the repository element, below. The default is no-sync.
conflict-notification-policy Comment or Log Specifies how conflicts are reported by Tasktop Sync. When Comment is specified, a comment is appended to the task to indicate the conflict in addition to logging it in the log files. Log is the default, and specifies that the conflict should only be noted in the log files.
person-mapping string Name of a person-mapping element, defined above. Identifies the person mapping that should be used.

Tasktop Sync makes sure that an incoming task matches at most one task mapping. If the task matches more than one mapping, synchronization does not proceed and is moved to the error queue.

Repository Specification

Repositories in each task mapping are defined in the repository element. There must be exactly two such elements in each task-mapping to identify participating repositories. Each repository specification has a set of required configuration settings. The configuration specified as attributes of the repository element are:

Attribute Value Type Description
id String A unique identifier for this particular repository configuration.
proxy-creation-trigger all or none Specifies when a new incoming task should have a synchronized proxy task created.
write-policy allow-writes or proxy-association-only Specifies a policy for writing data to the repository. Default is allow-writes. See below for more information.
auto-comment-user String The user that should be used by Tasktop Sync when it creates incoming notification comments for tasks on the repository (i.e. for reporting a conflict).
url URL The URL used to connect to this repository (e.g. an IBM Rational Team Concert URL might be https://rtc.example.com:9443/ccm)
query-interval-minutes non-negative decimal Specifies how many minutes to wait between consulting the changes query for this repository only. This value overrides default-query-interval-minutes or default-query-schedule in the sync-model element. You cannot specify this and a query-schedule.
query-schedule cron expression Specifies when the changes query will run, for this repository only. This value overrides default-query-interval-minutes or default-query-schedule in the sync-model element. You cannot specify this and a query-interval-minutes.
author-validation-policy no-validation, default-user-on-failure Specifies whether or not to validate the authors of comments and attachments, and what to do if validation fails. When default-user-on-failure is used the auto-comment-user will be set as the author of a comment or attachment if the mapped author is found to not exist in the target repository. When no-validation is used no checks will be made to ensure the author exists in the target repository.

The write-policy specifies whether or not Tasktop Sync is expected to write data to the repository and can be used to enforce a one-way sync of data. The default policy allow-writes performs no checking of write operations, whereas the policy proxy-association-only ensures that all other settings related to write operations are set to eliminate writes, except for setting the proxy association on each task. Specifically, it checks the following:

For proxy-creation-trigger, it is possible to customize when proxy tasks are created. If proxy-creation-trigger is “all” (the default), then all new tasks from a repository will have proxies created for them in the corresponding target repository. If proxy-creation-trigger is “none” then proxy tasks are never created. This can be useful in a scenario where you want to enforce task creation in one repository and disallow it in the other.

Important! The repository specification is position-dependent. The order that the repositories are specified in the file determines which is “repository-1” and which is “repository-2” in repository-1-dominates and repository-2-dominates; this order is also the order in which they are referenced in attribute mappings, below.

Scope Specification

Each repository can limit which tasks it can access through a scope element. The scope element contains a list of field elements with IDs and values. Each vendor’s repository defines a unique list of fields for their scope. It is recommended that you use Quick Start to create an initial mapping, which provides help with defining the scope fields and their values.

It is possible that the specification of a system’s scope may change when Tasktop Sync is updated. When this occurs Tasktop Sync’s configuration must be updated to align with the new scope definition. Until the configuration is updated Tasktop Sync will not run. Details on how to handle this scenario are found on the Tasktop Sync FAQ.

Source Specification

The repository element is connected to the actual repository through the source element. The source element can either have a set of two query elements (see Create Queries ), or a task element (see Limited Scope ). Each is described below.

Element Value Type Restrictions Description
<query name="changes" value=""/> String Must be paired with initialization The name of the query to be used for the changes query.
<query name="initialization" value=""/> String Must be paired with changes The name of the query to be used for the manual initialization query.
<task url=""/> URL Must be the only source element The URL identifying the single task to map to, described in Limited Scope.

Proxy Association Storage

Tasktop Sync needs to keep track of the association between a task and its proxy task. The association is persisted in a proxy store. There are different types of proxy stores available and each repository element must specify the store type through a proxy-storage element.

Attribute Proxy Store

The attribute store sets an attribute on each task to the URL of its proxy. The attribute can be specified through the attribute-id or attribute-label property on the proxy-storage element. In the example below, we specifying that the attribute BG_USER04 should be used to store the proxy association URL.

<repository ...>
   ...
   <proxy-storage store="attribute" attribute-id="BG_USER_04"/>
</repository>

Some connectors store some attributes as sparse (see Sparse Attributes ). If this is the case for a configured proxy attribute, the repository must declare the proxy attribute as such. This is done by adding the sparse="true" property to the proxy-storage element on a repository. In the example below, we specify that the sparse attribute task.optional.attribute should be used to store the proxy association URL. Refer to the connector-specific documentation to determine if the sparse property is required.

<repository ...>
   ...
   <proxy-storage store="attribute" attribute-id="task.optional.attribute" sparse="true"/>
</repository>
Database Proxy Store

The database store stores proxy association information in Tasktop Sync’s internal database.

<repository ...>
   ...
   <proxy-storage store="database"/>
</repository>

Important! When a repository is configured to use the database store, Tasktop Sync’s internal database becomes the only source of proxy association information and needs to be backed up regularly. Failure to do so could cause duplicate proxy tasks being created.

Task relations Proxy Store

Some connectors have a built-in way of storing links to other tasks, and for those connectors it’s possible to use the task relations store.

<repository ...>
   ...
   <proxy-storage store="task-relations"/>
</repository>

However, it’s recommended to use the other stores because they allow Tasktop Sync to store additional information together with the proxy association that cannot be stored using the built-in linking mechanism. This additional information allows Tasktop Sync to detect when a task has been copied and avoids the possibility of two tasks having links to the same proxy task. Such a situation will result in a synchronization error.

Changing Configured Proxy Store

Note that if two repositories contain a number of tasks that have already been synced, then changing configured proxy store will have the following consequences:

Property Specification

Additionally, each repository can contain a number of property elements. Only the generally applicable properties are described here. Each vendor-specific repository will likely have an additional set of required and optional properties. These properties are described in sections of Certified Connectors.

Attachment Mapping Specification

Every task-mapping element may have an optional attachment-mapping element which specifies the attachment synchronization behaviour. Every attachment-mapping element must contain two repository elements each with a required boolean attribute sync-incoming-attachments which when set to true will cause attachments to be synced into the corresponding repository.

    <attachment-mapping>
        <repository sync-incoming-attachments="true"/>
        <repository sync-incoming-attachments="false"/>
    </attachment-mapping>

Attachment file size filter configuration

Optionally each repository element may define an attachment-filesize-filter element which will enable filtering of oversized attachments. The attachment-filesize-filter elements has two required attributes filter-strategy and size-limit. filter-strategy may be one of either error or ignore, error will cause any synchronization with an oversized attachment to enter the error queue stopping all synchronization of those tasks, ignore will skip synchronizing the oversized attachment allowing the rest of the synchronization to proceed. size-limit is the maximum attachment size in bytes, any attachment which is larger than this limit will trigger the attachment filter.

    <attachment-mapping>
        <repository sync-incoming-attachments="true">
            <attachment-filesize-filter filter-strategy="error" size-limit="362659"/>
        </repository>
        <repository sync-incoming-attachments="false"/>
    </attachment-mapping>

Failed attachments filter configuration

Optionally each repository element may define a failed-attachment-filter element which will handle invalid attachments. The failed-attachment-filter elements has one required attribute: filter-strategy. filter-strategy may be one of either error or ignore, error will cause any synchronization with an invalid attachment to enter the error queue stopping all synchronization of those tasks, ignore will skip synchronizing the invalid attachment allowing the rest of the synchronization to proceed.

    <attachment-mapping>
        <repository sync-incoming-attachments="true">
            <failed-attachment-filter filter-strategy="error"/>
        </repository>
        <repository sync-incoming-attachments="false"/>
    </attachment-mapping>

Comment Mapping

Every task-mapping element may have an optional comment-mapping element which specifies the comment synchronization behaviour. Every comment-mapping element must contain two repository elements. Each repository element may have the following attributes:

Attribute Value Type Description
sync-incoming-comments true or false Specifies whether comments should be synced to this repository. Default is false.
comment-content-type Mime type string The content-type of the comments attributes in the repository (e.g. “text/html”).
add-author-header-to-comments true or false Specifies whether a line specifying the author of the comment in the source repository will be added to the beginning of all comments synced to this repository.
    <comment-mapping>
        <repository sync-incoming-comments="true" comment-content-type="text/html" add-author--header-to-comments"true" />
        <repository sync-incoming-comments="true" comment-content-type="text/html" add-author--header-to-comments"true" />
    </comment-mapping>

Comment Visibility Configuration

In addition, each repository element may define a comment-visibility-filter element, and a comment-visibility-assignment element. The comment-visibility-filter defines what comments may be synchronized out of the repository, while the comment-visibility-assignment defined the visibility of comments being synchronized into the repository. The comment visibility filter, and comment visibility assignment, are only applicable for repositories which support the notion of public and private comments. The comment-visibility-filter element has a single required attribute comment-visibility, which may be set to all, private, or public. When it is set to all, no filtering is done and both public and private comments will be synchronized out of and into this repository. When it is set to private, only private comments will be synchronized out of this repository. When it is set to public, only public comments will be synchronized out of this repository. The comment-visibility-assignment element has a single required attribute comment-visibility, which may be set to retain, private, or public. When it is set to retain, all comments synchronized into this repository will be created with the same visibility as in their originating system. When it is set to private, all comments created in this repository will be created with a visibility of private. When it is set to public, all comments created in this repository will be created with a visibility of public.

    <comment-mapping>
        <repository sync-incoming-comments="true" comment-content-type="text/html" add-author--header-to-comments"true" >
            <comment-visibility-filter comment-visibility="private" />
            <comment-visibility-filter comment-visibility="public" />
        </repository> 
        <repository sync-incoming-comments="true" comment-content-type="text/html" add-author--header-to-comments"true" />
    </comment-mapping>
    

Oversized Comment Handing

Each repository may defined an oversized-comment-handling element. This element determines how Tasktop Sync will handle comments which are too large to synchronized into the target system. The element has a single attribute filter-strategy which is required and may have one of two values, error and ignore. Configuring the element with error will cause Tasktop Sync to throw an error during comment synchronization when it detects that a comment is too large to be submitted to the target system. Configuring the element with ignore will cause Tasktop Sync to not synchronize any comments which are too large to be submitted to the target system. If no oversized-comment-handling is specified Tasktop Sync will not check the comment size and comments may be submitted to the target system which are too large which may result in errors or other unexpected behaviour. The size threshold which triggers the oversized-comment-handling is determined by the connector, and is stored in the Tasktop Sync’s repository schema.

Attribute mapping

This section describes how to configure attribute mapping from the synchronizer.xml within Tasktop Sync. The more user-friendly way to edit these attribute mappings is through the Attribute Mappings Editor. Note that some repositories are flexible enough to support task attribute mappings natively; for these repositories, you can use any combination of Tasktop Sync attribute mapping and repository-native attribute mappings. Please see the vendor-specific configuration section for your repositories to see if they support native mappings.

For each pair of task attributes to synchronize, one attribute-mapping element is specified as a child of the task-mapping element. All of the information required to synchronize values of this attribute from one repository to another and vice versa are included in this element definition. Note that the order in which you specify options in an attribute-mapping corresponds to the order of the repository clauses of the task mapping.

This section is heavily example-based; most users should be able to modify examples in this section slightly to suit their needs.

Mapping Task Attributes with the Same Name and Type

In some (fortunately) simple cases, your task repositories may have attributes with the same name and type that can be mapped directly. To specify such a mapping, use the simplest attribute mapping:

    <attribute-mapping key="Description"/> <!-- maps the "Description" attribute between your repositories -->    

Mapping Task Attributes with different names

In many cases, the attributes you want to synchronize have the same type but different names. In this case you can use the attribute-mapping element as follows:

    <attribute-mapping>
        <attribute key="BG_SUMMARY"/> <!-- The name of the attribute in your first repository (in our case, HPE QC / ALM) -->
        <attribute key="Description"/> <!-- The name of the attribute in your second repository (in our case, IBM Rational Team Concert) -->
    </attribute-mapping>  

Note that this expanded way of specifying the task attribute mapping is position-dependent: the first attribute line corresponds to task attributes in the first repository and the second line refers to task attributes in the second repository. Thus, in this example, the “BG_SUMMARY” task attribute in the qc.example.com repository is synchronized with the “Description” task attribute in rtc.example.com.

Mapping Task Attributes by ID

There are many task attributes which have the same meaning in different vendors' repositories, but which have slightly different names, e.g. “Description” and “Summary”. As a convenience, Tasktop has mapped many of the task attributes to a common ID which can be used in place of the name. For the example above, if qc.example.com’s repository’s “Description” task attribute and rtc.example.com’s “Summary” task attribute both have the ID of “task.summary.com”, then it can be written like this:

    	<attribute-mapping id="task.common.summary"/> <!-- one line for both -->

Mixing Names and IDs

It is completely possible to mix task attribute names with task attribute IDs. For example, if your company uses qc.example.com’s “Note” task attribute in the same way that rtc.example.com uses the “Description” field, you could do something like this:

		<attribute-mapping>
			<attribute key="Note"/>                    <!-- first repository -->
			<attribute id="task.common.description"/>  <!-- second repository -->
		</attribute-mapping>

Attribute Mapping Strategy

By default, task attribute mappings cause task attribute values to be copied to the destination repository. However, there are several other mapping strategies that can be employed.

<attribute-mapping strategy="copy">

This is the default strategy, and doesn’t need to be specified explicitly. In this case, the source attribute is copied to the target attribute. If the target attribute does not exist, the attribute is not synchronized.

<attribute-mapping strategy="initialize">

This strategy copies the source value to the target attribute only if the target task is new. This is useful for the purpose of initializing task attributes when the task is first synchronized. The attribute mapping is skipped for subsequent synchronizations.

<attribute-mapping strategy="ignore">

This strategy ignores this attribute. Applying this strategy at the attribute-mapping level is equivalent to not specifying an attribute mapping at all. However, it can be useful to explicitly document that not synchronizing a task attribute was deliberate.

Each of these strategies can also be applied to one end of the mapping by specifying the strategy in the attribute sub-element of attribute-mapping. For example, to map the task.common.description attribute in one direction only, from the first repository to the second repository, you could use the following mapping:

		<attribute-mapping>
			<attribute id="task.common.description" strategy="ignore"/>
			<attribute id="task.common.description"/>
		</attribute-mapping>

Additionally there is an always copy strategy that can be applied at the attribute level. This strategy always copies the source value to the target attribute whether or not a change has been detected on the attribute. This is useful if you have tasks that move between different queries or synchronization scopes during the task’s lifecycle.

This strategy can only be applied one-way. To map the task.common.summary attribute from the first repository to the second repository, you would use the following mapping:

		<attribute-mapping>
			<attribute id="task.common.summary" strategy="ignore"/>
			<attribute id="task.common.summary" strategy="always"/>
		</attribute-mapping>

Attribute Mapping Conflict Resolution

Tasktop Sync gives you the flexibility to specify a conflict resolution policy on an attribute-by-attribute basis. This overrides any setting of conflict-resolution-policy in the task mapping.

For example, with the following attribute mapping, the Note attribute in the first repository would always “win” in a conflict with the Description attribute of the second repository, regardless of the task mapping’s global conflict resolution policy.

		<attribute-mapping conflict-resolution-policy="repository-1-dominates">
			<attribute key="Note"/>         <!-- first repository -->
			<attribute key="Description"/>  <!-- second repository -->
		</attribute-mapping>

Transforming Task Attribute Values with Casters

Frequently, repositories will have slightly different formats for the same information. Casters are used to transform task attribute values from one format to another. Tasktop Sync comes with several built-in casters for common transformations.

Date-Time Caster

For repositories that represent date values differently, the date-time caster is used. For example, one repository might store date values in seconds since the 1 January 1970 epoch, while another might store dates as strings like “5:32 pm, Wed, 5 October 1963”. In order to cast the values from one format to another, there are several built-in casters which can be specified.

The following can be used to transform task attribute values from epoch date to string date/time format, and vice-versa:

		<attribute-mapping>
			<attribute key="Date" caster="date-time"> <!-- first repository's task attribute -->
				<caster-configuration>
					<source-format>epoch</source-format>
					<target-format>yyyy-MM-dd'T'HH:mm:ss.SSSZ</target-format>
				</caster-configuration>
			</attribute>
			<attribute key="DateTime" caster="date-time"> <!-- second repository's task attribute-->
				<caster-configuration>
					<source-format>yyyy-MM-dd'T'HH:mm:ss.SSSZ</source-format>
					<target-format>epoch</target-format>
				</caster-configuration>
			</attribute>
		</attribute-mapping>

Note that it is not common to need a Date-Time caster; the Tasktop connectors handle almost all date-time conversions.

Value Mapping Caster

For task attributes that can have a value from a finite set of choices, you can use the value-map caster. This is useful for task attributes that are presented using a drop-down in the repository’s native application’s GUI.

For example, one repository might have priority values of P1, P2, P3, P4, and P5, while the other repository has values of Urgent, High, Medium, Low, and WontFix. The following example causes these values to be mapped correctly:

		<attribute-mapping>
			<attribute key="Priority" caster="value-map"> <!-- first repository -->
				<caster-configuration>
					<map map-by-label="true" ignore-case="false">
						<entry key="Urgent"  value="P1"/>
						<entry key="High"    value="P2"/>
						<entry key="Medium"  value="P3"/>
						<entry key="Low"     value="P4"/>
						<entry key="WontFix" value="P5"/>
					</map>
				</caster-configuration>
			</attribute>
			<attribute key="Priority" caster="value-map"> <!-- second repository -->
				<caster-configuration>
					<map map-by-label="true" ignore-case="false">
						<entry key="P1" value="Urgent"/>
						<entry key="P2" value="High"/>
						<entry key="P3" value="Medium"/>
						<entry key="P4" value="Low"/>
						<entry key="P5" value="WontFix"/>
					</map>
				</caster-configuration>
			</attribute>
		</attribute-mapping>

Note that the key specifies the incoming value, and that is is mapped to value before being saved in the target attribute. In the above example, this means that the values P1, P2, P3, P4, P5 are associated with the Priority attribute in the first repository, and the values Urgent, High, Medium, Low, WontFix are associated with the Priority attribute in the second repository.

Also note the attributes that are present in the map element. The map-by-label="true" attribute indicates that the option labels are used, as opposed to the option identifiers. The ignore-case="false" attribute indicates that the case of the option will not be ignored when mapping. For more details on the map-by-label and ignore-case settings, see Value Mapping.

External Value Mapping Caster

For task attributes that can have a value from a finite set of choices, you can also use the external-value-map caster. This caster works the same as the Value Mapping Caster, only it allows you to define the mappings in external properties files.

The following example is for the same mapping as in Value Mapping Caster example:

		<attribute-mapping>
			<attribute key="Priority" caster="external-value-map"> <!-- first repository -->
				<caster-configuration>
					<map map-by-label="true" ignore-case="false" file="priority1.properties">
				</caster-configuration>
			</attribute>
			<attribute key="Priority" caster="external-value-map"> <!-- second repository -->
				<caster-configuration>
					<map map-by-label="true" ignore-case="false" file="priority2.properties"/>
				</caster-configuration>
			</attribute>
		</attribute-mapping>

The priority1.properties file:

Urgent=P1
High=P2
Medium=P3
Low=P4
WontFix=P5

The priority2.properties file:

P1=Urgent
P2=High
P3=Medium
P4=Low
P5=WontFix

Note that the properties files are located as a reference of the synchronizer.xml file. So in this example, they reside in the same directory.

Also note the attributes that are present in the map element. The map-by-label="true" attribute indicates that the option labels are used, as opposed to the option identifiers. The ignore-case="false" attribute indicates that the case of the option will not be ignored when mapping. For more details on the map-by-label and ignore-case settings, see Value Mapping.

Text

Many repositories support rich text, especially in the description attribute. Different repositories store the representation of rich text in different formats, so to provide high-fidelity rendering of that text after synchronization, Tasktop Sync provides text casters, e.g.:

		<attribute-mapping>
				<attribute id="task.common.description" caster="confluence-to-html"/>
				<attribute id="task.common.description" caster="html-to-confluence"/>
		</attribute-mapping>

Examples of text casters:

If one of the repositories uses plain text, then we recommend using the textile caster. Textile is a wiki markup language that is easily readable as plain text. If both repositories use HTML to represent rich text, then we recommend using the html-copy caster. The html-copy caster handles differences in HTML generated by repositories from different vendors.

Literal Values

Occasionally it is useful to have a task attribute set to an arbitrary value. You can do this by specifying a literal value. For example, if tasks from one repository should always have the task attribute task_type set to “Defect”, and the other repository should have the TaskType attribute set to “Bug”, the task attribute mapping could be specified as follows:

		<attribute-mapping>
			<attribute key="task_type" caster="Defect"/> <!-- first repository -->
			<attribute key="TaskType" caster="Bug"/>     <!-- second repository -->
		</attribute-mapping>

If only the second repository should have a literal value, you can use an initialization strategy as follows:

		<attribute-mapping>
			<attribute id="task_type"/>
			<attribute id="TaskType" strategy="initialize" initial-value="Bug"/>
		</attribute-mapping>

as before, this will cause the attribute to be initialized with the literal "Bug"

Task Link To Task Link Caster

When synchronizing tasks with relationships, you can maintain the relationships in both repositories using the task-link-to-task-link caster. For example, if a defect is created with references to a test case, and you are synchronizing both the test cases and defects, you can keep their relationships in both repositories. Each task will expose attributes representing these relationships. Create a mapping between each relationship attribute and use the task-link-to-task-link caster to maintain the relationships in the two repositories.

If it is known that the relationship references tasks that will not be synchronized by Tasktop Sync, or that there are restrictions on accepted relationship types, then the caster can be configured to filter references to undesired tasks by setting filter-links to true. When enabled, the caster will ignore any references to tasks that will not be synchronized by the Tasktop Sync instance, or references to tasks that are not of the desired type.

         <attribute-mapping>
            <attribute caster="task-link-to-task-link" id="linked-entities">
               <caster-configuration>
                  <filter-links>true</filter-links>
                </caster-configuration>
            </attribute>
            <attribute caster="task-link-to-task-link" id="Defects">
               <caster-configuration>
                  <filter-links>true</filter-links>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This caster will only work between two attributes of type “taskDependency”.

Task Link To Task Link Group Caster

When synchronizing tasks with multiple relationship attributes into a task with a single relationship attribute, you can still maintain the relationships in both repositories using the task-link-to-task-link-group caster, along with the task-link-to-task-link caster. For example, if a defect is created with both “clones” and “blocks” relationships, and you are synchronizing to a target repository defect that supports only “linked-entities” relationships, you can keep combine all the relationships from “clones” and “blocks” into the “linked-entities” attribute.

This caster can only exist as a compliment to an existing mapping using a task-link-to-task-link caster. You first create the task-link-to-task-link mapping between first of the many attributes to your single target attribute (see Task Link To Task Link Caster ). You then define a unidirectional mapping from your subsequent of the many attributes to the same single target attribute, including the configuration of the group-default-attribute-id containing the first of the many attributes. For more details, see Task Link to Task Link Group.

        <attribute-mapping>
            <attribute caster="task-link-to-task-link" id="clones"/>
            <attribute caster="task-link-to-task-link" id="linked-entities"/>
        </attribute-mapping>
        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-task-link-group" id="blocks"/>
            <attribute caster="task-link-to-task-link-group" id="linked-entities">
                <caster-configuration>
                    <group-default-attribute-id>clones</group-default-attribute-id>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This caster will only work as a unidirectional mapping between two attributes of type “taskDependency”. The caster-configuration must exist on the target attribute of the unidirectional mapping, and its group-default-attribute-id must contain a valid source attribute id of an existing mapping that uses the task-link-to-task-link caster.

Task Link To Web Link Caster

When synchronizing a task with internal references to other tasks, you may not want to synchronize the referenced tasks, but instead simply synchronize references to those tasks as web URLs. For example, if a defect is created with references to one or more test cases, you may want to synchronize the defect but not the test cases. Instead, you can synchronize the referenced test cases as web URLs that when clicked will open the test case in the source repository.

        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-web-link" id="Test"/>
            <attribute caster="task-link-to-web-link" id="web-links">
                <caster-configuration>
                    <target-format>%task.common.summary (%ID) - %task.common.status (%DATE)</target-format>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This cast is a unidirectional cast from a task link to a web link. Therefore, the source attribute must have strategy="ignore" and must be of type “taskDependency”. The target attribute must be of type “externalLink”.

The target-format is used to format the label of the web link. The format can contain any clear text and the following wild cards:

Wild Card Description
%URL Will be replaced by a web URL representing the referenced task.
%ID Will be replaced by the task ID of the referenced task.
%KEY Will be replaced by the task key of the referenced task.
%DATE Will be replaced by the system date of the Tasktop Sync server at synchronization time.
%TIME Will be replaced by the system time of the Tasktop Sync server in 24-hour format at synchronization time.

Additionally any attributes on the linked task can be referenced by common key or attribute id. Please refer to the schema for a list of available attribute IDs.

For example, using the format %KEY: %summary (%task.common.status) as of %DATE will produce:

Task-1234: Deliver Presents (In Progress) as of 2015-12-25

When the linked task has a summary of “Deliver Presents” and a status of “In Progress”.

It is important to note that when task attributes are present in the target link label format, Tasktop Sync will retrieved the linked tasks during synchronization to get the information needed to create the link label. It is recommended that the synchronizations strategy be set to always for mappings which use attribute IDs in the link label to keep the link labels as up to date as possible as the linked tasks change.

If no format is specified, the link label will not be filled out.

Task Link To Web Link Group Caster

When synchronizing tasks with multiple relationship attributes into a target task’s single URL attribute, use the task-link-to-web-link-group caster, along with the task-link-to-web-link caster. For example, if a defect is created with both “clones” and “blocks” relationships, and you are synchronizing to a target repository defect that supports only “url-attachments” relationships, you can keep combine all the relationships from “clones” and “blocks” into the “url-attachments” attribute.

This caster can only exist as a compliment to an existing mapping using a task-link-to-web-link caster. You first create the task-link-to-web-link mapping between first of the many attributes to your single target attribute (see Task Link To Web Link Caster ). You then define a unidirectional mapping from your subsequent of the many attributes to the same single target attribute, including the configuration of the group-default-attribute-id containing the first of the many attributes. For more details, see Task Link to Web Link Group.

        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-web-link" id="clones"/>
            <attribute caster="task-link-to-web-link" id="url-attachments"/>
        </attribute-mapping>
        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-web-link-group" id="blocks"/>
            <attribute caster="task-link-to-web-link-group" id="url-attachments">
                <caster-configuration>
                    <group-default-attribute-id>clones</group-default-attribute-id>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This cast is a unidirectional cast from a task link to a web link. The caster-configuration must exist on the target attribute of the unidirectional mapping, and its group-default-attribute-id must contain a valid source attribute id of an existing mapping that uses the task-link-to-web-link caster.

Task Link To String Caster

If you want to use the Task Link to Web Link caster, but your target repository does not support web URL attachments, you can format the references into text attributes using the task-link-to-string caster.

        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-string" id="Parents"/>
            <attribute caster="task-link-to-string" id="LongText">
                <caster-configuration>
                    <target-format>%URL%,</target-format>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This cast is a unidirectional cast from a task link. Therefore, the source attribute must have strategy="ignore", and must be of type “taskDependency”. The target attribute must support text context, and it is highly recommended that the attribute support strings of at least 1024 characters.

The target-format is used to format each task URL. Multiple task URLs will each be formatted using target-format and then sequentially concatenated. The format can contain any clear text and the following two wild cards:

Wild Card Description
%URL Will be replaced by a web URL representing the referenced task.
%, Places a comma in all formats except the last one. Useful for separating a list of task URLs.
%EOL Inserts a line break if the target attribute supports them. Useful for formatting a list of task URLs.

For example, using the format Test: %URL%, on the two task URLs “http://www.repository.com/1” and “http://www.repository.com/2”, the resulting text attribute will be:

Test: http://www.repository.com/1, Test: http://http://www.repository.com/2

If no format is specified, a default of %URL%, is used, which will list the web URLs separated by commas.

Task Link To OSLC Link Caster

When synchronizing a task with internal references to other tasks, you may not want to synchronize the referenced tasks, but instead simply synchronize references to those tasks as OSLC Links. For example, if a defect is created with references to one or more test cases, you may want to synchronize the defect but not the test cases. Instead, you can synchronize the referenced test cases as OSLC Links which when presented in the target system provide information about the linked tasks using Tasktop Sync’s OSLC Adapter.

        <attribute-mapping>
            <attribute strategy="ignore" caster="task-link-to-oslc-link" id="Test"/>
            <attribute caster="task-link-to-oslc-link" id="web-links"/>
        </attribute-mapping>

This cast is a unidirectional cast from a task link to an OSLC link. Therefore, the source attribute must have strategy="ignore" and must be of type “taskDependency”. The target attribute must be of type “externalLink”. For these links to provide information about the linked tasks Tasktop Sync’s OSLC Adapter must be configured and running, the target system must support OSLC linking and be configured to accept OSLC links from Tasktop Sync, and the link target must be exposed via Tasktop Sync’s OSLC Adapter. For further information on OSLC linking see the section on Task Linking Configuration.

Value to Task Link Caster

To synchronize a data enumeration with an internal task reference, use the value-to-task-link caster.

        <attribute-mapping>
            <attribute id="values" caster="value-to-task-link">
                <caster-configuration>
                    <query>Categories</query>
                    <map>
                        <entry key="13312" value="10700"/>
                    </map>
                </caster-configuration>
            </attribute>
            <attribute id="tasks" caster="value-to-task-link">
                <caster-configuration>
                    <query>Categories</query>
                    <map>
                        <entry key="10700" value="13312"/>
                    </map>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

Note that this caster will only work between an attribute of type “Single Select” or “Multi Select”, and an attribute of type “Task Dependency”.

Web Link To Web Link Caster

To synchronize attached web URLs between tasks, use the web-link-to-web-link caster.

        <attribute-mapping>
            <attribute caster="web-link-to-web-link" id="related-links"/>
            <attribute caster="web-link-to-web-link" id="web-links"/>
        </attribute-mapping>

The caster will only work between two attributes of type “externalLink”.

Web Link To String Caster

If you want to use the Web Link to Web Link caster, but your target repository does not support web URL attachments, you can format the references into text attributes using the web-link-to-string caster.

        <attribute-mapping>
            <attribute strategy="ignore" caster="web-link-to-string" id="Parents"/>
            <attribute caster="web-link-to-string" id="LongText">
                <caster-configuration>
                    <target-format>%URL%,</target-format>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

This cast is a unidirectional cast from a web link. Therefore, the source attribute must have strategy="ignore", and must be of type “externalLink”. The target attribute must support text context, and it is highly recommended that the attribute support strings of at least 1024 characters.

The target-format is used to format each web URL. Multiple web URLs will each be formatted using target-format and then sequentially concatenated. The format can contain any clear text and the following two wild cards:

Wild Card Description
%URL Will be replaced by then web URL from the source.
%LABEL Will be replaced by the URL’s label (or name), if it exists.
%, Places a comma in all formats except the last one. Useful for separating a list of web URLs.
%EOL Inserts a line break if the target attribute supports them. Useful for formatting a list of web URLs.

For example, using the format Test: %URL%, on the two web URLs “http://www.repository.com/1” and “http://www.repository.com/2”, the resulting text attribute will be:

Test: http://www.repository.com/1, Test: http://http://www.repository.com/2

If no format is specified, a default of %URL%, is used, which will list the web URLs separated by commas.

Location To Web Link Caster

If you need to have the URL of the source task as a web link on the target task, use the location-to-web-link caster. This caster will create a web link, which points to the source task, on the target task.

        <attribute-mapping>
            <attribute strategy="copy" id="web-links" caster="location-to-web-link">
                <caster-configuration>
                    <target-format>%KEY - %SUMMARY</target-format>
                </caster-configuration>
            </attribute>
            <attribute strategy="ignore" id="location" caster="location-to-web-link"/>
        </attribute-mapping>

This cast is a unidirectional cast from a location. Therefore, the source attribute must have strategy="ignore", and must be of type “url”. The target attribute must be of type “externalLink”.

The target-format is used to format the label of the web link. The format can contain any clear text and the following wild cards:

Wild Card Description
%URL Will be replaced by the source task’s URL.
%SUMMARY Will be replaced by the source task’s summary.
%KEY Will be replaced by the source task’s key.

For example, using the format %KEY - %SUMMARY (%URL) on a task with URL “http://www.repository.com/1”, summary “Task 1” and key “T-1” will result in a web link with the following label:

T-1 - Task 1 (http://www.repository.com/1)

If no format is specified, a default of %KEY - %SUMMARY is used.

Note: If the summary is used in the label, it is recommended that the strategy be set to “always” to ensure the label of web link stays up to date. For more details, see the Attribute Mapping Strategy section.

Status Transition Caster

If you need to synchronize status into a repository with a workflow use the status-transition caster. With this caster you can synchronize status by executing transitions to move the target task between statuses following the workflow defined in the remote repository.

		<attribute-mapping>
			<attribute caster="status-transition" id="task.common.status" strategy="ignore" />
			<attribute caster="status-transition" id="task.common.status">
				<caster-configuration>
					<map>
						<entry key="status.new" value="1-New" />
						<entry key="status.assigned" value="2-Active" />
						<entry key="status.resolved" value="3-Closed" />
						<entry key="status.reopened" value="4-Reopened" />
					</map>
					<graph>
						<edge from-option-id="1-New" to-option-id="2-Active" operation-id="task.common.operation-accept"/>
						<edge from-option-id="1-New" to-option-id="3-Closed" operation-id="task.common.operation-close"/>
						<edge from-option-id="2-Active" to-option-id="3-Closed" operation-id="task.common.operation-resolve"/>
						<edge from-option-id="3-Closed" to-option-id="4-Reopened" operation-id="task.common.operation-reopen"/>
						<edge from-option-id="4-Reopened" to-option-id="2-Active" operation-id="task.common.operation-accept"/>
						<edge from-option-id="4-Reopened" to-option-id="3-Closed" operation-id="task.common.operation-resolve"/>
					</graph>
					<creation-value>1-New</creation-value>
				</caster-configuration>
			</attribute>
		</attribute-mapping> 

To configure this caster both a value mapping and a transition graph must be specified. The value mapping is used to translate the status of the source task into a desired status on the target task. The transition graph is used to determine the sequence of transitions which must be executed to attain the desired status.

For the synchronization to proceed a path must exist in the graph between the current and desired statuses. If no such path can be found then the synchronization will fail. For instance in the above example no path exists from 3-Closed to 1-New. This means that if the target task had the 3-Closed status, and the source task’s status was changed to status.new, the synchronization would fail as no sequence of transitions will leave the target task with the 1-New status.

All edges defined in the graph are unidirectional. If transitions exist between statuses in both directions then one edge must be configured for each direction. This has been done in the above example configuration where the transition task.common.operation-resolve exists from 4-Reopened to 3-Closed while the transition task.common.operation-reopen exists from 3-Closed to 4-Reopened.

If more than one transition is required to attain the desired status Sync will execute them one at a time in order to reach the desired status. In the example above if the target task has the 1-New status, and the source task has the status.reopened status then the following transitions will be executed: task.common.operation-close, task.common.operation-reopen. This will change the status of the target task first from 1-New to 3-Closed, then from 3-Closed to 4-Reopened. The caster will always choose the path with the fewest number of transitions, this is why the target task never attained 2-Active status as this would require three transitions instead of two.

For repositories that require an initial status on new task creation, use creation-value to assign this status. The status should represent the starting status on the target repository’s workflow.

This caster is a unidirectional caster only. Therefore, the source attribute must have strategy="ignore". If you need to synchronize workflows in both directions create two attribute mappings with this caster, one in each direction. This is done to facilitate mappings where status transitions are required in one direction, but a different caster may be used in the reverse direction.

This caster is only supported when mapping the status field, and only transitions affecting status are currently supported.

Caster Customization

Casters can also be written in an external scripting language such as Groovy or JavaScript; we recommend Groovy. Here is an example:

<caster name="toUpper" language="groovy"><![CDATA[
	
	def cast(value) {
		value.toUpperCase()
	}
	
	]]></caster>
	

The above caster must be declared after any <task-mapping> declarations. You can refer to this caster in an attribute mapping like this:

	<attribute-mapping>
	   <attribute id="Summary" caster="toUpper"/>
		<attribute id="Summary"/>
	</attribute-mapping>
		

Casters can also be written in external files and included via the script attribute of the caster element:

	<caster 
		name="toUpper" 
		language="groovy"
		script="scripts/statusHandler.groovy"/>


The path to the Groovy script is resolved relative to the Tasktop Sync working directory. The above caster would look for a directory called scripts alongside the synchronizer.xml file, and it would look for a file called statusHandler.groovy in that scripts directory.

For more details on scripting in Tasktop Sync, see Advanced Scripting

Using Person Mappings

For repository attributes representing people, you can use a person caster if a person mapping has been specified in the enclosing task-mapping element:

	<attribute-mapping>
		<attribute id="AssignedTo" caster="person"/>
		<attribute id="AssignedTo" caster="person"/>
	</attribute-mapping>
		

The person caster uses the person mapping named in the enclosing task-mapping element to cast its values.

Advanced Concepts

One-Way Mappings

Tasktop Sync’s attribute-mapping can be used to support several different configurations of one-way synchronization of objects. Below are several examples using attribute mapping strategies to realize a one-way mapping.

The first example is a generic one-way mapping of the status attribute from the first repository into the second repository:

		<attribute-mapping>
			<attribute id="task.common.status" strategy="ignore"/>
			<attribute id="task.common.status"/>
		</attribute-mapping>

This causes a status attribute change in the first repository to be synchronized to the status attribute in the second repository, but not vice versa.

To populate the status attribute of the task in the second repository only the first time it is created, you can use the initialization strategy as follows:

		<attribute-mapping>
			<attribute id="task.common.status"/>
			<attribute id="task.common.status" strategy="initialize"/>
		</attribute-mapping>

This will cause the attribute to be initialized with a copy from the first repository, with subsequent changes being ignored.

If you want to synchronize an attribute one way with a literal value, so that no source attribute is specified, then you can leave off the id and key properties on one of the attributes as long as the strategy for that attribute is set to ignore. For example:

		<attribute-mapping>
			<attribute strategy="ignore" />
			<attribute id="BG_SEVERITY" caster="'2-Medium'" strategy="initialize"/>
		</attribute-mapping>

This will cause the BG_SEVERITY attribute to be initialized to the literal value “2-Medium”.

Synchronizing Subsets of Queried Incoming Tasks

Sometimes you might want to only synchronize a subset of the tasks found in your specified queries. For example, you might only be interested in synchronizing the Cobra project defects — not anything about the Mongoose project, not anything about the Cobra test cases. You can restrict which subset of entries in the repositories to synchronize by using the nary element in conjunction with condition elements, both inside the repository element.

For example, to specify that only tasks which have a value of "Requirement" or "TestCase" in the Type task attribute will be synchronized in our example HPE QC / ALM repository we could rewrite that repository element as follows:

     <repository proxy-creation-trigger="all"
                 auto-comment-user="developer1"
                 id="com.tasktop.sync.QC"
                 url="http://qc.example.com:8080/qcbin;SYNCHRONIZER;ProjectArea">
        <property name="defaultCommentUser" value="developer1"/>
        <scope>
            <field id="itemType" value="BUG"/>
        </scope>
        <source>
            <query name="initialization" value="Tasktop Sync - HPE QC / ALM - All Defects"/>
            <query name="changes" value="Tasktop Sync - HPE QC / ALM - Recently Modified Defects"/>
        </source>
        <proxy-storage store="attribute" attribute-id="BG_USER_01"/>
        <nary operator="or">
             <condition attribute-key="type" operator="=" value="Requirement"/>
             <condition attribute-key="type" operator="=" value="TestCase"/>
        </nary>
     </repository>

The nary element can use one of three operators: or, and, or !. The or operator evaluates to true when at least one of the conditions within it evaluates to true. The and operator evaluates to true when each and every condition within it evaluates to true. The ! operator inverts the truth value of the contained condition (i.e. true becomes false and false becomes true). A nary element may also be nested within another nary as one of its conditions.

The condition element must use one of attribute-id, attribute-key, or attribute-label as the identifier for the attribute to filter by. The value for the operator to evaluate can be set using value or with value-label to find the corresponding value option identified through label.

The operators available for the condition element are summarized in the following table:

Operator Type of Attribute Description
= Single-value True when the value provided equals the value of the specified attribute.
!= Single-value True when the value provided does not equal the value of the specified attribute.
null Single-value True when the value of the specified attribute is empty, or the specified attribute doesn’t exist.
equals_ignore_case Single-value True when the value provided equals the value of the specified attribute, ignoring case.
contains Single-value True when the value of the specified attribute contains the value provided. For example, “abc” contains “bc” but not “ac”.
contains-any Multi-value True when at least one of the values in the specified multi-value attribute contains the value provided.
contains-all Multi-value True when each and every value in the the specified multi-value attribute contains the value provided.
matches Single-value True when the value of the specified attribute matches the given regular expression.
matches-any Multi-value True when at least one of the values in the specified multi-value attribute matches the given regular expression.
matches-all Multi-value True when each and every value in the specified multi-value attribute matches the given regular expression.
Scripted Attribute Handlers

If you need even more flexibility than the normal attribute mapping, you can write a scripted attribute handler. This is particularly useful if there is not a one-to-one mapping between some of the task attributes in the two repositories. For example, if one repository has a single “mailing address” task attribute but the other has three separate task attributes for “street”, “city”, and “country”, you could write an attribute handler to synchronize those task attributes.

The scripting languages that are available to you include JavaScript and Groovy; if you have other scripting languages available on your system, those might be available to you as well. Between JavaScript and Groovy, we recommend that you use Groovy.

<attribute-handler language="groovy" id="task.common.status">
    <script><![CDATA[
        
def map(context,sourceAttribute,targetTask) {
    if (targetTask.root.attributes['bug_status']?.value != sourceAttribute.value || 
        (sourceAttribute.value == 'RESOLVED' && targetTask.root.attributes['resolution']?.value != sourceAttribute.parent.attributes['resolution']?.value)) {
        if (targetTask.isNew()) {
            // 
        } else {
            def operation = targetTask.root.attributes['task.common.operation']
            switch (sourceAttribute.value) {
            case 'ASSIGNED':
                operation.value = 'accept';
                break;
            case 'VERIFIED':
                operation.value = 'verify';
                break;
            case 'RESOLVED':
                operation.value = 'resolve';
                targetTask.root.attributes['resolution'].value = 
                    sourceAttribute.parent.attributes['resolution']?.value;
                break;
            case 'CLOSED':
                operation.value = 'close';
                targetTask.root.attributes['resolution'].value = 
                    sourceAttribute.parent.attributes['resolution']?.value;
                break;
            case 'REOPENED':
                operation.value = 'reopen';
                break;
            case 'NEW':
                operation.value = 'marknew';
                break;
            case 'DUPLICATE':
                operation.value = 'resolve';
                targetTask.root.attributes['resolution'].value = 
                    sourceAttribute.parent.attributes['resolution']?.value;
                break;
            }
            if (targetTask.root.attributes['task.common.operation-'+operation.value] == null) {
                targetTask.root.createAttribute('task.common.operation-'+operation.value)
            }
        }
    }
}
        
    ]]></script>
</attribute-handler>
		

Scripted attribute handlers can also be written in external files and included via the script attribute of the attribute-handler element:

	<attribute-handler 
		language="groovy" 
		id="task.common.status" 
		script="scripts/statusHandler.groovy"/>
		

The location of the Groovy script specified in the scripts attribute is resolved relative to the location of the synchronizer.xml file. In the above attribute handler, Tasktop Sync will look for a file called statusHandler.groovy in a directory called scripts which is located in the same directory as the synchronizer.xml file.

Note: Tasktop Sync will log warnings for required attributes which are not mapped. If such attributes are mapped using a scripted attribute handler, the attributes must specified in the attribute handler’s configuration in order for the warnings to be removed. Attributes may be identified by id or key.

	<attribute-handler 
		language="groovy" 
		id="task.common.status" 
		script="scripts/statusHandler.groovy">
		<target-attributes-handled>
			<attribute id="status"/>
			<attribute key="task.common.summary"/>
		</target-attributes-handled>
	</attribute-handler>

For more details on scripting in Tasktop Sync, see Advanced Scripting

Multiple Submissions per Synchronization

One use case for attribute handlers is to perform more complicated computations during a synchronization than just taking an input from the source attribute and storing an output in the proxy attribute. Many of these computations are related to workflow restrictions in the proxy repository which restrict the values an attribute can be changed to based on its current value. For example, in some repositories, new tasks must have the “New” status. However, if you are synchronizing tasks from an existing repository, many of the source tasks may already be closed; the target repository will then prevent proxy tasks from being created because it won’t allow new tasks to be created in the “closed” state.

To address this issue, Tasktop Sync allows scripted attribute handlers to request that the scripts be applied again once all of the current changes have been submitted to the repositories. This allows a script to step through workflow restrictions and submit each step along the way, effectively allowing a closed task from one repository to create a new proxy task in the closed state in the target repository. Here is an example Groovy script which causes a target “counter” attribute to be incremented by one each time the script is run, stopping at 10. This script will cause 10 submissions to the target repository, one for each value from 1 to 10.

<attribute-handler language="groovy" id="counter">
    <script><![CDATA[
        def map(context,sourceAttribute,targetTask) {
            if (targetTask.root.attributes['counter'] == null) {
                targetTask.root.createAttribute('counter')
                targetTask.root.attributes['counter'].setValue('1')
                context.setSyncAgain(true)
            } else if (targetTask.root.attributes['counter'].value.toInteger() < 10) {
                targetTask.root.attributes['counter'].setValue((targetTask.root.attributes['counter'].value.toInteger() + 1).toString())
                context.setSyncAgain(true)
            } 
    } ]]></script>
</attribute-handler>

There is one important feature to notice about this script that is crucial in how it works. The script must call context.setSyncAgain(true) to request that another round of processing occur after the current one. This also causes the script mapping to be applied even if the source attribute hasn’t changed since the last synchronization. Otherwise, each round of processing after the first would not apply the script mapping since the source attribute hasn’t changed since the last round.

Note that there is a hard limit on the number of iterations per complete synchronization that Tasktop Sync will allow, to prevent erroneous scripts from submitting indefinitely to any task repository. This limits the number of rounds of synchronization to 15.

Ignoring Automated Changes

When performing a synchronization involving multiple submissions it is usually important that the synchronization is not interrupted by other changes. This is especially true when submitting to attributes whose change may alter other attributes. A common case for this is when synchronizing status attributes with a workflow, the workflow constraints may require that multiple submissions are performed, for example to move from ‘Open’ to ‘Reopened’ a task may need to proceed through the following states ‘Open’, ‘In Progress’, ‘Closed’, and ‘Reopened’. During such a procession it is important that changes in the proxy repository do not cause any interruption. This is especially important when the attribute handler does not submit to the status attribute directly but instead triggers a transition which may alter multiple attributes on the task being submitted to.

<attribute-handler language="groovy" id="status">
    <script><![CDATA[
            def map(context,sourceAttribute,targetTask) {
                    def transitions = computePath(sourceAttribute, targetTask)
                    if (transitions.length == 1) {
                        targetTask.root.attributes['status-transition'] = transitions[0]
                    } else if (transitions.length > 1) {
                        targetTask.root.attributes['status-transition'] = transitions[0]
                        context.setSyncAgain(true)
                        context.ignoreTargetAttribute('status')
                    }
                }
    } ]]></script>
</attribute-handler>

In the above example the script computes the transitions it must perform and then performs the first transition as well as requesting a subsequent synchronization to perform the rest of the transitions. However this transition will change the value of the proxy task’s status attribute which will cause Sync to attempt to synchronize this change back to the source. To avoid this interruption of the multiple synchronization submissions the script instructs Sync to ignore changes to the target attribute ‘status’ during the reverse synchronization. All other attributes will be considered during the reverse synchronization and any changes to the ‘status’ attribute will be considered during any subsequent synchronizations.

Sparse Attributes

Occasionally connectors store an attribute as sparse meaning that such attribute is not present on a task when there is no existing value for the attribute. Tasktop Sync has a mechanism for properly detecting erasure of the value of a sparse task attribute. The mechanism is enabled through using the sparse property of an attribute element of an attribute-mapping.

<attribute-mapping strategy="copy">
	<attribute id="BG_USER_04" />
	<attribute id="task.sparse.attribute" sparse="true" />
</attribute-mapping>

In most cases, using the sparse property will not be required and should not be used. Please refer to the connector-specific documentation to determine if the sparse property is required.

Operation Attribute Mappings

When using the Status Transition Caster certain transitions may require extra information to execute. This information can be provided by using operation attribute mappings. One common scenario where this may be necessary is when executing a status transition which resolves or closes a defect. These status transitions often require a resolution to be specified.

An operation attribute mapping provides this information to the transition by mapping attributes from source task attributes to target operation attributes.

<operation-attribute-mapping>
	<attribute id="task.common.resolution" />
	<operation-attribute id="task.common.resolution" operation-id="task.common.operation-resolve" />
</operation-attribute-mapping>

The above example maps the source task’s resolution directly to the resolution attribute of the operation task.common.operation-resolve. The operation-id must be specified so that the mapping is applied to the correct operation. This means that if there are multiple status transitions which require a resolution attribute to be set a separate operation attribute mapping must be configured for each.

Operation attribute mappings are always one way mappings from the task attribute to the operation attribute. Under no circumstances will synchronizations take place from the operation attribute into the task attribute. As such the attribute element in the operation-attribute-mapping element cannot have any strategy set on it other than ignore, if no strategy is set ignore is used by default. Operation attribute mappings may use casters in the same way that task attribute mappings can, the only exclusion is that group casters are not supported.

Jobs

Scheduled jobs can be configured to run using CRON expressions. The following job types can be scheduled:

Type Description Required
StatisticsEmail Send statistics emails that show detailed information about how much activity there has been in the last 24 hours. True
MetricsEmail Sends emails with synchronization activity over the last month. True
RepositoryConfigurationRefresh Periodically refreshes the repository configuration of the specified repository. False
RefreshSchema Periodically refreshes every repository schema corresponding to the specified repository. False
CheckForChanges Periodically downloads all tasks within the specified query and checks for changes. This can be used to identify changes which are not reported by the repository. False
ErrorNotification Send error notification emails which show detailed information about errors which have occurred during synchronization. False
DiskSpaceWarning Periodically checks the free space on the disk containing the Tasktop Sync workspace to see if it has fallen below a configurable threshold. If it has fallen below the threshold, the job will send a warning email and optionally stop Tasktop Sync. False

Each job has the following attributes:

Attribute Description Sample Value
name A unique name for the job. MyJob
type One of the types defined in the table above. MetricsEmail
schedule A CRON expression defining when the job should run. 0 0 0 * * ?

Each job can also have custom parameters, defined as child elements with the following attributes:

Attribute Description Sample Value
name A expected parameter name. repositoryUrl
value The value to use for the parameter. http://repo.com/

For example:

<job name="StatisticsEmail" type="StatisticsEmail" schedule="0 0 0 * * ?"/>
<job name="Sample" type="SampleType" schedule="0 0 0 1 * ?">
    <job-parameter name="sampleParam" value="1"/>
</job>

Refresh Repository Configuration Job

The RepositoryConfigurationRefresh job requires the following parameter:

Name Value
repository-url The url of the repository

For example:

<job name="RepositoryConfigurationRefresh" type="RepositoryConfigurationRefresh" schedule="0 0 0 * * ?">
    <job-parameter name="repository-url" value="http://repo.com/" />
</job>

Refresh Schema Job

The RefreshSchema job requires the following two parameters:

Name Value
repository-url The url of the repository
refresh-type local or remote

For example:

<job name="RefreshSchema" type="RefreshSchema" schedule="0 0 0 * * ?">
    <job-parameter name="repository-url" value="http://repo.com/" />
    <job-parameter name="refresh-type" value="local" />
</job>

Check For Changes Job

The CheckForChanges job requires the following two parameters:

Name Value
repository-url The url of the repository
query-name The name of the query

For example:

<job name="CheckForChanges" type="CheckForChanges" schedule="0 0 0 * * ?">
    <job-parameter name="repository-url" value="http://repo.com/"/>
    <job-parameter name="query-name" value="defects"/>
</job>

Disk Space Warning Job

The DiskSpaceWarning job requires the following two parameters:

Name Value
threshold-in-MB The minimum amount of remaining disk space in MB before the warning email will be sent.
stop-sync-if-below-threshold Whether this job should stop Tasktop Sync if the remaining disk space is below the threshold

For example:

<job name="DiskSpaceWarning" type="DiskSpaceWarning" schedule="0 0 0 * * ?">
        <job-parameter name="threshold-in-MB" value="2000"/>
        <job-parameter name="stop-sync-if-below-threshold" value="false"/>
    </job>

Error Notification Job

The Error Notification Job will send an email containing the configured error notification at the provided schedule. For more information on error notifications, see the Notifications section.

Notifications

This section describes how to configure the email notifications from the synchronizer.xml within Tasktop Sync. The more user friendly way to configure this is detailed in the Notifications section.

There are three types of notifications which may be sent, each corresponding to a xml element:

Name Contents
error-notification Any errors which may have occurred when Tasktop Sync is running
statistics-notification Statistics on the Tasktop Sync instance, such as uptime and average processing time
metrics-notificaion Metrics on the number of synchronizations performed in the last three months

Each notification element may contain any number of email elements, which each have a single address attribute. For example, the following is the configuration of the statistics notification being sent to the email addresses “recipient1@example.com” and “recipient2@example.com”.

<statistics-notification>
    <email address="recipient1@example.com" />
    <email address="recipient2@example.com" />
</statistics-notification> 

Error Notification

The Error notification has additional configuration for the contents of the notification:

Name Description
include-synchronization-errors Errors that occurred during synchronization, which may include conditions such as: a proxy task has been deleted, a repository is offline, or a task submission has failed
include-synchronization-conflicts Conflicts that occurred during synchronization which resulted in the changed attribute not being synchronized
include-query-errors Errors that resulted from queries being run by Tasktop Sync

For example, the following is the configuration of the error notification configured to only receive synchronization errors and synchronization conflicts, being sent to the email addresses “recipient1@example.com” and “recipient2@example.com”.

<error-notification include-synchronization-errors="true" include-synchronization-conflicts="true" include-query-errors="false">
    <email address="recipient1@example.com" />
    <email address="recipient2@example.com" />
</error-notification> 

Person Mapping Files

You can map people in one repository to people in the other repository via person mapping files. These XML files have a similar structure to the task-mapping element in the synchronizer.xml file. Here is an example person mapping file:

    <?xml version="1.0" encoding="UTF-8"?>
    <person-mappings xmlns="http://tasktop.com/xml/ns/sync/person-mapping-model">
    
        <repository
            url="http://qc.example.com"
            default-person-id="Admin"
            mapping-ignore-case="true"/>
        <repository
            url="http://rtc.example.com"
            default-person-id="administrator"/>
    
        <!-- 
        This mapping is for optional attributes. If an optional attribute has no value set 
        on it then its synced attribute will also have no value. If the desired behaviour 
        is to map an empty value to the default user then remove this mapping. 
        -->
        <person-mapping>
        <person id="" />
        <person id="" />
        </person-mapping>

        <person-mapping>
            <person id="dev1"/>
            <person id="dev1@example.com"/>
        </person-mapping>
        <person-mapping>
            <person id="dev2"/>
            <person id="dev2@example.com"/>
        </person-mapping>
    </person-mappings>

In the above example, the first mapping maps the empty value "" in the first repository to another empty value "" in the second repository. As stated in the comments, this mapping is optional, and can be removed to map blank values to the default-person-id.

dev1 in the repository at http://qc.example.com is mapped to dev1@example.com in the repository at http://rtc.example.com. Similarly, dev2 in http://qc.example.com is mapped to dev2@example.com in http://rtc.example.com. The repository URLs in this file must correspond to the repository URLs used in each task-mapping element in the synchronizer.xml file that uses the mapping.

The default-person-id of http://qc.example.com is Admin, meaning that any items syncing from http://rtc.example.com to http://qc.example.com that contain a person identity not included in this mapping will be mapped to Admin on http://qc.example.com. For items going from http://qc.example.com to http://rtc.example.com, the default-person-id is administrator.

The default-person-id will not override any valid person identities that are included in the person mapping file. For example, on an item syncing from http://rtc.example.com to http://qc.example.com, using the person identity administrator when the item on http://qc.example.com already uses dev1 will have no effect on the item on http://qc.example.com.

In the case of a multi person attribute mapping the default-person-id will not be synchronized to the target repository. In addition, any person identities in the target repository which are not mapped will not be overwritten. For example, on an item syncing from http://rtc.example.com to http:/qc.example.com, if the RTC multi person attribute contains the values dev1@example.com and administrator while the HPE QC / ALM multi person attribute contains the values dev2 and dev3. dev1@example.com will map to will be mapped to dev1, administrator will not be mapped, and dev3 will be retained resulting in the HPE QC / ALM multi person attribute having the values dev1 and dev3 set after synchronization has completed.

Setting the mapping-ignore-case attribute to true indicates that Sync should match person identifiers without regard to case. This is useful if the repository allows users to enter person identifiers with the wrong case, such as “testuser1” when the real identifier is “TestUser1”. In example above, the first repository, “http://qc.example.com”, has a user with the identifier “dev1”, but allows the user to enter their identifier as “Dev1” onto tasks. This would normally not match your defined mappings in the Person Mapping file. But since the first repository has mapping-ignore-case="true", it will allow Sync to match the task’s value “Dev1” with the Person Mapping configured person “dev1”. If this attribute is not found on the configuration, the default value is false.

NOTE: Be careful to only set mapping-ignore-case to true on repositories that match person identifiers without regard to case. If set incorrectly, you may encounter errors matching the incorrect person identifier. For instance, if there exists an old mapping to a deactivated or deleted person identifier of “admin”, this may be matched instead of your newly created person identifier “Admin”.

Attribute Based Person Mappings

If the two systems being mapped have users with common attributes, such as their email addresses, then these attributes can be used to automate the person mapping. Here is an example person mapping configuration exercising this capability:

    <?xml version="1.0" encoding="UTF-8"?>
    <person-mappings xmlns="http://tasktop.com/xml/ns/sync/person-mapping-model">
    
        <repository
            url="http://jira.example.com"
            default-person-id="Admin" />
        <repository
            url="http://versionone.example.com"
            default-person-id="administrator" />
            
        <person-mapping>
            <person id="developer" />
            <person id="154J865A246" />
        </person-mapping>
            
        <field-person-mapping>
            <repository
                url="http://jira.example.com"
                mapping-field-id="person-email" />
            <repository
                url="http://versionone.example.com"
                mapping-field-id="Email" />
        </field-person-mapping>

    </person-mappings>
    

In the above example a field-person-mapping has been added which tells Tasktop Sync to attempt to match persons based off the specified fields. Here we’ve chosen to map the email field from each repository. This will cause Tasktop Sync to use the person’s email address to match the corresponding users in each system. If no such person can be found Sync will attempt to map the user by other means.

It may be the case that more than one user exists in the target system which matches the mapped field, for example there may be multiple users in a system with the same display name, or email address. If multiple results are found during person mapping the Synchronization will be placed in error. This can be resolved by adding direct person mappings for the duplicate users, the direct person mappings will be tried before the attribute based person mapping and if a result if found the attribute based person mapping will not be tried.

Multiple field-person-mapping elements can be configured, and the same repository can appear in multiple field-person-mapping elements with different mapping-field-id attributes configured. This allows a single source repository to be mapped to multiple target repositories using different person fields, for example:

    <?xml version="1.0" encoding="UTF-8"?>
    <person-mappings xmlns="http://tasktop.com/xml/ns/sync/person-mapping-model">
    
        <repository
            url="http://jira.example.com"
            default-person-id="Admin" />
        <repository
            url="http://versionone.example.com"
            default-person-id="administrator" />
        <repository
            url="http://tfs.example.com"
            default-person-id="DOMAIN/administrator" />
            
        <person-mapping>
            <person id="developer" />
            <person id="154J865A246" />
            <person id="DOMAIN/developer" />
        </person-mapping>
        
        <field-person-mapping>
            <repository
                url="http://jira.example.com"
                mapping-field-id="person-email" />
            <repository
                url="http://versionone.example.com"
                mapping-field-id="Email" />
        </field-person-mapping>
        
        <field-person-mapping>
            <repository
                url="http://versionone.example.com"
                mapping-field-id="Name" />
            <repository
                url="http://tfs.example.com"
                mapping-field-id="display-name" />
        </field-person-mapping>

    </person-mappings>
    

In the above example users in VersionOne will be mapped with users in Jira using the person’s email, and be mapped with users in Team Foundation Server using the display name. This configuration lacks a field-person-mapping between Jira and Team Foundation Server, as such no attribute based field mapping will occur between these two repositories.

Scripted Person Mappings

If you need even more flexibility than a direct person to person mapping, you can write a scripted person mapper. This can be useful in situations where the difference in the mapped user follows an algorithm, such as jsmith@email.com => jsmith. You can also include much richer logic, such as a connection to a remote server to map the users.

Here is a basic example with two mapping scripts; one defined inside the person mapping configuration, the other defined as a reference to an external groovy file.

<person-mappings xmlns="http://tasktop.com/xml/ns/sync/person-mapping-model">
		
   <repository default-person-id="tasktop" url="https://rallydev.com"/>
   <repository default-person-id="tasktop@email.com" url="http://alm/qcbin"/>

   <!-- A direct person mapping -->
   <person-mapping>
     <person id="jsmith" />
     <person id="johnsmith@email.com" />
   </person-mapping>

   <!-- Links a script to a pair of repositories -->
   <scripted-person-mapping 
      source-repository="https://rallydev.com" 
      target-repository=="http://alm/qcbin" 
      person-script="convertToEmail"/>

   <!-- Links a script to a pair of repositories -->
   <scripted-person-mapping 
      source-repository="http://alm/qcbin" 
      target-repository=="https://rallydev.com" 
      person-script="removeEmail"/>

   <!--An inline script -->
   <person-script language="groovy" name="convertToEmail"><![CDATA[
      def map(value) {
         return value+"@email.com";
      }
   ]]></scripted-person-mapper>

   <!--An external script -->
   <person-script language="groovy" name="removeEmail" script="scripts/removeEmail.groovy"/>

</person-mappings>

The person-script must contain one function, map, which receives a string parameter containing the source person id, and returns a string containing the target person id. If no target person id exists, then the function should return null, which will be mapped to the default person id.

The person-script is connected to a pair of repositories using the scripted-person-mapping node. That script will be executed when a synchronization is occurring from the source-repository URL to the target-repository URL.

The mapping script will only be executed if there is not a match in the direct person-mapping nodes, and no match is found by the attribute based person mapping (if configured). For example, using the script defined above, if the source person is “jsmith”, this user exists within a person-mapping and therefore the “convertToEmail” person-script will not be run. If the source person is “bjohnson”, there is no person-mapping that matches and therefore the person-script will be run (returning “bjohnson@email.com”).

For more details on scripting in Tasktop Sync, see Advanced Scripting

Person Mapping Priority Order

Sync exposes several mechanisms by which to map persons, these mappings are tried in sequence and the first mapping which yields a target result is used. If an error occurs during one mapping step the entire mapping is aborted and the Synchronization will be placed in error. The order in which the mappings will be applied is as follows:

If no result can be found after all mapping stages are tried the Synchronization will be placed in error.