/// <summary>
        /// Checks whether a version is valid.
        /// </summary>
        /// <param name="vers">The version to validate</param>
        /// <returns>True if <c>vers</c> is valid, false otherwise</returns>
        public bool Validate(ApiVersionInfo vers)
        {
            int maxMajor = this.FirstMajorVersion + (this.NumMajorVersions - 1);

            // first, check the major version is valid
            if (vers.MajorVersion < this.FirstMajorVersion || vers.MajorVersion > maxMajor)
            {
                return(false);
            }

            // next, check the minor version number
            if (vers.MinorVersion < this.ValidVersions[vers.MajorVersion].Min ||
                vers.MinorVersion > this.ValidVersions[vers.MajorVersion].Max)
            {
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseVersionRangeAttribute"/> class.
        /// </summary>
        /// <param name="serviceVersionInfo">service version info</param>
        /// <param name="versionRange">attribute string for the version range</param>
        public BaseVersionRangeAttribute(IServiceVersionInfo serviceVersionInfo, string versionRange)
        {
            this.versionRange = versionRange;

            // first, parse the version range string to make sure it has the correct format
            bool result = this.ParseVersionRange(serviceVersionInfo, this.versionRange);

            // if versionRange parses OK, then check that the range numbers are compatible with the service version info
            if (result)
            {
                this.outOfRange = !this.IsRangeValid(serviceVersionInfo);
            }

            if (this.outOfRange || this.parseError)
            {
                this.minVersion = new ApiVersionInfo(0, 0);
                this.maxVersion = new ApiVersionInfo(0, 0);
            }
        }
        /// <summary>
        /// Enumerates all the valid versions in the range from start to end
        /// </summary>
        /// <param name="start">the starting version of the range</param>
        /// <param name="end">the ending version of the range</param>
        /// <returns>a list of all valid versions in the range from start to end</returns>
        public List <string> EnumerateVersions(ApiVersionInfo start, ApiVersionInfo end)
        {
            List <string> versionList = null;

            // first, check that the start and end paramenters are valid versions
            if (this.Validate(start) == false || this.Validate(end) == false)
            {
                return(null);
            }

            int startMajor = start.MajorVersion;

            for (int i = start.MajorVersion; i <= end.MajorVersion; i++)
            {
                int minorStart = this.ValidVersions[i].Min;
                int minorEnd   = this.ValidVersions[i].Max;

                if (i == start.MajorVersion)
                {
                    minorStart = start.MinorVersion;
                }

                if (i == end.MajorVersion)
                {
                    minorEnd = end.MinorVersion;
                }

                for (int j = minorStart; j <= minorEnd; j++)
                {
                    string version = new ApiVersionInfo(i, j).ToString();
                    if (versionList == null)
                    {
                        versionList = new List <string>();
                    }

                    versionList.Add(version);
                }
            }

            return(versionList);
        }
        /// <summary>
        /// Performs the work of parsing the version range string.
        /// </summary>
        /// <param name="serviceVersionInfo">service version info</param>
        /// <param name="versionRange">the version range string</param>
        /// <returns>true if the version string parses successfully</returns>
        private bool ParseVersionRange(IServiceVersionInfo serviceVersionInfo, string versionRange)
        {
            string versionPattern = @"(All)|(Min)|(Cur)|[vV](\d+).(\d+)";
            string firstVersion = null, secondVersion = null;
            int    separatorPosition = versionRange.IndexOf('-');

            if (separatorPosition >= 0)
            {
                firstVersion = versionRange.Substring(0, separatorPosition);
                var match = Regex.Match(firstVersion, versionPattern);
                if (match.Success)
                {
                    bool isAll = match.Groups[1].Value.Equals(All);
                    bool isMin = match.Groups[2].Value.Equals(Min);
                    bool isCur = match.Groups[3].Value.Equals(Cur);
                    if (isAll)
                    {
                        // cannot have a version range that begins with All and a hypen that follows
                        this.parseError = true;
                        return(false);
                    }
                    else if (isMin)
                    {
                        this.minVersion = serviceVersionInfo.GetMinVersion();
                    }
                    else if (isCur)
                    {
                        this.minVersion = serviceVersionInfo.GetMaxVersion();
                    }
                    else
                    {
                        int major = int.Parse(match.Groups[4].Value);
                        int minor = int.Parse(match.Groups[5].Value);
                        if (major < 0 || minor < 0)
                        {
                            this.parseError = true;
                            return(false);
                        }

                        this.minVersion = new ApiVersionInfo(major, minor);
                    }
                }
                else
                {
                    this.parseError = true;
                    return(false);
                }

                secondVersion = versionRange.Substring(separatorPosition + 1);
                match         = Regex.Match(secondVersion, versionPattern);
                if (match.Success)
                {
                    bool isAll = match.Groups[1].Value.Equals(All);
                    bool isMin = match.Groups[2].Value.Equals(Min);
                    bool isCur = match.Groups[3].Value.Equals(Cur);
                    if (isAll)
                    {
                        // cannot have a version range that has a hypen and then All
                        this.parseError = true;
                        return(false);
                    }
                    else if (isMin)
                    {
                        // cannot have a version range that has a hypen and then Min
                        this.parseError = true;
                        return(false);
                    }
                    else if (isCur)
                    {
                        this.maxVersion = serviceVersionInfo.GetMaxVersion();
                    }
                    else
                    {
                        int major = int.Parse(match.Groups[4].Value);
                        int minor = int.Parse(match.Groups[5].Value);
                        if (major < 0 || minor < 0)
                        {
                            this.parseError = true;
                            return(false);
                        }

                        this.maxVersion = new ApiVersionInfo(major, minor);
                    }
                }
                else
                {
                    this.parseError = true;
                    return(false);
                }
            }
            else
            {
                firstVersion = versionRange;
                var match = Regex.Match(firstVersion, versionPattern);
                if (match.Success)
                {
                    bool isAll = match.Groups[1].Value.Equals(All);
                    bool isMin = match.Groups[2].Value.Equals(Min);
                    bool isCur = match.Groups[3].Value.Equals(Cur);
                    if (isAll)
                    {
                        this.minVersion = serviceVersionInfo.GetMinVersion();
                        this.maxVersion = serviceVersionInfo.GetMaxVersion();
                    }
                    else if (isMin)
                    {
                        this.minVersion = serviceVersionInfo.GetMinVersion();
                        this.maxVersion = serviceVersionInfo.GetMinVersion();
                    }
                    else if (isCur)
                    {
                        this.minVersion = serviceVersionInfo.GetMaxVersion();
                        this.maxVersion = serviceVersionInfo.GetMaxVersion();
                    }
                    else
                    {
                        int major = int.Parse(match.Groups[4].Value);
                        int minor = int.Parse(match.Groups[5].Value);
                        if (major < 0 || minor < 0)
                        {
                            this.parseError = true;
                            return(false);
                        }

                        this.minVersion = new ApiVersionInfo(major, minor);
                        this.maxVersion = new ApiVersionInfo(major, minor);
                    }
                }
                else
                {
                    this.parseError = true;
                    return(false);
                }
            }

            return(true);
        }