/// <summary>
        /// Parse and return a dependency version
        /// The version string is either a simple version or an arithmetic range
        /// e.g.
        ///      1.0         --> 1.0 ≤ x
        ///      (,1.0]      --> x ≤ 1.0
        ///      (,1.0)      --> x lt 1.0
        ///      [1.0]       --> x == 1.0
        ///      (1.0,)      --> 1.0 lt x
        ///      (1.0, 2.0)   --> 1.0 lt x lt 2.0
        ///      [1.0, 2.0]   --> 1.0 ≤ x ≤ 2.0
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DependencyVersion ParseDependencyVersion(string value)
        {
            var depVers = new DependencyVersion();

            if (String.IsNullOrWhiteSpace(value))
            {
                return depVers;
            }

            value = value.Trim();

            char first = value.First();
            char last = value.Last();

            if (first != '(' && first != '[' && last != ']' && last != ')')
            {
                // Stand alone version
                depVers.IsMinInclusive = true;
                depVers.MinVersion = new SemanticVersion(value);
                return depVers;
            }

            // value must have length greater than 3
            if (value.Length < 3)
            {
                return depVers;
            }

            // The first character must be [ or (
            switch (value.First())
            {
                case '[':
                    depVers.IsMinInclusive = true;
                    break;
                case '(':
                    depVers.IsMinInclusive = false;
                    break;
                default:
                    // If not, return without setting anything
                    return depVers;
            }

            // The last character must be ] or )
            switch (value.Last())
            {
                case ']':
                    depVers.IsMaxInclusive = true;
                    break;
                case ')':
                    depVers.IsMaxInclusive = false;
                    break;
                default:
                    // If not, return without setting anything
                    return depVers;
            }

            // Get rid of the two brackets
            value = value.Substring(1, value.Length - 2);

            // Split by comma, and make sure we don't get more than two pieces
            string[] parts = value.Split(',');

            // Wrong format if we have more than 2 parts or all the parts are empty
            if (parts.Length > 2 || parts.All(String.IsNullOrEmpty))
            {
                return depVers;
            }

            // First part is min
            string minVersionString = parts[0];

            // If there is only 1 part then first part will also be max
            string maxVersionString = (parts.Length == 2) ? parts[1] : parts[0];

            // Get min version if we have it
            if (!String.IsNullOrWhiteSpace(minVersionString))
            {
                depVers.MinVersion = new SemanticVersion(minVersionString);
            }

            // Get max version if we have it
            if (!String.IsNullOrWhiteSpace(maxVersionString))
            {
                depVers.MaxVersion = new SemanticVersion(maxVersionString);
            }

            return depVers;
        }
        /// <summary>
        /// Parses a dependency from the feed in the format:
        /// id or id:versionSpec, or id:versionSpec:targetFramework
        /// </summary>
        private static Tuple<string, DependencyVersion, string> ParseDependency(string value)
        {
            if (String.IsNullOrWhiteSpace(value))
            {
                return null;
            }

            // IMPORTANT: Do not pass StringSplitOptions.RemoveEmptyEntries to this method, because it will break 
            // if the version spec is null, for in that case, the Dependencies string sent down is "<id>::<target framework>".
            // We do want to preserve the second empty element after the split.
            string[] tokens = value.Trim().Split(new[] { ':' });

            if (tokens.Length == 0)
            {
                return null;
            }

            // Trim the id
            string id = tokens[0].Trim();

            // Parse the dependency version
            DependencyVersion depVer = new DependencyVersion();
            if (tokens.Length > 1)
            {
                // Parse the version
                depVer = DependencyVersion.ParseDependencyVersion(tokens[1]);
            }

            // Get the target framework, returns empty string if none exists.
            var targetFramework = (tokens.Length > 2 && !String.IsNullOrEmpty(tokens[2])) ? tokens[2] : String.Empty;

            return Tuple.Create(id, depVer, targetFramework);
        }