|
namespace System.Workflow.Activities
{
#region Imports
using System;
using System.Text;
using System.Reflection;
using System.Collections;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Drawing;
using System.Diagnostics;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Xml.Serialization;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.Activities.Common;
#endregion
#region StateValidator class
[System.Runtime.InteropServices.ComVisible(false)]
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
public class StateActivityValidator : CompositeActivityValidator
{
public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
{
ValidationErrorCollection validationErrors = new ValidationErrorCollection(base.Validate(manager, obj));
StateActivity state = obj as StateActivity;
if (state == null)
throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(StateActivity).FullName), "obj");
// First we validate contaiment
if (state.Parent != null)
{
if (StateMachineHelpers.IsStateMachine(state))
{
validationErrors.Add(new ValidationError(SR.GetError_StateMachineWorkflowMustBeARootActivity(), ErrorNumbers.Error_StateMachineWorkflowMustBeARootActivity));
return validationErrors;
}
else
{
// Make sure that a State is always contained in
// another State or StateMachineWorkflow. State machine
// within a sequential workflow is not supported
if (!(state.Parent is StateActivity))
{
validationErrors.Add(new ValidationError(SR.GetError_InvalidStateActivityParent(), ErrorNumbers.Error_InvalidStateActivityParent));
return validationErrors;
}
}
}
if (state.Parent == null && !StateMachineHelpers.IsStateMachine(state))
{
ValidateCustomStateActivity(state, validationErrors);
}
if (StateMachineHelpers.IsLeafState(state))
{
ValidateLeafState(state, validationErrors);
}
else if (StateMachineHelpers.IsRootState(state))
{
ValidateRootState(state, validationErrors);
}
else
{
ValidateState(state, validationErrors);
}
ValidateEventDrivenActivities(state, validationErrors);
return validationErrors;
}
private static void ValidateCustomStateActivity(StateActivity state, ValidationErrorCollection validationErrors)
{
if (state.Activities.Count > 0)
{
validationErrors.Add(new ValidationError(SR.GetError_BlackBoxCustomStateNotSupported(), ErrorNumbers.Error_BlackBoxCustomStateNotSupported));
}
}
public override ValidationError ValidateActivityChange(Activity activity, ActivityChangeAction action)
{
if (activity == null)
throw new ArgumentNullException("activity");
if (action == null)
throw new ArgumentNullException("action");
if (activity.ExecutionStatus != ActivityExecutionStatus.Initialized &&
activity.ExecutionStatus != ActivityExecutionStatus.Executing &&
activity.ExecutionStatus != ActivityExecutionStatus.Closed)
{
return new ValidationError(SR.GetString(SR.Error_DynamicActivity2, activity.QualifiedName, activity.ExecutionStatus, activity.GetType().FullName), ErrorNumbers.Error_DynamicActivity2);
}
RemovedActivityAction remove = action as RemovedActivityAction;
if (remove != null)
{
StateActivity removedState = remove.OriginalRemovedActivity as StateActivity;
if (removedState != null)
{
// we don't have a way to check if the removed
// activity is executing or not, so if the user is trying to
// remove a StateActivity, we simply disallow it.
//
return new ValidationError(
SR.GetError_CantRemoveState(removedState.QualifiedName),
ErrorNumbers.Error_CantRemoveState);
}
if (activity.ExecutionStatus == ActivityExecutionStatus.Executing)
{
EventDrivenActivity removedEventDriven = remove.OriginalRemovedActivity as EventDrivenActivity;
if (removedEventDriven != null)
{
return new ValidationError(
SR.GetError_CantRemoveEventDrivenFromExecutingState(removedEventDriven.QualifiedName, activity.QualifiedName),
ErrorNumbers.Error_CantRemoveEventDrivenFromExecutingState);
}
}
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
private static void ValidateLeafState(StateActivity state, ValidationErrorCollection validationErrors)
{
ValidateLeafStateChildren(state, validationErrors);
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
private static void ValidateRootState(StateActivity state, ValidationErrorCollection validationErrors)
{
ValidateCompositeStateChildren(state, validationErrors);
if (StateMachineHelpers.IsStateMachine(state))
{
ValidateInitialState(state, validationErrors);
ValidateCompletedState(state, validationErrors);
}
}
private static void ValidateState(StateActivity state, ValidationErrorCollection validationErrors)
{
ValidateCompositeStateChildren(state, validationErrors);
}
#region Helpers
private static void ValidateLeafStateChildren(StateActivity state, ValidationErrorCollection validationErrors)
{
bool invalidChild = false;
foreach (Activity activity in state.Activities)
{
if (!activity.Enabled)
continue;
if (activity is EventDrivenActivity ||
activity is StateInitializationActivity ||
activity is StateFinalizationActivity)
{
continue;
}
else
{
invalidChild = true;
break;
}
}
// validate that all child activities are event driven activities.
if (invalidChild)
validationErrors.Add(new ValidationError(
SR.GetError_InvalidLeafStateChild(),
ErrorNumbers.Error_InvalidLeafStateChild));
}
private static void ValidateCompositeStateChildren(StateActivity state, ValidationErrorCollection validationErrors)
{
bool invalidChild = false;
foreach (Activity activity in state.Activities)
{
if (!activity.Enabled)
continue;
if (activity is EventDrivenActivity ||
activity is StateActivity)
{
continue;
}
else
{
invalidChild = true;
break;
}
}
if (invalidChild)
validationErrors.Add(new ValidationError(
SR.GetError_InvalidCompositeStateChild(),
ErrorNumbers.Error_InvalidCompositeStateChild));
}
private static void ValidateInitialState(StateActivity state, ValidationErrorCollection validationErrors)
{
string initialStateName = StateMachineHelpers.GetInitialStateName(state);
if (String.IsNullOrEmpty(initialStateName))
{
if (state.Activities.Count > 0)
{
// we only require an initial state if the state machine is
// not empty
validationErrors.Add(new ValidationError(
SR.GetString(SR.Error_PropertyNotSet, StateMachineWorkflowActivity.InitialStateNamePropertyName),
ErrorNumbers.Error_PropertyNotSet, false,
StateMachineWorkflowActivity.InitialStateNamePropertyName));
}
}
else
{
StateActivity initialState = StateMachineHelpers.FindStateByName(
state,
initialStateName);
if (initialState == null)
{
validationErrors.Add(new ValidationError(
SR.GetError_InitialStateMustPointToAState(),
ErrorNumbers.Error_InitialStateMustPointToAState,
false,
StateMachineWorkflowActivity.InitialStateNamePropertyName));
}
else
{
if (!StateMachineHelpers.IsLeafState(initialState))
{
validationErrors.Add(new ValidationError(
SR.GetError_InitialStateMustPointToALeafNodeState(),
ErrorNumbers.Error_InitialStateMustPointToALeafNodeState,
false,
StateMachineWorkflowActivity.InitialStateNamePropertyName));
}
// InitialState cannot be the completed state
string completedStateName = StateMachineHelpers.GetCompletedStateName(state);
if (initialStateName == completedStateName)
{
validationErrors.Add(new ValidationError(
SR.GetError_InitialStateMustBeDifferentThanCompletedState(),
ErrorNumbers.Error_InitialStateMustBeDifferentThanCompletedState,
false,
StateMachineWorkflowActivity.InitialStateNamePropertyName));
}
}
}
}
private static void ValidateCompletedState(StateActivity state, ValidationErrorCollection validationErrors)
{
string completedStateName = StateMachineHelpers.GetCompletedStateName(state);
if (!String.IsNullOrEmpty(completedStateName))
{
StateActivity completedState = StateMachineHelpers.FindStateByName(
state,
completedStateName);
if (completedState == null)
{
validationErrors.Add(new ValidationError(
SR.GetError_CompletedStateMustPointToAState(),
ErrorNumbers.Error_CompletedStateMustPointToAState,
false,
StateMachineWorkflowActivity.CompletedStateNamePropertyName));
}
else
{
if (StateMachineHelpers.IsLeafState(completedState))
{
if (completedState.EnabledActivities.Count > 0)
validationErrors.Add(new ValidationError(
SR.GetString(SR.Error_CompletedStateCannotContainActivities),
ErrorNumbers.Error_CompletedStateCannotContainActivities,
false,
StateMachineWorkflowActivity.CompletedStateNamePropertyName));
}
else
{
validationErrors.Add(new ValidationError(
SR.GetError_CompletedStateMustPointToALeafNodeState(),
ErrorNumbers.Error_CompletedStateMustPointToALeafNodeState,
false,
StateMachineWorkflowActivity.CompletedStateNamePropertyName));
}
}
}
}
private static void ValidateEventDrivenActivities(StateActivity state, ValidationErrorCollection validationErrors)
{
List<EventDrivenActivity> eventDrivenList = new List<EventDrivenActivity>();
foreach (Activity activity in state.EnabledActivities)
{
EventDrivenActivity eventDriven = activity as EventDrivenActivity;
if (eventDriven != null)
{
eventDrivenList.Add(eventDriven);
}
}
foreach (EventDrivenActivity eventDriven in eventDrivenList)
{
bool result = ValidateMultipleIEventActivity(eventDriven, validationErrors);
if (!result)
break;
}
}
private static bool ValidateMultipleIEventActivity(EventDrivenActivity eventDriven, ValidationErrorCollection validationErrors)
{
IEventActivity firstEventActivity = null;
if (eventDriven.EnabledActivities.Count > 0)
{
firstEventActivity = eventDriven.EnabledActivities[0] as IEventActivity;
}
return ValidateMultipleIEventActivityInCompositeActivity(eventDriven, firstEventActivity, eventDriven, validationErrors);
}
private static bool ValidateMultipleIEventActivityInCompositeActivity(EventDrivenActivity eventDriven, IEventActivity firstEventActivity, CompositeActivity parent, ValidationErrorCollection validationErrors)
{
foreach (Activity activity in parent.Activities)
{
// Skip disabled activities or the first IEventActivity
// Note that we don't use EnabledActivities because we want to
// enforce this rule inside Cancellation and Exception Handlers.
if (!activity.Enabled || activity == firstEventActivity)
continue;
if (activity is IEventActivity)
{
validationErrors.Add(new ValidationError(
SR.GetString(SR.Error_EventDrivenMultipleEventActivity, eventDriven.Name, typeof(IEventActivity).FullName, typeof(EventDrivenActivity).Name),
ErrorNumbers.Error_EventDrivenMultipleEventActivity));
return false;
}
else
{
CompositeActivity compositeActivity = activity as CompositeActivity;
if (compositeActivity != null)
{
bool result = ValidateMultipleIEventActivityInCompositeActivity(eventDriven, firstEventActivity, compositeActivity, validationErrors);
if (!result)
return false;
}
}
}
return true;
}
#endregion
}
#endregion StateValidator class
}
|