internal void Add(PropertyDescriptionRoute value, bool overwrite)
        {
            PropertyDescriptionRouteDictionary.EnsureValue(value);

            var key = PropertyRouteBuilder.ToPropertyRoute(value);

            this.Add(key, value, overwrite);
        }
        internal static PropertyRoute ToPropertyRoute(DataGridItemPropertyRoute itemProperty)
        {
            if (itemProperty == null)
            {
                return(null);
            }

            return(PropertyRoute.Combine(PropertyRouteBuilder.ToSegment(itemProperty.Current), PropertyRouteBuilder.ToPropertyRoute(itemProperty.Parent)));
        }
        internal static PropertyRoute ToPropertyRoute(PropertyDescriptionRoute description)
        {
            if (description == null)
            {
                return(null);
            }

            return(PropertyRoute.Combine(PropertyRouteBuilder.ToSegment(description.Current), PropertyRouteBuilder.ToPropertyRoute(description.Parent)));
        }
        internal void PushDescendant(DataGridItemPropertyBase itemProperty)
        {
            if (itemProperty == null)
            {
                throw new ArgumentNullException("itemProperty");
            }

            this.PushDescendant(PropertyRouteBuilder.ToSegment(itemProperty));
        }
        internal void PushDescendant(PropertyDescription description)
        {
            if (description == null)
            {
                throw new ArgumentNullException("description");
            }

            this.PushDescendant(PropertyRouteBuilder.ToSegment(description));
        }
        private static bool AddProperty(string path, int length, ref int index, PropertyRouteBuilder builder)
        {
            var currentIndex = index;

            while ((currentIndex < length) && (path[currentIndex] == '.'))
            {
                currentIndex++;
            }

            var startIndex = currentIndex;
            var parens     = 0;

            while (currentIndex < length)
            {
                var c = path[currentIndex];

                if (PropertyRouteParser.ReservedSymbols.IndexOf(c) >= 0)
                {
                    break;
                }

                if (c == '(')
                {
                    parens++;
                }
                else if (c == ')')
                {
                    parens--;

                    // A closing parenthesis was found before an opening parenthesis.
                    if (parens < 0)
                    {
                        return(false);
                    }
                }

                currentIndex++;
            }

            if ((parens != 0) || (startIndex >= length))
            {
                return(false);
            }

            var name = path.Substring(startIndex, currentIndex - startIndex).Trim();

            if (name.Length > 0)
            {
                builder.PushDescendant(new PropertyRouteSegment(PropertyRouteSegmentType.Property, name));
                index = currentIndex;
            }

            return(true);
        }
        private static void AddOther(string path, int length, ref int index, PropertyRouteBuilder builder)
        {
            if (index >= length)
            {
                return;
            }

            var value = path.Substring(index, length - index).Trim();

            builder.PushDescendant(new PropertyRouteSegment(PropertyRouteSegmentType.Other, value));
            index = length;
        }
        private static bool AddIndexer(string path, int length, ref int index, PropertyRouteBuilder builder)
        {
            if ((index >= length) || (path[index] != '['))
            {
                return(false);
            }

            var currentIndex = index + 1;
            var startIndex   = currentIndex;

            while (currentIndex < length)
            {
                var c = path[currentIndex];

                if (c == ']')
                {
                    Debug.Assert(startIndex < length);
                    Debug.Assert(startIndex <= currentIndex);

                    var value = path.Substring(startIndex, currentIndex - startIndex).Trim();
                    if (value.Length <= 0)
                    {
                        return(false);
                    }

                    // The value is parsed twice in order to get a standard name that could be used as a key for further use.
                    var parametersList = IndexerParametersParser.Parse(value);
                    var parameters     = IndexerParametersParser.Parse(parametersList);
                    if (string.IsNullOrEmpty(parameters))
                    {
                        return(false);
                    }

                    builder.PushDescendant(new PropertyRouteSegment(PropertyRouteSegmentType.Indexer, parameters));
                    index = currentIndex + 1;

                    return(true);
                }
                else if (PropertyRouteParser.ReservedSymbols.IndexOf(c) >= 0)
                {
                    return(false);
                }

                currentIndex++;
            }

            return(false);
        }
        internal static PropertyRoute Parse(string path)
        {
            path = (path != null) ? path.Trim() : string.Empty;

            var length = path.Length;

            if (length <= 0)
            {
                return(null);
            }

            var builder = new PropertyRouteBuilder();
            var state   = ParserState.Start;
            var index   = 0;

            while (index < length)
            {
                var c = path[index];

                if (char.IsWhiteSpace(c))
                {
                    index++;
                }
                else
                {
                    switch (state)
                    {
                    case ParserState.Start:
                    {
                        switch (c)
                        {
                        case '.':
                            index++;
                            break;

                        default:
                            state = ParserState.Property;
                            break;
                        }
                    }
                    break;

                    case ParserState.Separator:
                    {
                        switch (c)
                        {
                        case '.':
                            index++;
                            break;

                        case '[':
                            break;

                        default:
                        {
                            PropertyRouteParser.AddOther(path, length, ref index, builder);
                            Debug.Assert(index >= length);
                        }
                        break;
                        }

                        state = ParserState.Property;
                    }
                    break;

                    case ParserState.Property:
                    {
                        switch (c)
                        {
                        case '[':
                        {
                            if (PropertyRouteParser.AddIndexer(path, length, ref index, builder))
                            {
                                state = ParserState.Separator;
                            }
                            else
                            {
                                PropertyRouteParser.AddOther(path, length, ref index, builder);
                                Debug.Assert(index >= length);
                            }
                        }
                        break;

                        default:
                        {
                            if (PropertyRouteParser.AddProperty(path, length, ref index, builder))
                            {
                                state = ParserState.Separator;
                            }
                            else
                            {
                                PropertyRouteParser.AddOther(path, length, ref index, builder);
                                Debug.Assert(index >= length);
                            }
                        }
                        break;
                        }
                    }
                    break;

                    default:
                        throw new NotImplementedException();
                    }
                }
            }

            if (builder.IsEmpty)
            {
                builder.PushDescendant(PropertyRouteSegment.Self);
            }

            return(builder.ToPropertyRoute());
        }
 internal static string Parse(DataGridItemPropertyBase itemProperty)
 {
     return(PropertyRouteParser.Parse(PropertyRouteBuilder.ToPropertyRoute(DataGridItemPropertyRoute.Create(itemProperty))));
 }