/// <summary>
        /// Method returns collection of violation message details.
        /// </summary>
        /// <param name="schedule">Schedule to be checked.</param>
        /// <param name="info">Solver's asyncrone operation info.</param>
        /// <param name="violations">Founded violations.</param>
        /// <returns>Message detail with description for violations.</returns>
        public static ICollection <MessageDetail> GetViolationDetails(Schedule schedule,
                                                                      AsyncOperationInfo info,
                                                                      ICollection <Violation> violations)
        {
            Debug.Assert(null != schedule);
            Debug.Assert(0 < violations.Count);

            // special case
            bool  isSpecialCase = false;
            Order orderToAssign = null;

            if (SolveOperationType.AssignOrders == info.OperationType)
            {
                AssignOrdersParams param = (AssignOrdersParams)info.InputParams;
                if (null != param.TargetSequence)
                {
                    isSpecialCase = param.TargetSequence.HasValue;
                }

                if (isSpecialCase)
                {
                    Debug.Assert(1 == param.OrdersToAssign.Count);
                    orderToAssign = param.OrdersToAssign.First();
                }
            }

            ICollection <MessageDetail> details = null;

            if (!isSpecialCase && _IsRouteRelatedViolationPresent(violations))
            {
                details = _GetRouteViolationDetails(violations);
            }
            else
            {
                ICollection <Route> routes = ViolationsHelper.GetRoutingCommandRoutes(schedule, info);
                Debug.Assert((null != routes) && (0 < routes.Count));

                details = _GetViolationDetails(routes, isSpecialCase, orderToAssign, violations);
            }

            return(details);
        }