The other problem is how you can find a path between from first state to last state. one way to do this is querying work flow and trying to find out next states reachable from current states and move along the way. But this is tricky as you might find yourself in a closed corner and have to backtrack to find another path. But there is an easy way to get the required state transitions, as source work item is available for us. We can get all the state transitions of a work item by work item history. therefore we get state transitions from source work item and replicate them in the target work item.
Code:
public void writeWorkItems(WorkItemCollection workItemCollection)
{
//creating new workitems for source work items
foreach (WorkItem workItem in workItemCollection)
{
WorkItem newWorkItem = null;
newWorkItem = new WorkItem(workItemTypes[workItem.Type.Name]);
------
-----
updateToLatestStatus(workItem, newWorkItem);
newWorkItem.Save();
}
}
public void updateToLatestStatus(WorkItem oldWorkItem, WorkItem newWorkItem)
{
Queue<string> result = new Queue<string>();
string previousState = null;
string originalState = (string)newWorkItem.Fields["State"].Value;
string sourceState = (string)oldWorkItem.Fields["State"].Value;
string sourceFinalReason = (string)oldWorkItem.Fields["Reason"].Value;
//try to change the status directly
newWorkItem.Open();
newWorkItem.Fields["State"].Value = oldWorkItem.Fields["State"].Value;
//System.Diagnostics.Debug.WriteLine(newWorkItem.Type.Name + " " + newWorkItem.Fields["State"].Value);
//if status can't be changed directly...
if (newWorkItem.Fields["State"].Status != FieldStatus.Valid)
{
//get the state transition history of the source work item.
foreach (Revision revision in oldWorkItem.Revisions)
{
// Get Status
if (!revision.Fields["State"].Value.Equals(previousState))
{
previousState = revision.Fields["State"].Value.ToString();
result.Enqueue(previousState);
}
}
int i = 1;
previousState = originalState;
//traverse new work item through old work items's transition states
foreach (String currentStatus in result)
{
bool success = false;
if (i != result.Count)
{
success = ChangeWorkItemStatus(newWorkItem, previousState, currentStatus);
previousState = currentStatus;
}
else
{
success = ChangeWorkItemStatus(newWorkItem, previousState, currentStatus, sourceFinalReason);
}
i++;
// If we could not do the incremental state change then we are done. We will have to go back to the orginal...
if (!success)
break;
}
}
else
{
// Just save it off if we can.
bool success = ChangeWorkItemStatus(newWorkItem, originalState, sourceState);
}
}
private bool ChangeWorkItemStatus(WorkItem workItem, string orginalSourceState, string destState)
{
//Try to save the new state. If that fails then we also go back to the orginal state.
try
{
workItem.Open();
workItem.Fields["State"].Value = destState;
workItem.Save();
return true;
}
catch (Exception)
{
logger.Info(String.Format("Failed to save state for workItem : {0} type:{1} state from {2} to {3}", workItem.Id, workItem.Type.Name, orginalSourceState, destState));
logger.Info(String.Format("rolling workItem status to original state {0}", orginalSourceState));
//Revert back to the original value.
workItem.Fields["State"].Value = orginalSourceState;
return false;
}
}
//save final state transition and set final reason.
private bool ChangeWorkItemStatus(WorkItem workItem, string orginalSourceState, string destState, string reason)
{
//Try to save the new state. If that fails then we also go back to the orginal state.
try
{
workItem.Open();
workItem.Fields["State"].Value = destState;
workItem.Fields["Reason"].Value = reason;
ArrayList list = workItem.Validate();
workItem.Save();
return true;
}
catch (Exception)
{
logger.Info(String.Format("Failed to save state for workItem: {0} type:{1} state from {2} to {3}", workItem.Id.ToString(), workItem.Type.Name, orginalSourceState, destState));
logger.Info(String.Format("rolling workItem status to original state {0}", orginalSourceState));
//Revert back to the original value.
workItem.Fields["State"].Value = orginalSourceState;
return false;
}
}