PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/System.Configuration/System.Configuration/ConfigurationElementCollection.cs

https://bitbucket.org/danipen/mono
C# | 598 lines | 469 code | 98 blank | 31 comment | 125 complexity | 29258b9e0e2bf92970f3d7ae78c6373a MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // System.Configuration.ConfigurationElementCollection.cs
  3. //
  4. // Authors:
  5. // Tim Coleman (tim@timcoleman.com)
  6. // Martin Baulig <martin.baulig@xamarin.com>
  7. //
  8. // Copyright (C) Tim Coleman, 2004
  9. // Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  31. //
  32. #if NET_2_0
  33. using System.Collections;
  34. using System.Diagnostics;
  35. using System.Xml;
  36. namespace System.Configuration
  37. {
  38. [DebuggerDisplayAttribute ("Count = {Count}")]
  39. public abstract partial class ConfigurationElementCollection : ConfigurationElement, ICollection, IEnumerable
  40. {
  41. ArrayList list = new ArrayList ();
  42. ArrayList removed;
  43. ArrayList inherited;
  44. bool emitClear;
  45. bool modified;
  46. IComparer comparer;
  47. int inheritedLimitIndex;
  48. string addElementName = "add";
  49. string clearElementName = "clear";
  50. string removeElementName = "remove";
  51. #region Constructors
  52. protected ConfigurationElementCollection ()
  53. {
  54. }
  55. protected ConfigurationElementCollection (IComparer comparer)
  56. {
  57. this.comparer = comparer;
  58. }
  59. internal override void InitFromProperty (PropertyInformation propertyInfo)
  60. {
  61. ConfigurationCollectionAttribute colat = propertyInfo.Property.CollectionAttribute;
  62. if (colat == null)
  63. colat = Attribute.GetCustomAttribute (propertyInfo.Type, typeof (ConfigurationCollectionAttribute)) as ConfigurationCollectionAttribute;
  64. if (colat != null) {
  65. addElementName = colat.AddItemName;
  66. clearElementName = colat.ClearItemsName;
  67. removeElementName = colat.RemoveItemName;
  68. }
  69. base.InitFromProperty (propertyInfo);
  70. }
  71. #endregion // Constructors
  72. #region Properties
  73. public virtual ConfigurationElementCollectionType CollectionType {
  74. get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
  75. }
  76. bool IsBasic {
  77. get {
  78. return CollectionType == ConfigurationElementCollectionType.BasicMap ||
  79. CollectionType == ConfigurationElementCollectionType.BasicMapAlternate;
  80. }
  81. }
  82. bool IsAlternate {
  83. get {
  84. return CollectionType == ConfigurationElementCollectionType.AddRemoveClearMapAlternate ||
  85. CollectionType == ConfigurationElementCollectionType.BasicMapAlternate;
  86. }
  87. }
  88. public int Count {
  89. get { return list.Count; }
  90. }
  91. protected virtual string ElementName {
  92. get { return string.Empty; }
  93. }
  94. public bool EmitClear {
  95. get { return emitClear; }
  96. set { emitClear = value; }
  97. }
  98. public bool IsSynchronized {
  99. get { return false; }
  100. }
  101. public object SyncRoot {
  102. get { return this; }
  103. }
  104. protected virtual bool ThrowOnDuplicate {
  105. get {
  106. if (CollectionType != ConfigurationElementCollectionType.AddRemoveClearMap &&
  107. CollectionType != ConfigurationElementCollectionType.AddRemoveClearMapAlternate)
  108. return false;
  109. return true;
  110. }
  111. }
  112. protected internal string AddElementName {
  113. get { return addElementName; }
  114. set { addElementName = value; }
  115. }
  116. protected internal string ClearElementName {
  117. get { return clearElementName; }
  118. set { clearElementName = value; }
  119. }
  120. protected internal string RemoveElementName {
  121. get { return removeElementName; }
  122. set { removeElementName = value; }
  123. }
  124. #endregion // Properties
  125. #region Methods
  126. protected virtual void BaseAdd (ConfigurationElement element)
  127. {
  128. BaseAdd (element, ThrowOnDuplicate);
  129. }
  130. protected void BaseAdd (ConfigurationElement element, bool throwIfExists)
  131. {
  132. if (IsReadOnly ())
  133. throw new ConfigurationErrorsException ("Collection is read only.");
  134. if (IsAlternate) {
  135. list.Insert (inheritedLimitIndex, element);
  136. inheritedLimitIndex++;
  137. }
  138. else {
  139. int old_index = IndexOfKey (GetElementKey (element));
  140. if (old_index >= 0) {
  141. if (element.Equals (list [old_index]))
  142. return;
  143. if (throwIfExists)
  144. throw new ConfigurationErrorsException ("Duplicate element in collection");
  145. list.RemoveAt (old_index);
  146. }
  147. list.Add (element);
  148. }
  149. modified = true;
  150. }
  151. protected virtual void BaseAdd (int index, ConfigurationElement element)
  152. {
  153. if (ThrowOnDuplicate && BaseIndexOf (element) != -1)
  154. throw new ConfigurationErrorsException ("Duplicate element in collection");
  155. if (IsReadOnly ())
  156. throw new ConfigurationErrorsException ("Collection is read only.");
  157. if (IsAlternate && (index > inheritedLimitIndex))
  158. throw new ConfigurationErrorsException ("Can't insert new elements below the inherited elements.");
  159. if (!IsAlternate && (index <= inheritedLimitIndex))
  160. throw new ConfigurationErrorsException ("Can't insert new elements above the inherited elements.");
  161. list.Insert (index, element);
  162. modified = true;
  163. }
  164. protected internal void BaseClear ()
  165. {
  166. if (IsReadOnly ())
  167. throw new ConfigurationErrorsException ("Collection is read only.");
  168. list.Clear ();
  169. modified = true;
  170. }
  171. protected internal ConfigurationElement BaseGet (int index)
  172. {
  173. return (ConfigurationElement) list [index];
  174. }
  175. protected internal ConfigurationElement BaseGet (object key)
  176. {
  177. int index = IndexOfKey (key);
  178. if (index != -1) return (ConfigurationElement) list [index];
  179. else return null;
  180. }
  181. protected internal object[] BaseGetAllKeys ()
  182. {
  183. object[] keys = new object [list.Count];
  184. for (int n=0; n<list.Count; n++)
  185. keys [n] = BaseGetKey (n);
  186. return keys;
  187. }
  188. protected internal object BaseGetKey (int index)
  189. {
  190. if (index < 0 || index >= list.Count)
  191. throw new ConfigurationErrorsException (String.Format ("Index {0} is out of range", index));
  192. return GetElementKey ((ConfigurationElement) list[index]).ToString ();
  193. }
  194. protected int BaseIndexOf (ConfigurationElement element)
  195. {
  196. return list.IndexOf (element);
  197. }
  198. int IndexOfKey (object key)
  199. {
  200. for (int n=0; n<list.Count; n++) {
  201. if (CompareKeys (GetElementKey ((ConfigurationElement) list[n]), key))
  202. return n;
  203. }
  204. return -1;
  205. }
  206. protected internal bool BaseIsRemoved (object key)
  207. {
  208. if (removed == null)
  209. return false;
  210. foreach (ConfigurationElement elem in removed) {
  211. if (CompareKeys (GetElementKey (elem), key))
  212. return true;
  213. }
  214. return false;
  215. }
  216. protected internal void BaseRemove (object key)
  217. {
  218. if (IsReadOnly ())
  219. throw new ConfigurationErrorsException ("Collection is read only.");
  220. int index = IndexOfKey (key);
  221. if (index != -1) {
  222. BaseRemoveAt (index);
  223. modified = true;
  224. }
  225. }
  226. protected internal void BaseRemoveAt (int index)
  227. {
  228. if (IsReadOnly ())
  229. throw new ConfigurationErrorsException ("Collection is read only.");
  230. ConfigurationElement elem = (ConfigurationElement) list [index];
  231. if (!IsElementRemovable (elem))
  232. throw new ConfigurationErrorsException ("Element can't be removed from element collection.");
  233. if (inherited != null && inherited.Contains (elem))
  234. throw new ConfigurationErrorsException ("Inherited items can't be removed.");
  235. list.RemoveAt (index);
  236. if (IsAlternate) {
  237. if (inheritedLimitIndex > 0)
  238. inheritedLimitIndex--;
  239. }
  240. modified = true;
  241. }
  242. bool CompareKeys (object key1, object key2)
  243. {
  244. if (comparer != null)
  245. return comparer.Compare (key1, key2) == 0;
  246. else
  247. return object.Equals (key1, key2);
  248. }
  249. public void CopyTo (ConfigurationElement[] array, int index)
  250. {
  251. list.CopyTo (array, index);
  252. }
  253. protected abstract ConfigurationElement CreateNewElement ();
  254. protected virtual ConfigurationElement CreateNewElement (string elementName)
  255. {
  256. return CreateNewElement ();
  257. }
  258. ConfigurationElement CreateNewElementInternal (string elementName)
  259. {
  260. ConfigurationElement elem;
  261. if (elementName == null)
  262. elem = CreateNewElement ();
  263. else
  264. elem = CreateNewElement (elementName);
  265. elem.Init ();
  266. return elem;
  267. }
  268. public override bool Equals (object compareTo)
  269. {
  270. ConfigurationElementCollection other = compareTo as ConfigurationElementCollection;
  271. if (other == null) return false;
  272. if (GetType() != other.GetType()) return false;
  273. if (Count != other.Count) return false;
  274. for (int n=0; n<Count; n++) {
  275. if (!BaseGet (n).Equals (other.BaseGet (n)))
  276. return false;
  277. }
  278. return true;
  279. }
  280. protected abstract object GetElementKey (ConfigurationElement element);
  281. public override int GetHashCode ()
  282. {
  283. int code = 0;
  284. for (int n=0; n<Count; n++)
  285. code += BaseGet (n).GetHashCode ();
  286. return code;
  287. }
  288. void ICollection.CopyTo (Array arr, int index)
  289. {
  290. list.CopyTo (arr, index);
  291. }
  292. public IEnumerator GetEnumerator ()
  293. {
  294. return list.GetEnumerator ();
  295. }
  296. protected virtual bool IsElementName (string elementName)
  297. {
  298. return false;
  299. }
  300. protected virtual bool IsElementRemovable (ConfigurationElement element)
  301. {
  302. return !IsReadOnly ();
  303. }
  304. protected internal override bool IsModified ()
  305. {
  306. if (modified)
  307. return true;
  308. for (int n=0; n<list.Count; n++) {
  309. ConfigurationElement elem = (ConfigurationElement) list [n];
  310. if (!elem.IsModified ())
  311. continue;
  312. modified = true;
  313. break;
  314. }
  315. return modified;
  316. }
  317. [MonoTODO]
  318. public override bool IsReadOnly ()
  319. {
  320. return base.IsReadOnly ();
  321. }
  322. internal override void PrepareSave (ConfigurationElement parentElement, ConfigurationSaveMode mode)
  323. {
  324. var parent = (ConfigurationElementCollection)parentElement;
  325. base.PrepareSave (parentElement, mode);
  326. for (int n=0; n<list.Count; n++) {
  327. ConfigurationElement elem = (ConfigurationElement) list [n];
  328. object key = GetElementKey (elem);
  329. ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
  330. elem.PrepareSave (pitem, mode);
  331. }
  332. }
  333. internal override bool HasValues (ConfigurationElement parentElement, ConfigurationSaveMode mode)
  334. {
  335. var parent = (ConfigurationElementCollection)parentElement;
  336. if (mode == ConfigurationSaveMode.Full)
  337. return list.Count > 0;
  338. for (int n=0; n<list.Count; n++) {
  339. ConfigurationElement elem = (ConfigurationElement) list [n];
  340. object key = GetElementKey (elem);
  341. ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
  342. if (elem.HasValues (pitem, mode))
  343. return true;
  344. }
  345. return false;
  346. }
  347. protected internal override void Reset (ConfigurationElement parentElement)
  348. {
  349. bool basic = IsBasic;
  350. ConfigurationElementCollection parent = (ConfigurationElementCollection) parentElement;
  351. for (int n=0; n<parent.Count; n++)
  352. {
  353. ConfigurationElement parentItem = parent.BaseGet (n);
  354. ConfigurationElement item = CreateNewElementInternal (null);
  355. item.Reset (parentItem);
  356. BaseAdd (item);
  357. if (basic) {
  358. if (inherited == null)
  359. inherited = new ArrayList ();
  360. inherited.Add (item);
  361. }
  362. }
  363. if (IsAlternate)
  364. inheritedLimitIndex = 0;
  365. else
  366. inheritedLimitIndex = Count - 1;
  367. modified = false;
  368. }
  369. protected internal override void ResetModified ()
  370. {
  371. modified = false;
  372. for (int n=0; n<list.Count; n++) {
  373. ConfigurationElement elem = (ConfigurationElement) list [n];
  374. elem.ResetModified ();
  375. }
  376. }
  377. [MonoTODO]
  378. protected internal override void SetReadOnly ()
  379. {
  380. base.SetReadOnly ();
  381. }
  382. protected internal override bool SerializeElement (XmlWriter writer, bool serializeCollectionKey)
  383. {
  384. if (serializeCollectionKey) {
  385. return base.SerializeElement (writer, serializeCollectionKey);
  386. }
  387. bool wroteData = false;
  388. if (IsBasic)
  389. {
  390. for (int n=0; n<list.Count; n++) {
  391. ConfigurationElement elem = (ConfigurationElement) list [n];
  392. if (ElementName != string.Empty)
  393. wroteData = elem.SerializeToXmlElement (writer, ElementName) || wroteData;
  394. else
  395. wroteData = elem.SerializeElement (writer, false) || wroteData;
  396. }
  397. }
  398. else
  399. {
  400. if (emitClear) {
  401. writer.WriteElementString (clearElementName, "");
  402. wroteData = true;
  403. }
  404. if (removed != null) {
  405. for (int n=0; n<removed.Count; n++) {
  406. writer.WriteStartElement (removeElementName);
  407. ((ConfigurationElement)removed[n]).SerializeElement (writer, true);
  408. writer.WriteEndElement ();
  409. }
  410. wroteData = wroteData || removed.Count > 0;
  411. }
  412. for (int n=0; n<list.Count; n++) {
  413. ConfigurationElement elem = (ConfigurationElement) list [n];
  414. elem.SerializeToXmlElement (writer, addElementName);
  415. }
  416. wroteData = wroteData || list.Count > 0;
  417. }
  418. return wroteData;
  419. }
  420. protected override bool OnDeserializeUnrecognizedElement (string elementName, XmlReader reader)
  421. {
  422. if (IsBasic)
  423. {
  424. ConfigurationElement elem = null;
  425. if (elementName == ElementName)
  426. elem = CreateNewElementInternal (null);
  427. if (IsElementName (elementName))
  428. elem = CreateNewElementInternal (elementName);
  429. if (elem != null) {
  430. elem.DeserializeElement (reader, false);
  431. BaseAdd (elem);
  432. modified = false;
  433. return true;
  434. }
  435. }
  436. else {
  437. if (elementName == clearElementName) {
  438. reader.MoveToContent ();
  439. if (reader.MoveToNextAttribute ())
  440. throw new ConfigurationErrorsException ("Unrecognized attribute '" + reader.LocalName + "'.");
  441. reader.MoveToElement ();
  442. reader.Skip ();
  443. BaseClear ();
  444. emitClear = true;
  445. modified = false;
  446. return true;
  447. }
  448. else if (elementName == removeElementName) {
  449. ConfigurationElement elem = CreateNewElementInternal (null);
  450. ConfigurationRemoveElement removeElem = new ConfigurationRemoveElement (elem, this);
  451. removeElem.DeserializeElement (reader, true);
  452. BaseRemove (removeElem.KeyValue);
  453. modified = false;
  454. return true;
  455. }
  456. else if (elementName == addElementName) {
  457. ConfigurationElement elem = CreateNewElementInternal (null);
  458. elem.DeserializeElement (reader, false);
  459. BaseAdd (elem);
  460. modified = false;
  461. return true;
  462. }
  463. }
  464. return false;
  465. }
  466. protected internal override void Unmerge (ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode updateMode)
  467. {
  468. ConfigurationElementCollection source = (ConfigurationElementCollection) sourceElement;
  469. ConfigurationElementCollection parent = (ConfigurationElementCollection) parentElement;
  470. for (int n=0; n<source.Count; n++) {
  471. ConfigurationElement sitem = source.BaseGet (n);
  472. object key = source.GetElementKey (sitem);
  473. ConfigurationElement pitem = parent != null ? parent.BaseGet (key) as ConfigurationElement : null;
  474. ConfigurationElement nitem = CreateNewElementInternal (null);
  475. if (pitem != null && updateMode != ConfigurationSaveMode.Full) {
  476. nitem.Unmerge (sitem, pitem, updateMode);
  477. if (nitem.HasValues (pitem, updateMode))
  478. BaseAdd (nitem);
  479. } else {
  480. nitem.Unmerge (sitem, null, ConfigurationSaveMode.Full);
  481. BaseAdd (nitem);
  482. }
  483. }
  484. if (updateMode == ConfigurationSaveMode.Full)
  485. EmitClear = true;
  486. else if (parent != null) {
  487. for (int n=0; n<parent.Count; n++) {
  488. ConfigurationElement pitem = parent.BaseGet (n);
  489. object key = parent.GetElementKey (pitem);
  490. if (source.IndexOfKey (key) == -1) {
  491. if (removed == null) removed = new ArrayList ();
  492. removed.Add (pitem);
  493. }
  494. }
  495. }
  496. }
  497. #endregion // Methods
  498. }
  499. }
  500. #endif