public void Validate(DeviceWorkflow workflow, ValidationResult result) { /* If core attributes (validated at parent level) are not valid, don't bother validating */ if (Validator.Validate(this).Successful) { result.Concat(ValidateNodeBase(workflow)); if (EntityHeader.IsNullOrEmpty(AttributeType)) { result.Errors.Add(new ErrorMessage($"On Attribute {Name}, Attribute Type is missing.", true)); } else if (AttributeType.Value == ParameterTypes.ValueWithUnit) { StateSet = null; if (EntityHeader.IsNullOrEmpty(UnitSet)) { result.Errors.Add(new ErrorMessage($"On Attribute {Name}, Value with Unit is data type, but no Unit Set was provided.", true)); return; } } else if (AttributeType.Value == ParameterTypes.State) { UnitSet = null; if (EntityHeader.IsNullOrEmpty(StateSet)) { result.Errors.Add(new ErrorMessage($"On Attribute {Name}, State Set is data type, but no State Set was provided.", true)); return; } } else { StateSet = null; UnitSet = null; } if (!result.Successful) { return; } foreach (var connection in OutgoingConnections) { switch (connection.NodeType) { case NodeType_Input: case NodeType_InputCommand: result.Errors.Add(new ErrorMessage($"Mapping from an Input to a node of type: {NodeType} is not supported", true)); break; case NodeType_StateMachine: ValidateStateMachine(result, workflow, connection); break; case NodeType_Attribute: case NodeType_OutputCommand: break; } } } }
public void Validate(DeviceWorkflow workflow, ValidationResult result) { if (result.Successful) { result.Concat(ValidateNodeBase(workflow)); if (Parameters.Select(param => param.Key).Distinct().Count() != Parameters.Count()) { result.Errors.Add(new ErrorMessage($"On Output Command {Name}, keys on Parameters must be unique.", true)); return; } foreach (var parameter in Parameters) { if (parameter.ParameterType == null) { result.Errors.Add(new ErrorMessage($"On Output Command {Name}, Parameter {parameter.Name} parameter type is missing.", true)); } else if (parameter.ParameterType.Value == ParameterTypes.ValueWithUnit) { parameter.StateSet = null; if (EntityHeader.IsNullOrEmpty(parameter.UnitSet)) { result.Errors.Add(new ErrorMessage($"On Output Command {Name}, Parameter {parameter.Name} Value with Unit is data type, but no unit type was provided.", true)); return; } } else if (parameter.ParameterType.Value == ParameterTypes.State) { parameter.UnitSet = null; if (EntityHeader.IsNullOrEmpty(parameter.StateSet)) { result.Errors.Add(new ErrorMessage($"On Output Command {Name}, Parameter {parameter.Name} is a state set, but no state set was provided.", true)); return; } } else { parameter.UnitSet = null; parameter.StateSet = null; } } if (OutgoingConnections.Count > 0) { result.Errors.Add(new ErrorMessage($"Mapping from an Output Command to an other node types is not supported", true)); } } }
protected void ValidateStateMachine(ValidationResult result, DeviceWorkflow workflow, Connection connection) { if (EntityHeader.IsNullOrEmpty(connection.StateMachineEvent)) { result.Errors.Add(new ErrorMessage($"Transition Event is empty from {Name} to State Machine {connection.NodeName} does not exist on that state machine.")); } else { var outputStateMachine = workflow.StateMachines.Where(stm => stm.Key == connection.NodeKey).FirstOrDefault(); if (outputStateMachine != null) { if (!outputStateMachine.Events.Where(evt => evt.Key == connection.StateMachineEvent.Id).Any()) { result.Errors.Add(new ErrorMessage($"Transition Event {connection.StateMachineEvent.Text} from {Name} to {outputStateMachine.Name} does not exist on that state machine.")); } } else { throw new InvalidOperationException($"Could not find state machine with key {connection.NodeKey}."); } } }
public void Validate(DeviceWorkflow workflow, ValidationResult result) { if (Validator.Validate(this).Successful) { if (States.Select(param => param.Key).Distinct().Count() != States.Count()) { result.AddUserError($"Duplicate Keys found in States on State Machine: {Name}."); } if (Events.Select(param => param.Key).Distinct().Count() != Events.Count()) { result.AddUserError($"Duplicate Keys found in Events on State Machine: {Name}."); } if (Variables.Select(param => param.Key).Distinct().Count() != Variables.Count()) { result.AddUserError($"Duplicate Keys found in Variables on State Machine: {Name}."); } result.Concat(ValidateNodeBase(workflow)); foreach (var connection in OutgoingConnections) { if (connection.NodeType == NodeType_Input || connection.NodeType == NodeType_InputCommand) { result.Errors.Add(new ErrorMessage($"Mapping from an Input to a node of type: {NodeType} is not supported", true)); } } foreach (var variable in Variables) { variable.Validate(result); } foreach (var state in States) { state.Validate(result); } } }
public ValidationResult Validate(DeviceWorkflow workflow, ValidationResult result) { if (Validator.Validate(this).Successful) { result.Concat(ValidateNodeBase(workflow)); if (Parameters.Select(param => param.Key).Distinct().Count() != Parameters.Count()) { result.Errors.Add(new ErrorMessage($"On Input Command, {Name} keys on Parameters must be unique.", true)); return(result); } foreach (var parameter in Parameters) { if (EntityHeader.IsNullOrEmpty(parameter.ParameterLocation)) { result.Errors.Add(new ErrorMessage($"On Input Command {Name}, Parameter Location is not provided.", true)); return(result); } if (parameter.ParameterType == null) { result.Errors.Add(new ErrorMessage($"On Input Command {Name}, Parameter {parameter.Name} parameter type is missing.", true)); } else if (parameter.ParameterType.Value == ParameterTypes.ValueWithUnit) { parameter.StateSet = null; if (EntityHeader.IsNullOrEmpty(parameter.UnitSet)) { result.Errors.Add(new ErrorMessage($"On Input Command {Name}, Parameter {parameter.Name} Value with Unit is data type, but no unit type was provided.", true)); return(result); } } else if (parameter.ParameterType.Value == ParameterTypes.State) { parameter.UnitSet = null; if (EntityHeader.IsNullOrEmpty(parameter.StateSet)) { result.Errors.Add(new ErrorMessage($"On Input Command {Name}, Parameter {parameter.Name} is a state set, but no state set was provided.", true)); return(result); } } else { parameter.UnitSet = null; parameter.StateSet = null; } if (parameter.ParameterLocation.Value == PayloadTypes.Json && (EndpointType.Value == EndpointTypes.RestGet || EndpointType.Value == EndpointTypes.RestDelete)) { result.AddSystemError("End point type of GET or DELETE was specified, however at least one of the parameters has JSON specified for the parameter location."); } } if (!result.Successful) { return(result); } foreach (var connection in OutgoingConnections) { switch (connection.NodeType) { case NodeType_Input: case NodeType_InputCommand: result.Errors.Add(new ErrorMessage($"Mapping from an Input Command on node {Name} to a node of type {connection.NodeType} is not supported", true)); break; case NodeType_Attribute: if (connection.InputCommandKey == null) { result.Errors.Add(new ErrorMessage($"When Mapping from in Input Command on node {Name} to an Attribute, you must specify which parameter will be mapped", false)); } else { var parameter = Parameters.Where(prm => prm.Key == connection.InputCommandKey).FirstOrDefault(); if (parameter == null) { result.Errors.Add(new ErrorMessage($"Specified Mapping Key {connection.InputCommandKey} not found on inputs from {Name}", false)); } else { var attribute = workflow.Attributes.Where(attr => attr.Key == connection.NodeKey).First(); if (attribute.AttributeType.Value != parameter.ParameterType.Value) { result.Errors.Add(new ErrorMessage($"On input command {Name}, type mismatch on mapping to {connection.NodeName} from input command {parameter.Name} to attribute of type {parameter.ParameterType.Text}.", false)); } else { if (attribute.AttributeType.Value == ParameterTypes.State && attribute.StateSet.Id != parameter.StateSet.Id) { result.Errors.Add(new ErrorMessage($"Invalid Mapping between {Name} and {connection.NodeName} - State Sets to do not match.")); } else if (attribute.AttributeType.Value == ParameterTypes.ValueWithUnit && attribute.UnitSet.Id != parameter.UnitSet.Id) { result.Errors.Add(new ErrorMessage($"Invalid Mapping between {Name} and {connection.NodeName} - Unit Sets to do not match.")); } } } } break; case NodeType_StateMachine: ValidateStateMachine(result, workflow, connection); break; } } } return(result); }
/// <summary> /// Make sure that the incoming and outgoing connections exists and valid for the core information. /// </summary> /// <param name="workflow"></param> /// <returns></returns> protected ValidationResult ValidateNodeBase(DeviceWorkflow workflow) { var result = new ValidationResult(); if (NodeType != NodeType_Input && NodeType != NodeType_Attribute && NodeType != NodeType_Script && NodeType != NodeType_InputCommand && NodeType != NodeType_Timer && NodeType != NodeType_StateMachine && NodeType != NodeType_OutputCommand) { result.Errors.Add(new ErrorMessage($"Invalid node type: {NodeType}", true)); } foreach (var connection in OutgoingConnections) { if (String.IsNullOrEmpty(connection.NodeType)) { result.Errors.Add(new ErrorMessage($"Missing Node Type for outgoing connection on node {Name}", true)); } if (String.IsNullOrEmpty(connection.NodeKey)) { result.Errors.Add(new ErrorMessage($"Missing Node Key for outgoing connection on node {Name}", true)); } if (String.IsNullOrEmpty(connection.NodeName)) { result.Errors.Add(new ErrorMessage($"Missing Node Name for outgoing connection on node {Name}", true)); } if (!result.Successful) { return(result); } switch (connection.NodeType) { case NodeType_Input: if (!workflow.Inputs.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find outgoing connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_Attribute: if (!workflow.Attributes.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find outgoing connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_InputCommand: if (!workflow.InputCommands.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find outgoing connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_OutputCommand: if (!workflow.OutputCommands.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find outgoing connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_StateMachine: if (!workflow.StateMachines.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find outgoing connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; default: result.Errors.Add(new ErrorMessage($"Unknown outgoing connection node type {connection.NodeType} on node {Name}", true)); break; } } foreach (var connection in IncomingConnections) { if (String.IsNullOrEmpty(connection.NodeType)) { result.Errors.Add(new ErrorMessage($"Missing Node type for incoming connection on node {Name}", true)); } if (String.IsNullOrEmpty(connection.NodeKey)) { result.Errors.Add(new ErrorMessage($"Missing Node Key for incoming connection on node {Name}", true)); } if (String.IsNullOrEmpty(connection.NodeName)) { result.Errors.Add(new ErrorMessage($"Missing Node Name for incoming connection on node {Name}", true)); } if (!result.Successful) { return(result); } switch (connection.NodeType) { case NodeType_Input: if (!workflow.Inputs.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find incoming connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_Attribute: if (!workflow.Attributes.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find incoming connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_InputCommand: if (!workflow.InputCommands.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find incoming connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_OutputCommand: if (!workflow.OutputCommands.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find incoming connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; case NodeType_StateMachine: if (!workflow.StateMachines.Where(inp => inp.Key == connection.NodeKey).Any()) { result.Errors.Add(new ErrorMessage($"On Node Type {NodeType}, Node {Name}, could not find incoming connection of type {connection.NodeType}, Node {connection.NodeKey}.")); } break; default: result.Errors.Add(new ErrorMessage($"Unknown incoming connection node type {connection.NodeType} on node {Name}", true)); break; } } return(result); }
public void Validate(DeviceWorkflow workflow, ValidationResult result) { /* If core attributes (validated at parent level) are not valid, don't bother validating */ if (Validator.Validate(this).Successful) { result.Concat(ValidateNodeBase(workflow)); if (EntityHeader.IsNullOrEmpty(InputType)) { result.Errors.Add(new ErrorMessage($"On Workflow Input {Name}, Input Type is missing.", true)); } else if (InputType.Value == ParameterTypes.ValueWithUnit) { StateSet = null; if (EntityHeader.IsNullOrEmpty(UnitSet)) { result.Errors.Add(new ErrorMessage($"On Workflow Input {Name}, data type is Value with Unit, but no unit type was provided.", true)); return; } } else if (InputType.Value == ParameterTypes.State) { UnitSet = null; if (EntityHeader.IsNullOrEmpty(StateSet)) { result.Errors.Add(new ErrorMessage($"On Workflow Input {Name}, data type is a State Set, but no state set was provided.", true)); return; } } else { UnitSet = null; StateSet = null; } if (!result.Successful) { return; } /* If we made it here, we can assume that all nodes have been validated that they exist and they are part of the workflow */ foreach (var connection in OutgoingConnections) { switch (connection.NodeType) { case NodeType_Input: case NodeType_InputCommand: result.Errors.Add(new ErrorMessage($"Mapping from an Input to a node of type {connection.NodeType} is not supported", true)); break; case NodeType_Attribute: var attribute = workflow.Attributes.Where(stm => stm.Key == connection.NodeKey).First(); if (attribute.AttributeType.Value != InputType.Value) { result.Errors.Add(new ErrorMessage($"Invalid Mapping between {Name} and {connection.NodeName} - Source Type {InputType.Text} - Destination Type: {attribute.AttributeType.Text}.")); } else { if (attribute.AttributeType.Value == ParameterTypes.State && attribute.StateSet.Id != StateSet.Id) { result.Errors.Add(new ErrorMessage($"Invalid Mapping between {Name} and {connection.NodeName} - State Sets to do not match.")); } else if (attribute.AttributeType.Value == ParameterTypes.ValueWithUnit && attribute.UnitSet.Id != UnitSet.Id) { result.Errors.Add(new ErrorMessage($"Invalid Mapping between {Name} and {connection.NodeName} - Unit Sets to do not match.")); } } break; case NodeType_OutputCommand: break; case NodeType_StateMachine: if (EntityHeader.IsNullOrEmpty(connection.StateMachineEvent)) { result.Errors.Add(new ErrorMessage($"Transition Event is empty from {Name} to State Machine {connection.NodeName}.")); } else { var outputStateMachine = workflow.StateMachines.Where(stm => stm.Key == connection.NodeKey).First(); if (!outputStateMachine.Events.Where(evt => evt.Key == connection.StateMachineEvent.Id).Any()) { result.Errors.Add(new ErrorMessage($"Transition Event {connection.StateMachineEvent.Text} from {Name} to {outputStateMachine.Name} does not exist on that state machine.")); } } break; } } } }
public void Validate(DeviceWorkflow workflow, ValidationResult resutl) { if (Validator.Validate(this).Successful) { } }