Synchronizing CA Project and Portfolio Management [pre Sync 4.1] with Microsoft Team Foundation Server

This section shows some common mappings between CA PPM® standard task attributes and Microsoft Team Foundation Server standard task attributes.

Task mapping

When synchronizing between Microsoft Team Foundation Server and CA Project and Portfolio Management repositories, it is recommended to use this task mapping:

    <task-mapping conflict-notification-policy="Log">

Comment should not be used as a conflict notification policy, as CA Project and Portfolio Management does not support comments.

Required Repository Properties

Project

The project attribute identifies the project area of the repository to be used for synchronization. It is required for both CA Project and Portfolio Management and Microsoft Team Foundation Server.

ProxyStorageAttribute

The proxyStorage Attribute identifies an attribute that Tasktop Sync will use to store proxy information. It is required for both CA Project and Portfolio Management and Microsoft Team Foundation Server.

Required Attribute Mappings

In order for Tasktop Sync to synchronize new Microsoft Team Foundation Server Work Items into CA Project and Portfolio Management, the External Task ID attribute in CA Project and Portfolio Management must be mapped in an initialization-only configuration. See the CA Project and Portfolio Management Connector For Sync section for full information on the requirements for the External Task ID attribute. Here is an example of a mapping that could be used for External Task ID:

Microsoft Team Foundation Server Attribute CA Project and Portfolio Management Attribute
Key External Task ID

The mapping would be one way (from Microsoft Team Foundation Server to CA Project and Portfolio Management) and would have a mapping strategy of initialize. The synchronizer.xml snippet corresponding to the above example would appear as:

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

Strings

String attributes do not need to be transformed with a caster and can be directly synchronized. Here is an example of a simple string mapping that could be used:

Microsoft Team Foundation Server Attribute CA Project and Portfolio Management Attribute
Summary Summary

Dates

A date caster is not needed when synchronizing between CA Project and Portfolio Management and Microsoft Team Foundation Server repositories. Dates may be synchronized directly.

Value-mapped attributes

Status and % Complete attributes

In CA Project and Portfolio Management, the values of the Status and % Complete attributes are linked. See the CA Project and Portfolio Management Connector For Sync section for details. This is a possible value mapping that can be used for Status.

Microsoft Team Foundation Server’s Status CA Project and Portfolio Management’s Status
Approved Started
Committed Started
Done Completed
New Not Started
Removed Completed

The synchronizer.xml snippet corresponding to the above example would appear as:

        <attribute-mapping>
            <attribute id="status" caster="value-map">
                <caster-configuration>
                    <map>
                        <entry key="New" value="0"/>
                        <entry key="Done" value="2"/>
                        <entry key="Removed" value="2"/>
                        <entry key="Committed" value="1"/>
                        <entry key="Approved" value="1"/>
                    </map>
                </caster-configuration>
            </attribute>
            <attribute id="task.common.status" caster="value-map">
                <caster-configuration>
                    <map>
                        <entry key="0" value="New"/>
                        <entry key="2" value="Done"/>
                        <entry key="1" value="Committed"/>
                    </map>
                </caster-configuration>
            </attribute>
        </attribute-mapping>

When configuring the mapping for the Status attribute, keep workflow rules in mind. Specific sequences of status may be necessary; for example, moving from New to Completed might require a move from New to In Progress followed by a move from In Progress to Completed. If these sequences cannot be mapped directly between repositories, more complicated mappings may be necessary for Status. See the Advanced Concepts section for more details.

Microsoft Team Foundation Server does not have an attribute with equivalent behavior to % Complete. Therefore, it is recommended that the % Complete attribute either not be mapped or be mapped one way, from CA Project and Portfolio Management to Microsoft Team Foundation Server.

Other single select attributes

Other single select attributes, like EV Calculation Method, should be mapped using an appropriate value mapping, similar to that shown for Status above.

Task Assignments

You can also synchronize CA Project and Portfolio Management task assignments with a field or a collection of fields in Microsoft Team Foundation Server, using a scripted attribute handler.

In the following example we set up a one-way mapping, from two fields in Microsoft Team Foundation Server to CA Project and Portfolio Management task assignments. The two Microsoft Team Foundation Server fields are custom.assignee, a person field, and custom.estimation, an integer field. Changing custom.assignee or custom.estimation will cause a new task assignment to be created in CA Project and Portfolio Management with its resource ID set to the value of custom.assignee and its estimated time to complete (ETC) set to the value of custom.estimation. Alternatively, if a task assignement with that resource ID already exists on the CA Project and Portfolio Management task, that existing assignment will have its ETC updated to the value of custom.estimation.

The attribute handler appears in synchronizer.xml as:

        <attribute-handler language="groovy" id="custom.assignee" script="scripts/tfs-fields-to-clarity-assignments.groovy"/>
        <attribute-handler language="groovy" id="custom.estimation" script="scripts/tfs-fields-to-clarity-assignments.groovy"/>

Notice we need to add the handler twice, once for each Microsoft Team Foundation Server field it should be triggered on.

Here is the full groovy script for the attribute handler:

import org.apache.log4j.Logger
import com.tasktop.sync.core.strategy.model.Attribute
import com.tasktop.sync.core.strategy.model.TaskModel
def map(context, Attribute sourceAttribute, TaskModel targetTask) {
	def CLARITY_CONNECTOR_TYPE = "com.tasktop.ca.clarity.ppm"
	def ATTR_ASSIGNEE = "custom.assignee"
	def ATTR_ETC = "custom.estimation"
	def MS_PER_HOUR = 3600000
	if(CLARITY_CONNECTOR_TYPE.equals(targetTask.getConnectorKind())){
		def sourceTaskData = sourceAttribute.taskAttribute.taskData
		def customAssigneeAttr = sourceTaskData.root.getAttribute(ATTR_ASSIGNEE)
		def assignee = customAssigneeAttr.value
		if( !assignee.isEmpty() ) {
			def customEstimateAttr = sourceTaskData.root.getAttribute(ATTR_ETC)
			def estimate = 0
			if( customEstimateAttr != null && !customEstimateAttr.value.isEmpty() ) {
				estimate = customEstimateAttr.value.toInteger() * MS_PER_HOUR
			}
			def assignmentAttr = getOrCreateAssignmentAttr(targetTask, assignee)
			assignmentAttr.createAttribute("tasktop.assignment.estimate").setValue(estimate.toString())
		}
	}
}
def getOrCreateAssignmentAttr(TaskModel targetTask, assignee) {
	def assignmentAttr = findAssignmentAttrByAssignee(targetTask, assignee)
	if( assignmentAttr == null ) {
		assignmentAttr = targetTask.root.createAttribute("tasktop.assignment-new")
		assignmentAttr.getMetaData().defaults().setType("tasktop.type.assignment")
		assignmentAttr.createAttribute("tasktop.assignment.assignee").setValue(assignee)
	}
	return assignmentAttr
}
def findAssignmentAttrByAssignee(TaskModel targetTask, assignee) {
	def taskData = targetTask.taskData
	def assignmentAttrs = taskData.attributeMapper.getAttributesByType(taskData, "tasktop.type.assignment")
	for( assignmentAttr in assignmentAttrs ) {
		def assigneeAttr = assignmentAttr.getAttribute("tasktop.assignment.assignee")
		if( assigneeAttr != null && assigneeAttr.value == assignee ) {
			return assignmentAttr
		}
	}
	return null
}

The script first finds the values of the custom.assignee and custom.estimate fields on the Microsoft Team Foundation Server task. It then checks if the CA Project and Portfolio Management task already has an assignment with the resource ID specified by custom.assignee. Task assignments are accessible as “assignment” attributes in the script. The method findAssignmentAttrByAssignee gets all assignment attributes from the CA Project and Portfolio Management task data and searches for one whose tasktop.assignment.assignee child attribute has this value. If a matching assignment attribute is not found, we create a new one. The method getOrCreateAssignmentAttr creates a new attribute and sets its type to tasktop.type.assignment. It then creates the child attribute tasktop.assignment.assignee and sets its value. Finally, we find or create a new tasktop.assignment.estimate child attribute under the assignment attribute, and set its value.

Note that the value of custom.assignee is not mapped or transformed, so this script will only work if Microsoft Team Foundation Server and CA Project and Portfolio Management have the same users (for example, they share an LDAP server).

For more general information on CA Project and Portfolio Management task assignments, see CA Project and Portfolio Management Connector For Sync: Task Assignments.

Limitations

Please check the Limitations sections of the CA Project and Portfolio Management and Microsoft Team Foundation Server documentation for details.