using System; using MxGateway.Contracts.Proto; using MxGateway.Worker.Conversion; using MxGateway.Worker.Sta; namespace MxGateway.Worker.MxAccess; public sealed class MxAccessCommandExecutor : IStaCommandExecutor { private readonly MxAccessSession session; private readonly VariantConverter variantConverter; public MxAccessCommandExecutor(MxAccessSession session) : this(session, new VariantConverter()) { } public MxAccessCommandExecutor( MxAccessSession session, VariantConverter variantConverter) { this.session = session ?? throw new ArgumentNullException(nameof(session)); this.variantConverter = variantConverter ?? throw new ArgumentNullException(nameof(variantConverter)); } public MxCommandReply Execute(StaCommand command) { if (command is null) { throw new ArgumentNullException(nameof(command)); } return command.Kind switch { MxCommandKind.Register => ExecuteRegister(command), MxCommandKind.Unregister => ExecuteUnregister(command), MxCommandKind.AddItem => ExecuteAddItem(command), MxCommandKind.AddItem2 => ExecuteAddItem2(command), MxCommandKind.RemoveItem => ExecuteRemoveItem(command), MxCommandKind.Advise => ExecuteAdvise(command), MxCommandKind.UnAdvise => ExecuteUnAdvise(command), MxCommandKind.AdviseSupervisory => ExecuteAdviseSupervisory(command), _ => CreateInvalidRequestReply(command, $"Unsupported MXAccess command kind {command.Kind}."), }; } private MxCommandReply ExecuteRegister(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.Register) { return CreateInvalidRequestReply(command, "Register command payload is required."); } int serverHandle = session.Register(command.Command.Register.ClientName); MxCommandReply reply = CreateOkReply(command); reply.ReturnValue = variantConverter.Convert(serverHandle); reply.Register = new RegisterReply { ServerHandle = serverHandle, }; return reply; } private MxCommandReply ExecuteUnregister(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.Unregister) { return CreateInvalidRequestReply(command, "Unregister command payload is required."); } session.Unregister(command.Command.Unregister.ServerHandle); return CreateOkReply(command); } private MxCommandReply ExecuteAddItem(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.AddItem) { return CreateInvalidRequestReply(command, "AddItem command payload is required."); } AddItemCommand addItemCommand = command.Command.AddItem; int itemHandle = session.AddItem( addItemCommand.ServerHandle, addItemCommand.ItemDefinition); MxCommandReply reply = CreateOkReply(command); reply.ReturnValue = variantConverter.Convert(itemHandle); reply.AddItem = new AddItemReply { ItemHandle = itemHandle, }; return reply; } private MxCommandReply ExecuteAddItem2(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.AddItem2) { return CreateInvalidRequestReply(command, "AddItem2 command payload is required."); } AddItem2Command addItem2Command = command.Command.AddItem2; int itemHandle = session.AddItem2( addItem2Command.ServerHandle, addItem2Command.ItemDefinition, addItem2Command.ItemContext); MxCommandReply reply = CreateOkReply(command); reply.ReturnValue = variantConverter.Convert(itemHandle); reply.AddItem2 = new AddItem2Reply { ItemHandle = itemHandle, }; return reply; } private MxCommandReply ExecuteRemoveItem(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.RemoveItem) { return CreateInvalidRequestReply(command, "RemoveItem command payload is required."); } RemoveItemCommand removeItemCommand = command.Command.RemoveItem; session.RemoveItem( removeItemCommand.ServerHandle, removeItemCommand.ItemHandle); return CreateOkReply(command); } private MxCommandReply ExecuteAdvise(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.Advise) { return CreateInvalidRequestReply(command, "Advise command payload is required."); } AdviseCommand adviseCommand = command.Command.Advise; session.Advise( adviseCommand.ServerHandle, adviseCommand.ItemHandle); return CreateOkReply(command); } private MxCommandReply ExecuteUnAdvise(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.UnAdvise) { return CreateInvalidRequestReply(command, "UnAdvise command payload is required."); } UnAdviseCommand unAdviseCommand = command.Command.UnAdvise; session.UnAdvise( unAdviseCommand.ServerHandle, unAdviseCommand.ItemHandle); return CreateOkReply(command); } private MxCommandReply ExecuteAdviseSupervisory(StaCommand command) { if (command.Command.PayloadCase != MxCommand.PayloadOneofCase.AdviseSupervisory) { return CreateInvalidRequestReply(command, "AdviseSupervisory command payload is required."); } AdviseSupervisoryCommand adviseSupervisoryCommand = command.Command.AdviseSupervisory; session.AdviseSupervisory( adviseSupervisoryCommand.ServerHandle, adviseSupervisoryCommand.ItemHandle); return CreateOkReply(command); } private static MxCommandReply CreateOkReply(StaCommand command) { return new MxCommandReply { SessionId = command.SessionId, CorrelationId = command.CorrelationId, Kind = command.Kind, Hresult = 0, ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.Ok, Message = "OK", }, }; } private static MxCommandReply CreateInvalidRequestReply( StaCommand command, string message) { return new MxCommandReply { SessionId = command.SessionId, CorrelationId = command.CorrelationId, Kind = command.Kind, ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.InvalidRequest, Message = message, }, DiagnosticMessage = message, }; } }