/// <summary>
        /// Creates violation message for related object collection.
        /// </summary>
        /// <param name="obj">Violation's object (can be any DataObject: Vehicle, Driver and etc).</param>
        /// <param name="relatedObjects">Related object's.</param>
        /// <param name="resourceStringName">Description message format resource name.</param>
        /// <returns>Created message detail.</returns>
        private static MessageDetail _GetRouteViolationMessageStr(DataObject obj, ICollection <DataObject> relatedObjects,
                                                                  string resourceStringName)
        {
            Debug.Assert(obj is Route);

            int paramCount = 1 + relatedObjects.Count; // route + all objects

            DataObject[] param = new DataObject[paramCount];

            int    index        = 0;
            string substitution = "{" + index.ToString() + "}";

            param[index++] = obj;
            string relatedObjFormat = ViolationsHelper.GetObjectListFormat(relatedObjects, ref index, param);
            string format           = App.Current.GetString(resourceStringName, substitution, relatedObjFormat);

            return(new MessageDetail(MessageType.Error, format, param));
        }
        /// <summary>
        /// Creates violation message for related object collection.
        /// </summary>
        /// <param name="obj">Violation's object (can be any DataObject: Vehicle, Driver and etc).</param>
        /// <param name="inputCollectionCount">Collection's object count.</param>
        /// <param name="violatedObjCollection">Violated object collection.</param>
        /// <param name="formatSingle">Description message format for single object.</param>
        /// <param name="formatList">Description message format for object's name list.</param>
        /// <param name="formatAll">Description message format for all object's.</param>
        /// <returns>Created message detail.</returns>
        private static MessageDetail _GetViolationMessageStr <T>(DataObject obj, int inputCollectionCount,
                                                                 ICollection <T> violatedObjCollection,
                                                                 string formatSingle, string formatList,
                                                                 string formatAll)
            where T : DataObject
        {
            bool checkOneRoute = (1 == violatedObjCollection.Count);
            bool checkNotAll   = checkOneRoute ? false : (violatedObjCollection.Count < inputCollectionCount);

            int paramCount = 1;

            if (checkOneRoute)
            {
                ++paramCount;
            }
            else if (checkNotAll)
            {
                paramCount += violatedObjCollection.Count;
            }
            DataObject[] param = new DataObject[paramCount];

            string format = null;
            int    index  = 0;

            if (checkOneRoute)
            {
                param[index++] = violatedObjCollection.First();
                format         = formatSingle;
            }
            else if (checkNotAll)
            {
                string listFormat   = ViolationsHelper.GetObjectListFormat(violatedObjCollection, ref index, param);
                string substitution = "{" + index.ToString() + "}";
                format = string.Format(formatList, listFormat, substitution);
            }
            else
            {
                format = formatAll;
            }
            param[index++] = obj;

            return(new MessageDetail(MessageType.Warning, format, param));
        }
        private static List <MessageDetail> _CheckDriverSpecialties(ICollection <Route> routes, ICollection <Order> orders)
        {
            List <MessageDetail> details = new List <MessageDetail>();

            bool checkOneRoute = (1 == routes.Count);

            string format = App.Current.FindString((checkOneRoute)? "ConstraintsCheckerDriverSpecRouteMessageFmt" :
                                                   "ConstraintsCheckerDriverSpecRoutesMessageFmt");

            foreach (Order order in orders)
            {
                ICollection <DriverSpecialty> specialties = (checkOneRoute)?
                                                            _CanAccommodateOrderSpecialties(routes.First().Driver.Specialties, order.DriverSpecialties) :
                                                            _CanAccommodateOrderDriverSpecialties(routes, order);;
                if (null != specialties)
                {
                    int paramCount = 1 + specialties.Count;
                    if (checkOneRoute)
                    {
                        ++paramCount;
                    }
                    AppData.DataObject[] param = new AppData.DataObject[paramCount];

                    int index = 0;
                    if (checkOneRoute)
                    {
                        param[index++] = routes.First().Driver;
                    }
                    param[index++] = order;

                    string specialtiesFormat = ViolationsHelper.GetObjectListFormat(specialties, ref index, param);
                    string messageFormat     = (checkOneRoute) ? string.Format(format, "{0}", "{1}", specialtiesFormat) :
                                               string.Format(format, "{0}", specialtiesFormat);
                    details.Add(new MessageDetail(MessageType.Warning, messageFormat, param));
                }
            }

            return(details);
        }