Example #1
0
        public void ArrayItems_FilteringByIndexAndValue_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("key1"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenProperty("key2"),
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenPrimitive(Math.PI),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenFalse
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(Math.PI),
                }
            };

            // select all even index primitive items
            var actual = input.ArrayItems(index => (index % 2 == 0)).Where(item => item.IsPrimitive()).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #2
0
        private void GetArrayTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, IEnumerable value)
        {
            DataName    typeName   = this.GetTypeName(value);
            IEnumerator enumerator = value.GetEnumerator();

            if (enumerator is IEnumerator <KeyValuePair <string, object> > )
            {
                this.GetObjectTokens(tokens, detector, typeName, (IEnumerator <KeyValuePair <string, object> >)enumerator);
                return;
            }

            if (enumerator is IDictionaryEnumerator)
            {
                this.GetObjectTokens(tokens, detector, typeName, (IDictionaryEnumerator)enumerator);
                return;
            }

            tokens.Add(ModelGrammar.TokenArrayBegin(typeName));

            while (enumerator.MoveNext())
            {
                this.GetTokens(tokens, detector, enumerator.Current);
            }

            tokens.Add(ModelGrammar.TokenArrayEnd);
        }
Example #3
0
        public void ArrayItems_IndexFilter_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenPrimitive("Pick me!"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("key1"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenProperty("key2"),
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenPrimitive("Pick me!")
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(42)
                }
            };

            // select items with odd indexes
            var actual = input.ArrayItems(index => (index % 2 == 1)).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #4
0
        public void ObjectProperties_NestedArrayPropertyReturned_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("key1"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenProperty("key2"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenProperty("three"),
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenProperty("4"),
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenObjectEnd
            };

            var expected = new Dictionary <DataName, IEnumerable <Token <ModelTokenType> > >
            {
                { new DataName("key2"), new[] {
                      ModelGrammar.TokenArrayBeginUnnamed,
                      ModelGrammar.TokenFalse,
                      ModelGrammar.TokenPrimitive(42),
                      ModelGrammar.TokenArrayEnd,
                  } }
            };

            // select all properties
            var actual = input.Properties(name => name.LocalName == "key2").ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #5
0
        public void IsPrimitive_StringPrimitive_ReturnsTrue()
        {
            var input = new[]
            {
                ModelGrammar.TokenPrimitive("Hello.")
            };

            Assert.True(input.IsPrimitive());
        }
Example #6
0
        public void IsArray_StringPrimitive_ReturnsFalse()
        {
            var input = new[]
            {
                ModelGrammar.TokenPrimitive("Hello.")
            };

            Assert.False(input.IsArray());
        }
Example #7
0
        private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IDictionaryEnumerator enumerator)
        {
            tokens.Add(ModelGrammar.TokenObjectBegin(typeName));

            while (enumerator.MoveNext())
            {
                tokens.Add(ModelGrammar.TokenProperty(enumerator.Key));
                this.GetTokens(tokens, detector, enumerator.Value);
            }

            tokens.Add(ModelGrammar.TokenObjectEnd);
        }
Example #8
0
        private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IEnumerator <KeyValuePair <string, object> > enumerator)
        {
            tokens.Add(ModelGrammar.TokenObjectBegin(typeName));

            while (enumerator.MoveNext())
            {
                KeyValuePair <string, object> pair = enumerator.Current;
                tokens.Add(ModelGrammar.TokenProperty(pair.Key));
                this.GetTokens(tokens, detector, pair.Value);
            }

            tokens.Add(ModelGrammar.TokenObjectEnd);
        }
Example #9
0
        public void Descendants_NestedObjectsFindDescendantsWithProperty_ReturnsMatchingSubsequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("One"),
                ModelGrammar.TokenNull,

                ModelGrammar.TokenProperty("Two"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenPrimitive("2-B"),
                ModelGrammar.TokenPrimitive(23),
                ModelGrammar.TokenArrayEnd,

                ModelGrammar.TokenProperty("Three"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("A"),
                ModelGrammar.TokenPrimitive("3-A"),
                ModelGrammar.TokenProperty("B"),
                ModelGrammar.TokenPrimitive(32),
                ModelGrammar.TokenProperty("C"),
                ModelGrammar.TokenPrimitive("3-C"),
                ModelGrammar.TokenObjectEnd,

                ModelGrammar.TokenProperty("Four"),
                ModelGrammar.TokenPrimitive(4),
                ModelGrammar.TokenObjectEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenObjectBeginUnnamed,
                    ModelGrammar.TokenProperty("A"),
                    ModelGrammar.TokenPrimitive("3-A"),
                    ModelGrammar.TokenProperty("B"),
                    ModelGrammar.TokenPrimitive(32),
                    ModelGrammar.TokenProperty("C"),
                    ModelGrammar.TokenPrimitive("3-C"),
                    ModelGrammar.TokenObjectEnd
                }
            };

            // select all descendants with property named "B"
            var actual = input.Descendants().Where(child => child.HasProperty(name => name.LocalName == "B")).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #10
0
        public void ArrayItems_NestedArray_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenNull,
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenFalse
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive("Hello!")
                },
                new[]
                {
                    ModelGrammar.TokenArrayBeginUnnamed,
                    ModelGrammar.TokenFalse,
                    ModelGrammar.TokenNull,
                    ModelGrammar.TokenTrue,
                    ModelGrammar.TokenPrimitive("Hello!"),
                    ModelGrammar.TokenPrimitive(42),
                    ModelGrammar.TokenArrayEnd,
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(42)
                },
            };

            // select all items
            var actual = input.ArrayItems(index => true).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #11
0
        private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, System.Dynamic.DynamicObject value)
        {
            DataName typeName = this.GetTypeName(value);

            tokens.Add(ModelGrammar.TokenObjectBegin(typeName));

            foreach (var memberName in value.GetDynamicMemberNames())
            {
                object propertyValue;
                if (!value.TryGetMember(new DynamicGetter(memberName), out propertyValue))
                {
                    continue;
                }

                tokens.Add(ModelGrammar.TokenProperty(memberName));
                this.GetTokens(tokens, detector, propertyValue);
            }

            tokens.Add(ModelGrammar.TokenObjectEnd);
        }
Example #12
0
        public void ArrayItems_MixedPrimitivesFilterAll_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenNull,
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new IEnumerable <Token <ModelTokenType> > [0];

            // select no items
            var actual = input.ArrayItems(index => false).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #13
0
        public void HasProperty_PickNonExisting_ReturnsFalse()
        {
            var input = new[]
            {
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("key1"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenProperty("key2"),
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenProperty("three"),
                ModelGrammar.TokenPrimitive(3),
                ModelGrammar.TokenProperty("4"),
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenObjectEnd
            };

            // test for a specific property
            var actual = input.HasProperty(name => name.LocalName == "five");

            Assert.False(actual);
        }
Example #14
0
        private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, object value)
        {
            DataName typeName = this.GetTypeName(value);

            tokens.Add(ModelGrammar.TokenObjectBegin(typeName));

            IDictionary <string, MemberMap> maps = this.Settings.Resolver.LoadMaps(type);

            if (maps == null)
            {
                // TODO: verify no other valid situations here
                tokens.Add(ModelGrammar.TokenObjectEnd);
                return;
            }

            // allow the resolver to optionally sort the members
            IEnumerable <MemberMap> members = this.Settings.Resolver.SortMembers(maps.Values);

            foreach (var map in members)
            {
                if (map.IsAlternate ||
                    map.Getter == null)
                {
                    continue;
                }

                object propertyValue = map.Getter(value);
                if (map.IsIgnored != null &&
                    map.IsIgnored(value, propertyValue))
                {
                    continue;
                }

                tokens.Add(ModelGrammar.TokenProperty(map.DataName));
                this.GetTokens(tokens, detector, propertyValue);
            }

            tokens.Add(ModelGrammar.TokenObjectEnd);
        }
Example #15
0
        public void ArrayItems_MixedPrimitivesFilterNonNull_ReturnsSplitSequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenNull,
                ModelGrammar.TokenPrimitive("Hello!"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenPrimitive(42),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenFalse
                },
                new[]
                {
                    ModelGrammar.TokenTrue
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive("Hello!")
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(42)
                },
            };

            // select all items with a non-null value
            var actual = input.ArrayItems().Where(item => item.All(token => token.Value != null)).ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #16
0
        private void GetTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, object value)
        {
            if (value == null)
            {
                tokens.Add(ModelGrammar.TokenNull);
                return;
            }

            // test for cycles
            if (detector.Add(value))
            {
                switch (this.Settings.GraphCycles)
                {
                case GraphCycleType.Reference:
                {
                    // no need to remove value as was duplicate reference
                    throw new GraphCycleException(GraphCycleType.Reference, "Graph cycle detected: repeated references");
                }

                case GraphCycleType.MaxDepth:
                {
                    throw new GraphCycleException(GraphCycleType.MaxDepth, "Graph cycle potentially detected: maximum depth exceeded");
                }

                default:
                case GraphCycleType.Ignore:
                {
                    // no need to remove value as was duplicate reference
                    // replace cycle with null
                    tokens.Add(ModelGrammar.TokenNull);
                    return;
                }
                }
            }

            try
            {
                foreach (var filter in this.Filters)
                {
                    IEnumerable <Token <ModelTokenType> > filterResult;
                    if (filter.TryWrite(this.Settings, value, out filterResult))
                    {
                        // found a successful match
                        tokens.AddRange(filterResult);
                        return;
                    }
                }

                Type type = value.GetType();

                // must test enumerations before other value types
                if (type.IsEnum)
                {
                    tokens.Add(ModelGrammar.TokenPrimitive((Enum)value));
                    return;
                }

                // Type.GetTypeCode() allows us to more efficiently switch type
                switch (Type.GetTypeCode(type))
                {
                case TypeCode.Boolean:
                {
                    tokens.Add(true.Equals(value) ? ModelGrammar.TokenTrue : ModelGrammar.TokenFalse);
                    return;
                }

                case TypeCode.Byte:
                case TypeCode.Decimal:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                {
                    tokens.Add(ModelGrammar.TokenPrimitive((ValueType)value));
                    return;
                }

                case TypeCode.Double:
                {
                    double doubleVal = (double)value;

                    if (Double.IsNaN(doubleVal))
                    {
                        tokens.Add(ModelGrammar.TokenNaN);
                    }
                    else if (Double.IsPositiveInfinity(doubleVal))
                    {
                        tokens.Add(ModelGrammar.TokenPositiveInfinity);
                    }
                    else if (Double.IsNegativeInfinity(doubleVal))
                    {
                        tokens.Add(ModelGrammar.TokenNegativeInfinity);
                    }
                    else
                    {
                        tokens.Add(ModelGrammar.TokenPrimitive(doubleVal));
                    }
                    return;
                }

                case TypeCode.Single:
                {
                    float floatVal = (float)value;

                    if (Single.IsNaN(floatVal))
                    {
                        // use the Double equivalent
                        tokens.Add(ModelGrammar.TokenNaN);
                    }
                    else if (Single.IsPositiveInfinity(floatVal))
                    {
                        // use the Double equivalent
                        tokens.Add(ModelGrammar.TokenPositiveInfinity);
                    }
                    else if (Single.IsNegativeInfinity(floatVal))
                    {
                        // use the Double equivalent
                        tokens.Add(ModelGrammar.TokenNegativeInfinity);
                    }
                    else
                    {
                        tokens.Add(ModelGrammar.TokenPrimitive(floatVal));
                    }
                    return;
                }

                case TypeCode.Char:
                case TypeCode.DateTime:
                case TypeCode.String:
                {
                    tokens.Add(ModelGrammar.TokenPrimitive(value));
                    return;
                }

                case TypeCode.DBNull:
                case TypeCode.Empty:
                {
                    tokens.Add(ModelGrammar.TokenNull);
                    return;
                }
                }

                if (value is IEnumerable)
                {
                    this.GetArrayTokens(tokens, detector, (IEnumerable)value);
                    return;
                }

                if (value is Guid || value is Uri || value is Version)
                {
                    tokens.Add(ModelGrammar.TokenPrimitive(value));
                    return;
                }

                if (value is TimeSpan)
                {
                    tokens.Add(ModelGrammar.TokenPrimitive((TimeSpan)value));
                    return;
                }

#if NET40 && !WINDOWS_PHONE
                if (value is System.Dynamic.DynamicObject)
                {
                    // TODO: expand to all IDynamicMetaObjectProvider?
                    this.GetObjectTokens(tokens, detector, type, (System.Dynamic.DynamicObject)value);
                    return;
                }
#endif

                // all other structs and classes
                this.GetObjectTokens(tokens, detector, type, value);
            }
            finally
            {
                detector.Remove(value);
            }
        }
Example #17
0
        public void Descendants_NestedObjects_ReturnsAllSubsequences()
        {
            var input = new[]
            {
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("One"),
                ModelGrammar.TokenNull,

                ModelGrammar.TokenProperty("Two"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenPrimitive("2-B"),
                ModelGrammar.TokenPrimitive(23),
                ModelGrammar.TokenArrayEnd,

                ModelGrammar.TokenProperty("Three"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("A"),
                ModelGrammar.TokenPrimitive("3-A"),
                ModelGrammar.TokenProperty("B"),
                ModelGrammar.TokenPrimitive(32),
                ModelGrammar.TokenProperty("C"),
                ModelGrammar.TokenPrimitive("3-C"),
                ModelGrammar.TokenObjectEnd,

                ModelGrammar.TokenProperty("Four"),
                ModelGrammar.TokenPrimitive(4),
                ModelGrammar.TokenObjectEnd
            };

            var expected = new[]
            {
                new[]
                {
                    ModelGrammar.TokenNull
                },
                new[]
                {
                    ModelGrammar.TokenArrayBeginUnnamed,
                    ModelGrammar.TokenTrue,
                    ModelGrammar.TokenPrimitive("2-B"),
                    ModelGrammar.TokenPrimitive(23),
                    ModelGrammar.TokenArrayEnd
                },
                new[]
                {
                    ModelGrammar.TokenTrue
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive("2-B")
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(23)
                },
                new[]
                {
                    ModelGrammar.TokenObjectBeginUnnamed,
                    ModelGrammar.TokenProperty("A"),
                    ModelGrammar.TokenPrimitive("3-A"),
                    ModelGrammar.TokenProperty("B"),
                    ModelGrammar.TokenPrimitive(32),
                    ModelGrammar.TokenProperty("C"),
                    ModelGrammar.TokenPrimitive("3-C"),
                    ModelGrammar.TokenObjectEnd
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive("3-A")
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(32)
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive("3-C")
                },
                new[]
                {
                    ModelGrammar.TokenPrimitive(4),
                }
            };

            // select all descendants
            var actual = input.Descendants().ToArray();

            Assert.Equal(expected, actual, false);
        }
Example #18
0
        public void Properties_GraphComplex_ReturnsGraph()
        {
            // input from pass1.json in test suite at http://www.json.org/JSON_checker/
            var input = new[]
            {
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenPrimitive("JSON Test Pattern pass1"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("object with 1 member"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenPrimitive("array with 1 element"),
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenPrimitive(-42),
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenNull,
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenProperty("integer"),
                ModelGrammar.TokenPrimitive(1234567890),
                ModelGrammar.TokenProperty("real"),
                ModelGrammar.TokenPrimitive(-9876.543210),
                ModelGrammar.TokenProperty("e"),
                ModelGrammar.TokenPrimitive(0.123456789e-12),
                ModelGrammar.TokenProperty("E"),
                ModelGrammar.TokenPrimitive(1.234567890E+34),
                ModelGrammar.TokenProperty(""),
                ModelGrammar.TokenPrimitive(23456789012E66),
                ModelGrammar.TokenProperty("zero"),
                ModelGrammar.TokenPrimitive(0),
                ModelGrammar.TokenProperty("one"),
                ModelGrammar.TokenPrimitive(1),
                ModelGrammar.TokenProperty("space"),
                ModelGrammar.TokenPrimitive(" "),
                ModelGrammar.TokenProperty("quote"),
                ModelGrammar.TokenPrimitive("\""),
                ModelGrammar.TokenProperty("backslash"),
                ModelGrammar.TokenPrimitive("\\"),
                ModelGrammar.TokenProperty("controls"),
                ModelGrammar.TokenPrimitive("\b\f\n\r\t"),
                ModelGrammar.TokenProperty("slash"),
                ModelGrammar.TokenPrimitive("/ & /"),
                ModelGrammar.TokenProperty("alpha"),
                ModelGrammar.TokenPrimitive("abcdefghijklmnopqrstuvwyz"),
                ModelGrammar.TokenProperty("ALPHA"),
                ModelGrammar.TokenPrimitive("ABCDEFGHIJKLMNOPQRSTUVWYZ"),
                ModelGrammar.TokenProperty("digit"),
                ModelGrammar.TokenPrimitive("0123456789"),
                ModelGrammar.TokenProperty("0123456789"),
                ModelGrammar.TokenPrimitive("digit"),
                ModelGrammar.TokenProperty("special"),
                ModelGrammar.TokenPrimitive("`1~!@#$%^&*()_+-={':[,]}|;.</>?"),
                ModelGrammar.TokenProperty("hex"),
                ModelGrammar.TokenPrimitive("\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"),
                ModelGrammar.TokenProperty("true"),
                ModelGrammar.TokenTrue,
                ModelGrammar.TokenProperty("false"),
                ModelGrammar.TokenFalse,
                ModelGrammar.TokenProperty("null"),
                ModelGrammar.TokenNull,
                ModelGrammar.TokenProperty("array"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenProperty("object"),
                ModelGrammar.TokenObjectBeginUnnamed,
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenProperty("address"),
                ModelGrammar.TokenPrimitive("50 St. James Street"),
                ModelGrammar.TokenProperty("url"),
                ModelGrammar.TokenPrimitive("http://www.JSON.org/"),
                ModelGrammar.TokenProperty("comment"),
                ModelGrammar.TokenPrimitive("// /* <!-- --"),
                ModelGrammar.TokenProperty("# -- --> */"),
                ModelGrammar.TokenPrimitive(" "),
                ModelGrammar.TokenProperty(" s p a c e d "),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenPrimitive(1),
                ModelGrammar.TokenPrimitive(2),
                ModelGrammar.TokenPrimitive(3),
                ModelGrammar.TokenPrimitive(4),
                ModelGrammar.TokenPrimitive(5),
                ModelGrammar.TokenPrimitive(6),
                ModelGrammar.TokenPrimitive(7),
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenProperty("compact"),
                ModelGrammar.TokenArrayBeginUnnamed,
                ModelGrammar.TokenPrimitive(1),
                ModelGrammar.TokenPrimitive(2),
                ModelGrammar.TokenPrimitive(3),
                ModelGrammar.TokenPrimitive(4),
                ModelGrammar.TokenPrimitive(5),
                ModelGrammar.TokenPrimitive(6),
                ModelGrammar.TokenPrimitive(7),
                ModelGrammar.TokenArrayEnd,
                ModelGrammar.TokenProperty("jsontext"),
                ModelGrammar.TokenPrimitive("{\"object with 1 member\":[\"array with 1 element\"]}"),
                ModelGrammar.TokenProperty("quotes"),
                ModelGrammar.TokenPrimitive("&#34; \u0022 %22 0x22 034 &#x22;"),
                ModelGrammar.TokenProperty("/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"),
                ModelGrammar.TokenPrimitive("A key can be any string"),
                ModelGrammar.TokenObjectEnd,
                ModelGrammar.TokenPrimitive(0.5),
                ModelGrammar.TokenPrimitive(98.6),
                ModelGrammar.TokenPrimitive(99.44),
                ModelGrammar.TokenPrimitive(1066),
                ModelGrammar.TokenPrimitive(10.0),
                ModelGrammar.TokenPrimitive(1.0),
                ModelGrammar.TokenPrimitive(0.1),
                ModelGrammar.TokenPrimitive(1.0),
                ModelGrammar.TokenPrimitive(2.0),
                ModelGrammar.TokenPrimitive(2.0),
                ModelGrammar.TokenPrimitive("rosebud"),
                ModelGrammar.TokenArrayEnd
            };

            var expected = new Dictionary <DataName, IEnumerable <Token <ModelTokenType> > >
            {
                { new DataName("url"), new[] { ModelGrammar.TokenPrimitive("http://www.JSON.org/") } },
                { new DataName("compact"), new[] {
                      ModelGrammar.TokenArrayBeginUnnamed,
                      ModelGrammar.TokenPrimitive(1),
                      ModelGrammar.TokenPrimitive(2),
                      ModelGrammar.TokenPrimitive(3),
                      ModelGrammar.TokenPrimitive(4),
                      ModelGrammar.TokenPrimitive(5),
                      ModelGrammar.TokenPrimitive(6),
                      ModelGrammar.TokenPrimitive(7),
                      ModelGrammar.TokenArrayEnd,
                  } }
            };

            Assert.True(input.IsArray());
            Assert.False(input.IsObject());
            Assert.False(input.IsPrimitive());

            // cherry pick properties
            var actual = input
                         .ArrayItems(index => index == 8).FirstOrDefault()                            // select the big object
                         .Properties(name => name.LocalName == "url" || name.LocalName == "compact"); // select two properties

            Assert.Equal(expected, actual, false);
        }