// <summary> // Prepares composite steps for validation // </summary> // <param name="stepCounter">StepCounter object to count optional and required steps</param> // <param name="parentIsOptional">Indicates if parent step is optional</param> // <param name="parentStep">parent step object</param> // <param name="indexInParent">index of this step inside its parent</param> private static void PrepareExpectedTrace(TraceGroup traceStep, bool parentIsOptional, TraceGroup parentStep, int indexInParent) { // set parent step reference for this step traceStep.parent = parentStep; traceStep.indexInParent = indexInParent; bool optional = parentIsOptional || traceStep.Optional; // set parent step reference for children steps for (int i = 0; i < traceStep.Steps.Count; i++) { WorkflowTraceStep childStep = traceStep.Steps[i]; if (childStep is TraceGroup) { TraceValidator.PrepareExpectedTrace((TraceGroup)childStep, optional, traceStep, i); } else if (childStep is IActualTraceStep) { if (optional || childStep.Optional) { TraceValidator.AddExpectedOptStepCount((IActualTraceStep)childStep); } else { TraceValidator.AddExpectedReqStepCount((IActualTraceStep)childStep); } } } // declare & init endIndexes[] array traceStep.endIndexes = new int[traceStep.Steps.Count]; for (int i = 0; i < traceStep.Steps.Count; i++) { traceStep.endIndexes[i] = -1; } }
// Expected Trace Filter public abstract bool IsAllowed(WorkflowTraceStep actualTrace);
public override bool IsAllowed(WorkflowTraceStep actualTrace) { ActivityTrace at = actualTrace as ActivityTrace; return(at == null || !this.DisplayNames.Contains(at.ActivityName)); }
/// <summary> /// Validate actual trace angainst expected trace. /// This method validates next same level expected step /// </summary> /// <param name="curExpIndex">expected trace step index</param> /// <param name="actualTrace">actual trace</param> /// <param name="startIndex">index to start searches from</param> /// <param name="lastTime">time last step occured at</param> /// <param name="mustBeAfter">subsequent step must occur after time specified</param> /// <returns>true if traces match</returns> private static bool Validate(TraceGroup currentTrace, int curExpIndex, int startIndex, DateTime lastTime, DateTime mustBeAfter) { // is this a last step to check? if (curExpIndex >= currentTrace.Steps.Count) { bool match = false; if (null == currentTrace.parent) { //Oracle.LogDebugInfo("End of step list. Verifying completeness"); return(TraceValidator.VerifyAllStepsValidated()); } else { //Oracle.LogDebugInfo("Check next parent step"); if (currentTrace.Async) { match = TraceValidator.ValidateNextSibling(currentTrace.parent, currentTrace.indexInParent, currentTrace.startIndex); } else { if (currentTrace.ordered) { match = TraceValidator.ValidateNextSibling(currentTrace.parent, currentTrace.indexInParent, currentTrace.startIndex); } else { match = TraceValidator.ValidateNextSibling(currentTrace.parent, currentTrace.indexInParent, TraceValidator.GetMaxEndIndex(currentTrace)); } } } return(match); } WorkflowTraceStep step = currentTrace.Steps[curExpIndex]; if (step is TraceGroup) { // check inner composite step return(TraceValidator.ValidateFirst((TraceGroup)step, startIndex)); } else if (step is DelayTrace) { mustBeAfter = lastTime.Add(((DelayTrace)step).TimeSpan); return(TraceValidator.Validate(currentTrace, curExpIndex + 1, startIndex, lastTime, mustBeAfter)); } else if (step is IActualTraceStep) { int[] entryIndexes = TraceValidator.FindAllEntries((IActualTraceStep)step, startIndex, mustBeAfter); bool match = false; if (entryIndexes.Length == 0) { // step not found if (!step.Optional) { string msg = String.Format("Step '{0}' is not found. Start index {1}", step, startIndex); //Oracle.LogDebugInfo("Adding error: {0}", msg); TraceValidator.s_errorList.Add(msg); } } else if (entryIndexes.Length == 1 && !step.Optional) { // this branch can be commented out // it's an optimization for the most common case // only one option int index = entryIndexes[0]; TraceValidator.MarkAsFound(index, out lastTime); currentTrace.endIndexes[curExpIndex] = index; if (currentTrace.ordered && !step.Async) { match = TraceValidator.Validate(currentTrace, curExpIndex + 1, index + 1, lastTime, mustBeAfter); } else { match = TraceValidator.Validate(currentTrace, curExpIndex + 1, startIndex, lastTime, mustBeAfter); } } else { // many options. try each choice until succeed foreach (int index in entryIndexes) { TraceValidator.SetRestorePoint(); //this.Dump("After SetRestorePoint"); TraceValidator.MarkAsFound(index, out lastTime); currentTrace.endIndexes[curExpIndex] = index; //this.Dump("After mark as found"); if (currentTrace.ordered && !step.Async) { match = TraceValidator.Validate(currentTrace, curExpIndex + 1, entryIndexes[0] + 1, lastTime, mustBeAfter); } else { match = TraceValidator.Validate(currentTrace, curExpIndex + 1, startIndex, lastTime, mustBeAfter); } //this.Dump("After searched subsequent steps"); if (match) { TraceValidator.Commit(); //this.Dump("After Commit"); break; } else { TraceValidator.Rollback(); //this.Dump("After Rollback1"); } } } if (!match && step.Optional) { //Oracle.LogDebugInfo("Skipping optional step"); match = TraceValidator.Validate(currentTrace, curExpIndex + 1, startIndex, lastTime, mustBeAfter); } return(match); } else { throw new Exception(String.Format( "Internal validation error. Unknown step type found {0}", step.GetType().Name)); } }
public override bool IsAllowed(WorkflowTraceStep actualTrace) { return(!(actualTrace is ActivityTrace at) || !this.DisplayNames.Contains(at.ActivityName)); }