using System; using System.Collections.Generic; using System.Linq; namespace MainShell.Motion { public sealed class MotionResult { public MotionResult(string axisName, MotionOperation operation, double? targetPosition, double startPosition, double endPosition, bool succeeded, bool cancelled, Exception exception, string message, bool alarmReported, DateTime startedAtUtc, DateTime finishedAtUtc, string correlationId = null, string batchId = null, string failureStage = null, bool timedOut = false, bool stoppedByCoordinator = false) { AxisName = axisName; Operation = operation; TargetPosition = targetPosition; StartPosition = startPosition; EndPosition = endPosition; Succeeded = succeeded; Cancelled = cancelled; Exception = exception; Message = message; AlarmReported = alarmReported; StartedAtUtc = startedAtUtc; FinishedAtUtc = finishedAtUtc; CorrelationId = correlationId; BatchId = batchId; FailureStage = failureStage; TimedOut = timedOut; StoppedByCoordinator = stoppedByCoordinator; } public string AxisName { get; } public MotionOperation Operation { get; } public double? TargetPosition { get; } public double StartPosition { get; } public double EndPosition { get; } public bool Succeeded { get; } public bool Cancelled { get; } public Exception Exception { get; } public string Message { get; } public bool AlarmReported { get; } public DateTime StartedAtUtc { get; } public DateTime FinishedAtUtc { get; } public string CorrelationId { get; } public string BatchId { get; } public string FailureStage { get; } public bool TimedOut { get; } public bool StoppedByCoordinator { get; } public long DurationMilliseconds => (long)(FinishedAtUtc - StartedAtUtc).TotalMilliseconds; public MotionResult WithAlarmReported(bool alarmReported) { if (AlarmReported == alarmReported) { return this; } return new MotionResult(AxisName, Operation, TargetPosition, StartPosition, EndPosition, Succeeded, Cancelled, Exception, Message, alarmReported, StartedAtUtc, FinishedAtUtc, CorrelationId, BatchId, FailureStage, TimedOut, StoppedByCoordinator); } public MotionResult WithFailureDetails(string failureStage, bool timedOut = false, bool stoppedByCoordinator = false, string correlationId = null, string batchId = null) { return new MotionResult(AxisName, Operation, TargetPosition, StartPosition, EndPosition, Succeeded, Cancelled, Exception, Message, AlarmReported, StartedAtUtc, FinishedAtUtc, correlationId ?? CorrelationId, batchId ?? BatchId, failureStage ?? FailureStage, timedOut, stoppedByCoordinator); } public void EnsureSuccess() { if (Succeeded) { return; } if (Exception != null) { throw Exception; } throw new InvalidOperationException(Message ?? string.Format("Motion failed. Axis: {0}", AxisName)); } } public sealed class MotionBatchResult { public MotionBatchResult(IEnumerable results) { Results = (results ?? Enumerable.Empty()).ToList().AsReadOnly(); } public IReadOnlyList Results { get; private set; } public bool Succeeded => Results.All(x => x != null && x.Succeeded); public bool Cancelled => Results.Any(x => x != null && x.Cancelled); public void EnsureSuccess() { var failedResults = Results.Where(x => x != null && !x.Succeeded).ToList(); if (failedResults.Count == 0) { return; } if (failedResults.Count == 1) { failedResults[0].EnsureSuccess(); return; } throw new AggregateException(failedResults.Select(CreateException)); } private static Exception CreateException(MotionResult result) { if (result == null) { return new InvalidOperationException("Motion result is null."); } return result.Exception ?? new InvalidOperationException(result.Message ?? string.Format("Motion failed. Axis: {0}", result.AxisName)); } } }