/// <summary> /// add States and Transitions in WIT /// </summary> /// <param name="wf">Handle to Workflow item</param> private void ProcessStatesAndTransitions(Workflow wf) { Logger.EnteredMethod(LogSource.CQ, wf); // get all states from CQ object[] cqStates = (object[])CQWrapper.GetStateDefNames(cqEntityDef); if (cqStates.Length > 0) { string[] states = new string[cqStates.Length]; Logger.Write(LogSource.CQ, TraceLevel.Verbose, "No of CQ States: [{0}]", cqStates.Length); int l = 0; foreach (string aState in cqStates) { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "CQ State: [{0}]", aState); State witState = new State(); witState.value = aState; wf.WITDSTATES.Add(witState); // add the state in states array states[l++] = aState; } string startState = null; object[] cqActions = (object[])CQWrapper.GetActionDefNames(cqEntityDef); string submitActionName = null; foreach (string action in cqActions) { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "CQ Action: [{0}]", action); int actType = CQWrapper.GetActionDefType(cqEntityDef, action); if (actType == CQConstants.ACTION_SUBMIT) { submitActionName = action; startState = CQWrapper.GetActionDestStateName(cqEntityDef, submitActionName); Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Found Start State : From [\"\"] to [{0}]", startState); // add a transition from NULL state to START state Transition witTransition = new Transition(); witTransition.from = String.Empty; witTransition.to = startState; // add the default reason as NEW for first transition Reason transReason = new Reason(); transReason.value = submitActionName; witTransition.REASONS.DEFAULTREASON = transReason; wf.WITDTRANSITIONS.Add(witTransition); break; } } // find out all the duplicate and unduplicate actions and duplicate states List <string> unduplicateActions = new List <string>(); List <string> duplicateStates = new List <string>(); object[] allActions = (object[])CQWrapper.GetActionDefNames(cqEntityDef); foreach (string action in allActions) { int actionType = CQWrapper.GetActionDefType(cqEntityDef, action); if (actionType == CQConstants.ACTION_DUPLICATE) { string dupActState = CQWrapper.GetActionDestStateName(cqEntityDef, action); if (!string.IsNullOrEmpty(dupActState)) { duplicateStates.Add(dupActState); } Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Duplicate Action : [{0}]", action); Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Duplicate State : [{0}]", dupActState); } else if (actionType == CQConstants.ACTION_UNDUPLICATE) { unduplicateActions.Add(action); Logger.Write(LogSource.CQ, TraceLevel.Verbose, "UnDuplicate Action : [{0}]", action); } } // prepare the state transition matrix for (int dstState = 0; dstState < states.Length; dstState++) { // visit all the source states which can lead to the current destination state for (int srcState = 0; srcState < states.Length; srcState++) { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Calling DoesTransitionExist Source State: [{0}], Dest State: [{1}]", states[srcState], states[dstState]); object[] transitions = (object[])CQWrapper.DoesTransitionExist(cqEntityDef, states[srcState], states[dstState]); if (transitions != null && transitions.Length > 0) { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Does Transition returned [{0}] transitions", transitions.Length); Transition witTransition = new Transition(); witTransition.from = states[srcState]; witTransition.to = states[dstState]; // add the reason as the ACTION defined in CQ Reason transReason = new Reason(); transReason.value = (string)transitions.GetValue(0); witTransition.REASONS.DEFAULTREASON = transReason; wf.WITDTRANSITIONS.Add(witTransition); Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Adding Transitions [{0}] to [{1}] with Reason [{2}]", states[srcState], states[dstState], transReason.value); } else { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Does Transition returned No transitions"); } } // now for each duplicate action find out all the states that lead to duplicate action // so that back transition could be added for (int dupStateIndex = 0; dupStateIndex < duplicateStates.Count; dupStateIndex++) { string dupState = duplicateStates[dupStateIndex]; // here dststate is being used as the source state and the destination state is Duplicate Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Calling DoesTransitionExist Source State: [{0}], Dest State: [{1}]", states[dstState], dupState); object[] transitions = (object[])CQWrapper.DoesTransitionExist(cqEntityDef, states[dstState], dupState); if (transitions != null && transitions.Length > 0) { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Does Transition returned [{0}] transitions", transitions.Length); bool found = false; // if this transition is not already there.. foreach (Transition trans in wf.WITDTRANSITIONS) { if (TFStringComparer.WorkItemStateName.Equals(trans.from, dupState) && TFStringComparer.WorkItemStateName.Equals(trans.to, states[dstState])) { found = true; // add all the unduplicate actions name as allowed reasons foreach (string undupActionName in unduplicateActions) { // string undupActionName = (string)duplicateActions[dupStateIndex]; if (trans.REASONS.DEFAULTREASON.Equals(undupActionName)) { // reason already there.. skip this duplicate state and move to next state continue; // skip this reason and add other reasons } // check in other reasons if (trans.REASONS.REASON == null) { // no reasons added yet.. add this trans.REASONS.WITDREASON.Add(undupActionName); } else { // check if this reason already there if (!trans.REASONS.REASON.Contains(undupActionName)) { trans.REASONS.REASON.Add(undupActionName); } } } // move to next state break; } // end of if transition exist } if (!found) { // this back transition is not defined.. create it now // add a unduplicate transition Transition witTransition = new Transition(); witTransition.from = dupState; witTransition.to = states[dstState]; // add the reason as the ACTION defined in CQ bool isFirst = true; foreach (string undupActionName in unduplicateActions) { Reason transReason = new Reason(); transReason.value = undupActionName; if (isFirst) { witTransition.REASONS.DEFAULTREASON = transReason; isFirst = false; } else { witTransition.REASONS.WITDREASON.Add(transReason); } } wf.WITDTRANSITIONS.Add(witTransition); } } else { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Does Transition returned No transitions"); } } // end of duplicate action handling } // end of preparing state transition matrix for loop } //if (cqStates.Length > 0) else { // if the current entity does not have any states the minimal // state model has top be created Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Creating Dummy Workflow for {0}", schemaXMLFileName); CreateDummyWorkflow(wf); } Logger.ExitingMethod(LogSource.CQ); } // end of ProcessStatesAndTransitions