TFS Integration Platform – Getting to grips with the new configuration options

We are working on creating a readiness package for the TFS Integration Package, which includes a usage document from Hyung for some of the new features … all of which we will quickly mention in this blog post. Let me know if you want/need more information on any of the features and we will dig in accordingly.Blue Men at a Bench at a Bus Stop Clipart Illustration Thanks Hyung, for the documentation which I am extracting and including in this post.

The three features we will skim over:

  • Using field map
  • Conditional field map
  • Aggregated fields

Using field map

  • The WorkItemType mapping defines type mapping from source to to target.
  • The FieldMap defines field mappings.
    • Note that any missing field in this map will be dropped if a field map is defined.
    • If no field map is defined the platform implicitly maps every field as is.
  • The ValueMap defines value mappings that can be used in field mapping.
    • We have two modes that the value map can be operating under:
      • EnableBypassRuleDataSubmission is enabled (Recommended mode)
        • TFS Adapter submits a work item directly using XML document which is constructed based on the field map.
        • If it’s the last revision, TFS Adapter will pick a default value for any field that is not mapped to make sure that the last revision on target is valid and editable. (This feature only applies to “CQ to TFS migration”)
      • EnableBypassRuleDataSubmission is disabled
        • TFS Adapter submits a work item using TFS OM. So if a field is not mapped, a default value (if any) will be used to create a work item by TFS OM

Example … if enablebypassruledatasubmission is enabled, we are moving the latest revision, if we use the TFS Adapter and are targeting a default work item of type bug in the Agile process template, the example below would migrate the defect as Medium, value 2, which is the default state in the work item template definition (WITD).

    1: <CustomSettings>
    2:  <SettingXml>
    3:   <WITSessionCustomSetting>
    4:   <WorkItemTypes>
    5:       <WorkItemType LeftWorkItemTypeName="Defect" RightWorkItemTypeName="Bug" fieldMap="Defect2BugFieldMap" /> 
    6:   </WorkItemTypes>
    7:   <FieldMaps>
    8:       <FieldMap name="Defect2BugFieldMap">
    9:           <MappedFields>
   10:               <MappedField LeftName="State" RightName="System.State" MapFromSide="Left" valueMap="StateMap" /> 
   11:               <MappedField LeftName="Priority" RightName="Microsoft.VSTS.Common.Priority" MapFromSide="Left" valueMap="PriorityMap" /> 
   12:           </MappedFields>
   13:       </FieldMap>
   14:   </FieldMaps>
   15:   <ValueMaps>
   16:       <ValueMap name="StateMap">
   17:           <Value LeftValue="Value1" RightValue="Active" /> 
   18:           <Value LeftValue="Value2" RightValue="Resolved" /> 
   19:           <Value LeftValue="Value3" RightValue="Closed" /> 
   20:       </ValueMap>
   21:       <ValueMap name="PriorityMap">
   22:           <Value LeftValue="High" RightValue="1" /> 
   23:           <Value LeftValue="Medium" RightValue="2" /> 
   24:           <Value LeftValue="Low" RightValue="3" /> 
   25:           <Value LeftValue="" RightValue="3" /> 
   26:       </ValueMap>
   27:   </ValueMaps>
   28:   </WITSessionCustomSetting>
   29:  </SettingXml>
   30: </CustomSettings>

Conditional field mapBlue Man Holding a Clipboard While Reviewing Employess Clipart Illustration

The latest new feature includes the conditional field map and the <When> construct. The when construct is used to map fields conditionally.

For instance, if CQ “AssignedTo” field needs to be mapped to “AssignedTo” field for all States except Submitted, the highlighted block migrates AssignedTo field to target only when State in CQ is not submitted.

    1: <FieldMaps>
    2:   <FieldMap name="FieldMapName">
    3:     <MappedFields>
    4:       <MappedField LeftName="CQAssignedToFieldName" RightName="System.AssignedTo" MapFromSide="Left" valueMap="AssignedToValueMap" />
    5:       ...other field mappings ..
    6:     </MappedFields>
    7:   </FieldMap>
    8: </FieldMaps>
    9: <ValueMaps>
   10:   <ValueMap name="AssignedToValueMap">
   11:     <!-- conditional mapping from anything to empty string when CQ State’s value is Submitted   -->
   12:     <Value LeftValue="*" RightValue="">
   13:       <When ConditionalSrcFieldName="State" ConditionalSrcFieldValue="Submitted" />
   14:     </Value>
   15:     <!-- otherwise…   -->
   16:     <Value LeftValue="*" RightValue="*" />
   17:   </ValueMap>
   18: </ValueMaps> 

Mapping evaluation precedence

  • In value map setting, <When> is new and optional.
  • The mapping evaluation precedence order is as following:
    • map v1 => v2, when SourceFieldName.value = value1
    • map *  => v2, when SourceFieldName .value = value1
    • map v1 => v2, when SourceFieldName.value = *
    • map *  => v2, when SourceFieldName.value = *
    • map v1 => v2
    • map *  => v2

For example, the configuration below is evaluated in the following order:

  • Map value 2 to value 1
  • Map value 2 to Value 3 if System.Description’s value is “Value2”
  • Map any value to Value 1 otherwise

Note that mapping evaluation order is not related to the order of conditions specified in ValueMaps. For example the 3rd condition in the example gets evaluated before the 2nd condition due to the evaluation precedence.

    1: <WorkItemTypes>
    2:   <WorkItemType LeftWorkItemTypeName="Bug" RightWorkItemTypeName="Bug" fieldMap="BugToBugFieldMap" />
    3: </WorkItemTypes>
    4: <FieldMaps>
    5:   <FieldMap name="BugToBugFieldMap">
    6:     <MappedFields>
    7:       <MappedField LeftName="*" RightName="*" MapFromSide="Left" />
    8:       <MappedField LeftName="Microsoft.VSTS.Common.Priority" RightName="Microsoft.VSTS.Common.Priority" MapFromSide="Left" valueMap="PriorityValueMap" />
    9:     </MappedFields>
   10:   </FieldMap>
   11: </FieldMaps>
   12: <ValueMaps>
   13:   <ValueMap name="PriorityValueMap">
   14:     <Value LeftValue="2" RightValue="1">
   15:       <When />
   16:     </Value>
   17:     <Value LeftValue="*" RightValue="1">
   18:       <When ConditionalSrcFieldName="System.Description" ConditionalSrcFieldValue="Value1" />
   19:     </Value>
   20:     <Value LeftValue="2" RightValue="3">
   21:       <When ConditionalSrcFieldName="System.Description" ConditionalSrcFieldValue="Value2" />
   22:     </Value>
   23:   </ValueMap>
   24: </ValueMaps>

Gold Business People Connected By Atoms, Symbolizing Teamwork, Brainstorming, Creativity And Ideas Clipart Illustration Image Aggregated fields

You can aggregate multiple fields into one field using AggregatedFields setting.

For instance the example below would map SourceFieldName1 and SourceFieldName2 to TargetFieldName. You can also customize the format to shape the value of the aggregated fields.

The example below simply concatenates two source fields by using “{0} {1}”.

    1: <MappedFields>
    2:   ....
    3: </MappedFields>
    4: <AggregatedFields>
    5: <FieldsAggregationGroup MapFromSide="Left" TargetFieldName="TargetFieldName" Format="{0} {1}">
    6:     <SourceField Index="0" SourceFieldName="SourceFieldName1" />
    7:     <SourceField Index="1" SourceFieldName="SourceFieldName2" />
    8:   </FieldsAggregationGroup>
    9: </AggregatedFields>

The power of the platform configuration is evolving constantly, especially as special cases are identified and features are requested in the proof of concepts we are busy with. In my next blog post I will mention the new and forthcoming administrative tool, which brings exciting evolutions to the administrative world. However, it is important to realize that the new administration tool is galloping behind the wave of configuration features and may not always be able to configure all of the new features at this stage. In a situation where the new administrative tool does not yet support the configuration we will have to roll up our sleeves and dig into the XML … we are therefore going to continue to expose you to and explain the relevant XML syntax ... as much as I would personally like to hide it :)