Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Linq\Extensions.cs

Symbol Coverage: 84.62% (55 of 65)

Branch Coverage: 80.00% (36 of 45)

Cyclomatic Complexity Avg: 1.55 Max:6

Code Lines: 70


L V Source
1
#region License
2
// Copyright (c) 2007 James Newton-King
3
//
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
11
// conditions:
12
//
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
24
#endregion
25

  
26
using System;
27
using System.Collections.Generic;
28
using System.Linq;
29
using System.Text;
30
using Newtonsoft.Json.Utilities;
31
using System.Collections;
32
using System.Globalization;
33

  
34
namespace Newtonsoft.Json.Linq
35
{
36
  /// <summary>
37
  /// Contains the LINQ to JSON extension methods.
38
  /// </summary>
39
  public static class Extensions
40
  {
41
    /// <summary>
42
    /// Returns a collection of tokens that contains the ancestors of every token in the source collection.
43
    /// </summary>
44
    /// <typeparam name="T">The type of the objects in source, constrained to <see cref="JToken"/>.</typeparam>
45
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
46
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the ancestors of every node in the source collection.</returns>
47
    public static IJEnumerable<JToken> Ancestors<T>(this IEnumerable<T> source) where T : JToken
48
    {
49
 0
      ValidationUtils.ArgumentNotNull(source, "source");
50

  
51
 0
      return source.SelectMany(j => j.Ancestors()).AsJEnumerable();
52
 0
    }
53

  
54
    //TODO
55
    //public static IEnumerable<JObject> AncestorsAndSelf<T>(this IEnumerable<T> source) where T : JObject
56
    //{
57
    //  ValidationUtils.ArgumentNotNull(source, "source");
58

  
59
    //  return source.SelectMany(j => j.AncestorsAndSelf());
60
    //}
61

  
62
    /// <summary>
63
    /// Returns a collection of tokens that contains the descendants of every token in the source collection.
64
    /// </summary>
65
    /// <typeparam name="T">The type of the objects in source, constrained to <see cref="JContainer"/>.</typeparam>
66
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
67
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the descendants of every node in the source collection.</returns>
68
    public static IJEnumerable<JToken> Descendants<T>(this IEnumerable<T> source) where T : JContainer
69
    {
70
 0
      ValidationUtils.ArgumentNotNull(source, "source");
71

  
72
 0
      return source.SelectMany(j => j.Descendants()).AsJEnumerable();
73
 0
    }
74

  
75
    //TODO
76
    //public static IEnumerable<JObject> DescendantsAndSelf<T>(this IEnumerable<T> source) where T : JContainer
77
    //{
78
    //  ValidationUtils.ArgumentNotNull(source, "source");
79

  
80
    //  return source.SelectMany(j => j.DescendantsAndSelf());
81
    //}
82

  
83
    /// <summary>
84
    /// Returns a collection of child properties of every object in the source collection.
85
    /// </summary>
86
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JObject"/> that contains the source collection.</param>
87
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JProperty"/> that contains the properties of every object in the source collection.</returns>
88
    public static IJEnumerable<JProperty> Properties(this IEnumerable<JObject> source)
89
    {
90
 1
      ValidationUtils.ArgumentNotNull(source, "source");
91

  
92
 1
      return source.SelectMany(d => d.Properties()).AsJEnumerable();
93
 1
    }
94

  
95
    /// <summary>
96
    /// Returns a collection of child values of every object in the source collection with the given key.
97
    /// </summary>
98
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
99
    /// <param name="key">The token key.</param>
100
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection with the given key.</returns>
101
    public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source, object key)
102
    {
103
 4
      return Values<JToken, JToken>(source, key).AsJEnumerable();
104
 4
    }
105

  
106
    /// <summary>
107
    /// Returns a collection of child values of every object in the source collection.
108
    /// </summary>
109
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
110
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection.</returns>
111
    public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source)
112
    {
113
 3
      return source.Values(null);
114
 3
    }
115

  
116
    /// <summary>
117
    /// Returns a collection of converted child values of every object in the source collection with the given key.
118
    /// </summary>
119
    /// <typeparam name="U">The type to convert the values to.</typeparam>
120
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
121
    /// <param name="key">The token key.</param>
122
    /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection with the given key.</returns>
123
    public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
124
    {
125
 2
      return Values<JToken, U>(source, key);
126
 2
    }
127

  
128
    /// <summary>
129
    /// Returns a collection of converted child values of every object in the source collection.
130
    /// </summary>
131
    /// <typeparam name="U">The type to convert the values to.</typeparam>
132
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
133
    /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection.</returns>
134
    public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source)
135
    {
136
 2
      return Values<JToken, U>(source, null);
137
 2
    }
138

  
139
    /// <summary>
140
    /// Converts the value.
141
    /// </summary>
142
    /// <typeparam name="U">The type to convert the value to.</typeparam>
143
    /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
144
    /// <returns>A converted value.</returns>
145
    public static U Value<U>(this IEnumerable<JToken> value)
146
    {
147
 1
      return value.Value<JToken, U>();
148
 1
    }
149

  
150
    /// <summary>
151
    /// Converts the value.
152
    /// </summary>
153
    /// <typeparam name="T">The source collection type.</typeparam>
154
    /// <typeparam name="U">The type to convert the value to.</typeparam>
155
    /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
156
    /// <returns>A converted value.</returns>
157
    public static U Value<T, U>(this IEnumerable<T> value) where T : JToken
158
    {
159
 1
      ValidationUtils.ArgumentNotNull(value, "source");
160

  
161
 1
      JToken token = value as JToken;
162
 1
      if (token == null)
163
 0
        throw new ArgumentException("Source value must be a JToken.");
164

  
165
 1
      return token.Convert<JToken, U>();
166
 1
    }
167

  
168

  
169
    internal static IEnumerable<U> Values<T, U>(this IEnumerable<T> source, object key) where T : JToken
170
    {
171
 15
      ValidationUtils.ArgumentNotNull(source, "source");
172

  
173
 15
      foreach (JToken token in source)
174
      {
175
 40
        if (key == null)
176
        {
177
 12
          if (token is JValue)
178
          {
179
 6
            yield return Convert<JValue, U>((JValue)token);
180
          }
181
          else
182
          {
183
 6
            foreach (JToken t in token.Children())
184
            {
185
 36
              yield return t.Convert<JToken, U>(); ;
186
            }
187
          }
188
        }
189
        else
190
        {
191
 28
          JToken value = token[key];
192
 28
          if (value != null)
193
 26
            yield return value.Convert<JToken, U>();
194
        }
195
      }
196

  
197
 13
      yield break;
198
    }
199

  
200
    //TODO
201
    //public static IEnumerable<T> InDocumentOrder<T>(this IEnumerable<T> source) where T : JObject;
202

  
203
    //public static IEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
204
    //{
205
    //  ValidationUtils.ArgumentNotNull(source, "source");
206

  
207
    //  return source.SelectMany(c => c.Children());
208
    //}
209

  
210
    /// <summary>
211
    /// Returns a collection of child tokens of every array in the source collection.
212
    /// </summary>
213
    /// <typeparam name="T">The source collection type.</typeparam>
214
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
215
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection.</returns>
216
    public static IJEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
217
    {
218
 3
      return Children<T, JToken>(source).AsJEnumerable();
219
 3
    }
220

  
221
    /// <summary>
222
    /// Returns a collection of converted child tokens of every array in the source collection.
223
    /// </summary>
224
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
225
    /// <typeparam name="U">The type to convert the values to.</typeparam>
226
    /// <typeparam name="T">The source collection type.</typeparam>
227
    /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection.</returns>
228
    public static IEnumerable<U> Children<T, U>(this IEnumerable<T> source) where T : JToken
229
    {
230
 3
      ValidationUtils.ArgumentNotNull(source, "source");
231

  
232
 3
      return source.SelectMany(c => c.Children()).Convert<JToken, U>();
233
 3
    }
234

  
235
    internal static IEnumerable<U> Convert<T, U>(this IEnumerable<T> source) where T : JToken
236
    {
237
 4
      ValidationUtils.ArgumentNotNull(source, "source");
238

  
239
 4
      bool cast = typeof(JToken).IsAssignableFrom(typeof(U));
240

  
241
 4
      foreach (JToken token in source)
242
      {
243
 23
        yield return Convert<JToken, U>(token, cast);
244
      }
245
    }
246

  
247
    internal static U Convert<T, U>(this T token) where T : JToken
248
    {
249
 75
      bool cast = typeof(JToken).IsAssignableFrom(typeof(U));
250

  
251
 75
      return Convert<T, U>(token, cast);
252
 75
    }
253

  
254
    internal static U Convert<T, U>(this T token, bool cast) where T : JToken
255
    {
256
 98
      if (cast)
257
      {
258
        // HACK
259
 68
        return (U)(object)token;
260
      }
261
      else
262
      {
263
 30
        if (token == null)
264
 1
          return default(U);
265

  
266
 29
        JValue value = token as JValue;
267
 29
        if (value == null)
268
 0
          throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T)));
269

  
270
 29
        Type targetType = typeof(U);
271

  
272
 29
        if (ReflectionUtils.IsNullableType(targetType))
273
        {
274
 2
          if (value.Value == null)
275
 1
            return default(U);
276

  
277
 1
          targetType = Nullable.GetUnderlyingType(targetType);
278
        }
279

  
280
 28
        return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture);
281
      }
282
 98
    }
283

  
284
    //TODO
285
    //public static void Remove<T>(this IEnumerable<T> source) where T : JContainer;
286

  
287
    /// <summary>
288
    /// Returns the input typed as <see cref="IJEnumerable{T}"/>.
289
    /// </summary>
290
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
291
    /// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
292
    public static IJEnumerable<JToken> AsJEnumerable(this IEnumerable<JToken> source)
293
    {
294
 9
      return source.AsJEnumerable<JToken>();
295
 9
    }
296

  
297
    /// <summary>
298
    /// Returns the input typed as <see cref="IJEnumerable{T}"/>.
299
    /// </summary>
300
    /// <typeparam name="T">The source collection type.</typeparam>
301
    /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
302
    /// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
303
    public static IJEnumerable<T> AsJEnumerable<T>(this IEnumerable<T> source) where T : JToken
304
    {
305
 10
      if (source == null)
306
 1
        return null;
307
 9
      else if (source is IJEnumerable<T>)
308
 1
        return (IJEnumerable<T>)source;
309
      else
310
 8
        return new JEnumerable<T>(source);
311
 10
    }
312
  }
313
}