PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Json45r7/Source/Src/Newtonsoft.Json/Linq/JContainer.cs

https://bitbucket.org/wantstudios/bitbucketclient
C# | 989 lines | 705 code | 168 blank | 116 comment | 146 complexity | 268c2682f4ea1ace4c32244b193f8561 MD5 | raw file
  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. using System;
  26. using System.Collections.Generic;
  27. #if !PORTABLE
  28. using System.Collections.Specialized;
  29. #endif
  30. using System.Threading;
  31. using Newtonsoft.Json.Utilities;
  32. using System.Collections;
  33. using System.Globalization;
  34. using System.ComponentModel;
  35. #if NET20
  36. using Newtonsoft.Json.Utilities.LinqBridge;
  37. #else
  38. using System.Linq;
  39. #endif
  40. namespace Newtonsoft.Json.Linq
  41. {
  42. /// <summary>
  43. /// Represents a token that can contain other tokens.
  44. /// </summary>
  45. public abstract class JContainer : JToken, IList<JToken>
  46. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  47. , ITypedList, IBindingList
  48. #elif !PORTABLE
  49. , INotifyCollectionChanged
  50. #endif
  51. , IList
  52. #if !(SILVERLIGHT || NET20 || NET35 || NETFX_CORE || PORTABLE)
  53. , INotifyCollectionChanged
  54. #endif
  55. {
  56. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  57. /// <summary>
  58. /// Occurs when the list changes or an item in the list changes.
  59. /// </summary>
  60. public event ListChangedEventHandler ListChanged;
  61. /// <summary>
  62. /// Occurs before an item is added to the collection.
  63. /// </summary>
  64. public event AddingNewEventHandler AddingNew;
  65. #endif
  66. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  67. /// <summary>
  68. /// Occurs when the items list of the collection has changed, or the collection is reset.
  69. /// </summary>
  70. public event NotifyCollectionChangedEventHandler CollectionChanged;
  71. #endif
  72. /// <summary>
  73. /// Gets the container's children tokens.
  74. /// </summary>
  75. /// <value>The container's children tokens.</value>
  76. protected abstract IList<JToken> ChildrenTokens { get; }
  77. private object _syncRoot;
  78. private bool _busy;
  79. internal JContainer()
  80. {
  81. }
  82. internal JContainer(JContainer other)
  83. {
  84. ValidationUtils.ArgumentNotNull(other, "c");
  85. foreach (JToken child in other)
  86. {
  87. Add(child);
  88. }
  89. }
  90. internal void CheckReentrancy()
  91. {
  92. if (_busy)
  93. throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  94. }
  95. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  96. /// <summary>
  97. /// Raises the <see cref="AddingNew"/> event.
  98. /// </summary>
  99. /// <param name="e">The <see cref="AddingNewEventArgs"/> instance containing the event data.</param>
  100. protected virtual void OnAddingNew(AddingNewEventArgs e)
  101. {
  102. AddingNewEventHandler handler = AddingNew;
  103. if (handler != null)
  104. handler(this, e);
  105. }
  106. /// <summary>
  107. /// Raises the <see cref="ListChanged"/> event.
  108. /// </summary>
  109. /// <param name="e">The <see cref="ListChangedEventArgs"/> instance containing the event data.</param>
  110. protected virtual void OnListChanged(ListChangedEventArgs e)
  111. {
  112. ListChangedEventHandler handler = ListChanged;
  113. if (handler != null)
  114. {
  115. _busy = true;
  116. try
  117. {
  118. handler(this, e);
  119. }
  120. finally
  121. {
  122. _busy = false;
  123. }
  124. }
  125. }
  126. #endif
  127. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  128. /// <summary>
  129. /// Raises the <see cref="CollectionChanged"/> event.
  130. /// </summary>
  131. /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
  132. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  133. {
  134. NotifyCollectionChangedEventHandler handler = CollectionChanged;
  135. if (handler != null)
  136. {
  137. _busy = true;
  138. try
  139. {
  140. handler(this, e);
  141. }
  142. finally
  143. {
  144. _busy = false;
  145. }
  146. }
  147. }
  148. #endif
  149. /// <summary>
  150. /// Gets a value indicating whether this token has childen tokens.
  151. /// </summary>
  152. /// <value>
  153. /// <c>true</c> if this token has child values; otherwise, <c>false</c>.
  154. /// </value>
  155. public override bool HasValues
  156. {
  157. get { return ChildrenTokens.Count > 0; }
  158. }
  159. internal bool ContentsEqual(JContainer container)
  160. {
  161. if (container == this)
  162. return true;
  163. IList<JToken> t1 = ChildrenTokens;
  164. IList<JToken> t2 = container.ChildrenTokens;
  165. if (t1.Count != t2.Count)
  166. return false;
  167. for (int i = 0; i < t1.Count; i++)
  168. {
  169. if (!t1[i].DeepEquals(t2[i]))
  170. return false;
  171. }
  172. return true;
  173. }
  174. /// <summary>
  175. /// Get the first child token of this token.
  176. /// </summary>
  177. /// <value>
  178. /// A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.
  179. /// </value>
  180. public override JToken First
  181. {
  182. get { return ChildrenTokens.FirstOrDefault(); }
  183. }
  184. /// <summary>
  185. /// Get the last child token of this token.
  186. /// </summary>
  187. /// <value>
  188. /// A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.
  189. /// </value>
  190. public override JToken Last
  191. {
  192. get { return ChildrenTokens.LastOrDefault(); }
  193. }
  194. /// <summary>
  195. /// Returns a collection of the child tokens of this token, in document order.
  196. /// </summary>
  197. /// <returns>
  198. /// An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.
  199. /// </returns>
  200. public override JEnumerable<JToken> Children()
  201. {
  202. return new JEnumerable<JToken>(ChildrenTokens);
  203. }
  204. /// <summary>
  205. /// Returns a collection of the child values of this token, in document order.
  206. /// </summary>
  207. /// <typeparam name="T">The type to convert the values to.</typeparam>
  208. /// <returns>
  209. /// A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.
  210. /// </returns>
  211. public override IEnumerable<T> Values<T>()
  212. {
  213. return ChildrenTokens.Convert<JToken, T>();
  214. }
  215. /// <summary>
  216. /// Returns a collection of the descendant tokens for this token in document order.
  217. /// </summary>
  218. /// <returns>An <see cref="IEnumerable{JToken}"/> containing the descendant tokens of the <see cref="JToken"/>.</returns>
  219. public IEnumerable<JToken> Descendants()
  220. {
  221. foreach (JToken o in ChildrenTokens)
  222. {
  223. yield return o;
  224. JContainer c = o as JContainer;
  225. if (c != null)
  226. {
  227. foreach (JToken d in c.Descendants())
  228. {
  229. yield return d;
  230. }
  231. }
  232. }
  233. }
  234. internal bool IsMultiContent(object content)
  235. {
  236. return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
  237. }
  238. internal JToken EnsureParentToken(JToken item, bool skipParentCheck)
  239. {
  240. if (item == null)
  241. return new JValue((object) null);
  242. if (skipParentCheck)
  243. return item;
  244. // to avoid a token having multiple parents or creating a recursive loop, create a copy if...
  245. // the item already has a parent
  246. // the item is being added to itself
  247. // the item is being added to the root parent of itself
  248. if (item.Parent != null || item == this || (item.HasValues && Root == item))
  249. item = item.CloneToken();
  250. return item;
  251. }
  252. private class JTokenReferenceEqualityComparer : IEqualityComparer<JToken>
  253. {
  254. public static readonly JTokenReferenceEqualityComparer Instance = new JTokenReferenceEqualityComparer();
  255. public bool Equals(JToken x, JToken y)
  256. {
  257. return ReferenceEquals(x, y);
  258. }
  259. public int GetHashCode(JToken obj)
  260. {
  261. if (obj == null)
  262. return 0;
  263. return obj.GetHashCode();
  264. }
  265. }
  266. internal int IndexOfItem(JToken item)
  267. {
  268. return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
  269. }
  270. internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
  271. {
  272. if (index > ChildrenTokens.Count)
  273. throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List.");
  274. CheckReentrancy();
  275. item = EnsureParentToken(item, skipParentCheck);
  276. JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
  277. // haven't inserted new token yet so next token is still at the inserting index
  278. JToken next = (index == ChildrenTokens.Count) ? null : ChildrenTokens[index];
  279. ValidateToken(item, null);
  280. item.Parent = this;
  281. item.Previous = previous;
  282. if (previous != null)
  283. previous.Next = item;
  284. item.Next = next;
  285. if (next != null)
  286. next.Previous = item;
  287. ChildrenTokens.Insert(index, item);
  288. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  289. if (ListChanged != null)
  290. OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
  291. #endif
  292. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  293. if (CollectionChanged != null)
  294. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
  295. #endif
  296. }
  297. internal virtual void RemoveItemAt(int index)
  298. {
  299. if (index < 0)
  300. throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
  301. if (index >= ChildrenTokens.Count)
  302. throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
  303. CheckReentrancy();
  304. JToken item = ChildrenTokens[index];
  305. JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
  306. JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
  307. if (previous != null)
  308. previous.Next = next;
  309. if (next != null)
  310. next.Previous = previous;
  311. item.Parent = null;
  312. item.Previous = null;
  313. item.Next = null;
  314. ChildrenTokens.RemoveAt(index);
  315. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  316. OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
  317. #endif
  318. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  319. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
  320. #endif
  321. }
  322. internal virtual bool RemoveItem(JToken item)
  323. {
  324. int index = IndexOfItem(item);
  325. if (index >= 0)
  326. {
  327. RemoveItemAt(index);
  328. return true;
  329. }
  330. return false;
  331. }
  332. internal virtual JToken GetItem(int index)
  333. {
  334. return ChildrenTokens[index];
  335. }
  336. internal virtual void SetItem(int index, JToken item)
  337. {
  338. if (index < 0)
  339. throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
  340. if (index >= ChildrenTokens.Count)
  341. throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
  342. JToken existing = ChildrenTokens[index];
  343. if (IsTokenUnchanged(existing, item))
  344. return;
  345. CheckReentrancy();
  346. item = EnsureParentToken(item, false);
  347. ValidateToken(item, existing);
  348. JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
  349. JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
  350. item.Parent = this;
  351. item.Previous = previous;
  352. if (previous != null)
  353. previous.Next = item;
  354. item.Next = next;
  355. if (next != null)
  356. next.Previous = item;
  357. ChildrenTokens[index] = item;
  358. existing.Parent = null;
  359. existing.Previous = null;
  360. existing.Next = null;
  361. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  362. OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
  363. #endif
  364. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  365. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index));
  366. #endif
  367. }
  368. internal virtual void ClearItems()
  369. {
  370. CheckReentrancy();
  371. foreach (JToken item in ChildrenTokens)
  372. {
  373. item.Parent = null;
  374. item.Previous = null;
  375. item.Next = null;
  376. }
  377. ChildrenTokens.Clear();
  378. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  379. OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
  380. #endif
  381. #if SILVERLIGHT || !(NET20 || NET35 || PORTABLE)
  382. OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  383. #endif
  384. }
  385. internal virtual void ReplaceItem(JToken existing, JToken replacement)
  386. {
  387. if (existing == null || existing.Parent != this)
  388. return;
  389. int index = IndexOfItem(existing);
  390. SetItem(index, replacement);
  391. }
  392. internal virtual bool ContainsItem(JToken item)
  393. {
  394. return (IndexOfItem(item) != -1);
  395. }
  396. internal virtual void CopyItemsTo(Array array, int arrayIndex)
  397. {
  398. if (array == null)
  399. throw new ArgumentNullException("array");
  400. if (arrayIndex < 0)
  401. throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
  402. if (arrayIndex >= array.Length)
  403. throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
  404. if (Count > array.Length - arrayIndex)
  405. throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
  406. int index = 0;
  407. foreach (JToken token in ChildrenTokens)
  408. {
  409. array.SetValue(token, arrayIndex + index);
  410. index++;
  411. }
  412. }
  413. internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
  414. {
  415. JValue v1 = currentValue as JValue;
  416. if (v1 != null)
  417. {
  418. // null will get turned into a JValue of type null
  419. if (v1.Type == JTokenType.Null && newValue == null)
  420. return true;
  421. return v1.Equals(newValue);
  422. }
  423. return false;
  424. }
  425. internal virtual void ValidateToken(JToken o, JToken existing)
  426. {
  427. ValidationUtils.ArgumentNotNull(o, "o");
  428. if (o.Type == JTokenType.Property)
  429. throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
  430. }
  431. /// <summary>
  432. /// Adds the specified content as children of this <see cref="JToken"/>.
  433. /// </summary>
  434. /// <param name="content">The content to be added.</param>
  435. public virtual void Add(object content)
  436. {
  437. AddInternal(ChildrenTokens.Count, content, false);
  438. }
  439. internal void AddAndSkipParentCheck(JToken token)
  440. {
  441. AddInternal(ChildrenTokens.Count, token, true);
  442. }
  443. /// <summary>
  444. /// Adds the specified content as the first children of this <see cref="JToken"/>.
  445. /// </summary>
  446. /// <param name="content">The content to be added.</param>
  447. public void AddFirst(object content)
  448. {
  449. AddInternal(0, content, false);
  450. }
  451. internal void AddInternal(int index, object content, bool skipParentCheck)
  452. {
  453. if (IsMultiContent(content))
  454. {
  455. IEnumerable enumerable = (IEnumerable)content;
  456. int multiIndex = index;
  457. foreach (object c in enumerable)
  458. {
  459. AddInternal(multiIndex, c, skipParentCheck);
  460. multiIndex++;
  461. }
  462. }
  463. else
  464. {
  465. JToken item = CreateFromContent(content);
  466. InsertItem(index, item, skipParentCheck);
  467. }
  468. }
  469. internal JToken CreateFromContent(object content)
  470. {
  471. if (content is JToken)
  472. return (JToken)content;
  473. return new JValue(content);
  474. }
  475. /// <summary>
  476. /// Creates an <see cref="JsonWriter"/> that can be used to add tokens to the <see cref="JToken"/>.
  477. /// </summary>
  478. /// <returns>An <see cref="JsonWriter"/> that is ready to have content written to it.</returns>
  479. public JsonWriter CreateWriter()
  480. {
  481. return new JTokenWriter(this);
  482. }
  483. /// <summary>
  484. /// Replaces the children nodes of this token with the specified content.
  485. /// </summary>
  486. /// <param name="content">The content.</param>
  487. public void ReplaceAll(object content)
  488. {
  489. ClearItems();
  490. Add(content);
  491. }
  492. /// <summary>
  493. /// Removes the child nodes from this token.
  494. /// </summary>
  495. public void RemoveAll()
  496. {
  497. ClearItems();
  498. }
  499. internal void ReadTokenFrom(JsonReader reader)
  500. {
  501. int startDepth = reader.Depth;
  502. if (!reader.Read())
  503. throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
  504. ReadContentFrom(reader);
  505. int endDepth = reader.Depth;
  506. if (endDepth > startDepth)
  507. throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
  508. }
  509. internal void ReadContentFrom(JsonReader r)
  510. {
  511. ValidationUtils.ArgumentNotNull(r, "r");
  512. IJsonLineInfo lineInfo = r as IJsonLineInfo;
  513. JContainer parent = this;
  514. do
  515. {
  516. if (parent is JProperty && ((JProperty)parent).Value != null)
  517. {
  518. if (parent == this)
  519. return;
  520. parent = parent.Parent;
  521. }
  522. switch (r.TokenType)
  523. {
  524. case JsonToken.None:
  525. // new reader. move to actual content
  526. break;
  527. case JsonToken.StartArray:
  528. JArray a = new JArray();
  529. a.SetLineInfo(lineInfo);
  530. parent.Add(a);
  531. parent = a;
  532. break;
  533. case JsonToken.EndArray:
  534. if (parent == this)
  535. return;
  536. parent = parent.Parent;
  537. break;
  538. case JsonToken.StartObject:
  539. JObject o = new JObject();
  540. o.SetLineInfo(lineInfo);
  541. parent.Add(o);
  542. parent = o;
  543. break;
  544. case JsonToken.EndObject:
  545. if (parent == this)
  546. return;
  547. parent = parent.Parent;
  548. break;
  549. case JsonToken.StartConstructor:
  550. JConstructor constructor = new JConstructor(r.Value.ToString());
  551. constructor.SetLineInfo(constructor);
  552. parent.Add(constructor);
  553. parent = constructor;
  554. break;
  555. case JsonToken.EndConstructor:
  556. if (parent == this)
  557. return;
  558. parent = parent.Parent;
  559. break;
  560. case JsonToken.String:
  561. case JsonToken.Integer:
  562. case JsonToken.Float:
  563. case JsonToken.Date:
  564. case JsonToken.Boolean:
  565. case JsonToken.Bytes:
  566. JValue v = new JValue(r.Value);
  567. v.SetLineInfo(lineInfo);
  568. parent.Add(v);
  569. break;
  570. case JsonToken.Comment:
  571. v = JValue.CreateComment(r.Value.ToString());
  572. v.SetLineInfo(lineInfo);
  573. parent.Add(v);
  574. break;
  575. case JsonToken.Null:
  576. v = new JValue(null, JTokenType.Null);
  577. v.SetLineInfo(lineInfo);
  578. parent.Add(v);
  579. break;
  580. case JsonToken.Undefined:
  581. v = new JValue(null, JTokenType.Undefined);
  582. v.SetLineInfo(lineInfo);
  583. parent.Add(v);
  584. break;
  585. case JsonToken.PropertyName:
  586. string propertyName = r.Value.ToString();
  587. JProperty property = new JProperty(propertyName);
  588. property.SetLineInfo(lineInfo);
  589. JObject parentObject = (JObject) parent;
  590. // handle multiple properties with the same name in JSON
  591. JProperty existingPropertyWithName = parentObject.Property(propertyName);
  592. if (existingPropertyWithName == null)
  593. parent.Add(property);
  594. else
  595. existingPropertyWithName.Replace(property);
  596. parent = property;
  597. break;
  598. default:
  599. throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType));
  600. }
  601. }
  602. while (r.Read());
  603. }
  604. internal int ContentsHashCode()
  605. {
  606. int hashCode = 0;
  607. foreach (JToken item in ChildrenTokens)
  608. {
  609. hashCode ^= item.GetDeepHashCode();
  610. }
  611. return hashCode;
  612. }
  613. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  614. string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
  615. {
  616. return string.Empty;
  617. }
  618. PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
  619. {
  620. ICustomTypeDescriptor d = First as ICustomTypeDescriptor;
  621. if (d != null)
  622. return d.GetProperties();
  623. return null;
  624. }
  625. #endif
  626. #region IList<JToken> Members
  627. int IList<JToken>.IndexOf(JToken item)
  628. {
  629. return IndexOfItem(item);
  630. }
  631. void IList<JToken>.Insert(int index, JToken item)
  632. {
  633. InsertItem(index, item, false);
  634. }
  635. void IList<JToken>.RemoveAt(int index)
  636. {
  637. RemoveItemAt(index);
  638. }
  639. JToken IList<JToken>.this[int index]
  640. {
  641. get { return GetItem(index); }
  642. set { SetItem(index, value); }
  643. }
  644. #endregion
  645. #region ICollection<JToken> Members
  646. void ICollection<JToken>.Add(JToken item)
  647. {
  648. Add(item);
  649. }
  650. void ICollection<JToken>.Clear()
  651. {
  652. ClearItems();
  653. }
  654. bool ICollection<JToken>.Contains(JToken item)
  655. {
  656. return ContainsItem(item);
  657. }
  658. void ICollection<JToken>.CopyTo(JToken[] array, int arrayIndex)
  659. {
  660. CopyItemsTo(array, arrayIndex);
  661. }
  662. bool ICollection<JToken>.IsReadOnly
  663. {
  664. get { return false; }
  665. }
  666. bool ICollection<JToken>.Remove(JToken item)
  667. {
  668. return RemoveItem(item);
  669. }
  670. #endregion
  671. private JToken EnsureValue(object value)
  672. {
  673. if (value == null)
  674. return null;
  675. if (value is JToken)
  676. return (JToken) value;
  677. throw new ArgumentException("Argument is not a JToken.");
  678. }
  679. #region IList Members
  680. int IList.Add(object value)
  681. {
  682. Add(EnsureValue(value));
  683. return Count - 1;
  684. }
  685. void IList.Clear()
  686. {
  687. ClearItems();
  688. }
  689. bool IList.Contains(object value)
  690. {
  691. return ContainsItem(EnsureValue(value));
  692. }
  693. int IList.IndexOf(object value)
  694. {
  695. return IndexOfItem(EnsureValue(value));
  696. }
  697. void IList.Insert(int index, object value)
  698. {
  699. InsertItem(index, EnsureValue(value), false);
  700. }
  701. bool IList.IsFixedSize
  702. {
  703. get { return false; }
  704. }
  705. bool IList.IsReadOnly
  706. {
  707. get { return false; }
  708. }
  709. void IList.Remove(object value)
  710. {
  711. RemoveItem(EnsureValue(value));
  712. }
  713. void IList.RemoveAt(int index)
  714. {
  715. RemoveItemAt(index);
  716. }
  717. object IList.this[int index]
  718. {
  719. get { return GetItem(index); }
  720. set { SetItem(index, EnsureValue(value)); }
  721. }
  722. #endregion
  723. #region ICollection Members
  724. void ICollection.CopyTo(Array array, int index)
  725. {
  726. CopyItemsTo(array, index);
  727. }
  728. /// <summary>
  729. /// Gets the count of child JSON tokens.
  730. /// </summary>
  731. /// <value>The count of child JSON tokens</value>
  732. public int Count
  733. {
  734. get { return ChildrenTokens.Count; }
  735. }
  736. bool ICollection.IsSynchronized
  737. {
  738. get { return false; }
  739. }
  740. object ICollection.SyncRoot
  741. {
  742. get
  743. {
  744. if (_syncRoot == null)
  745. Interlocked.CompareExchange(ref _syncRoot, new object(), null);
  746. return _syncRoot;
  747. }
  748. }
  749. #endregion
  750. #region IBindingList Members
  751. #if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
  752. void IBindingList.AddIndex(PropertyDescriptor property)
  753. {
  754. }
  755. object IBindingList.AddNew()
  756. {
  757. AddingNewEventArgs args = new AddingNewEventArgs();
  758. OnAddingNew(args);
  759. if (args.NewObject == null)
  760. throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType()));
  761. if (!(args.NewObject is JToken))
  762. throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken)));
  763. JToken newItem = (JToken)args.NewObject;
  764. Add(newItem);
  765. return newItem;
  766. }
  767. bool IBindingList.AllowEdit
  768. {
  769. get { return true; }
  770. }
  771. bool IBindingList.AllowNew
  772. {
  773. get { return true; }
  774. }
  775. bool IBindingList.AllowRemove
  776. {
  777. get { return true; }
  778. }
  779. void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
  780. {
  781. throw new NotSupportedException();
  782. }
  783. int IBindingList.Find(PropertyDescriptor property, object key)
  784. {
  785. throw new NotSupportedException();
  786. }
  787. bool IBindingList.IsSorted
  788. {
  789. get { return false; }
  790. }
  791. void IBindingList.RemoveIndex(PropertyDescriptor property)
  792. {
  793. }
  794. void IBindingList.RemoveSort()
  795. {
  796. throw new NotSupportedException();
  797. }
  798. ListSortDirection IBindingList.SortDirection
  799. {
  800. get { return ListSortDirection.Ascending; }
  801. }
  802. PropertyDescriptor IBindingList.SortProperty
  803. {
  804. get { return null; }
  805. }
  806. bool IBindingList.SupportsChangeNotification
  807. {
  808. get { return true; }
  809. }
  810. bool IBindingList.SupportsSearching
  811. {
  812. get { return false; }
  813. }
  814. bool IBindingList.SupportsSorting
  815. {
  816. get { return false; }
  817. }
  818. #endif
  819. #endregion
  820. }
  821. }