예제 #1
0
        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;
                    }
                }
            }
        }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
 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}.");
         }
     }
 }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        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;
                    }
                }
            }
        }
예제 #8
0
 public void Validate(DeviceWorkflow workflow, ValidationResult resutl)
 {
     if (Validator.Validate(this).Successful)
     {
     }
 }