Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / System / Data / Common / DataTableMappingCollection.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DataTableMappingCollection.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8
9 namespace System.Data.Common {
10
11     using System;
12     using System.Collections;
13     using System.Collections.Generic;
14     using System.ComponentModel;
15     using System.Data;
16     using System.Diagnostics;
17
18     [
19     Editor("Microsoft.VSDesigner.Data.Design.DataTableMappingCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
20     ListBindable(false)
21     ]
22     public sealed class DataTableMappingCollection : MarshalByRefObject, ITableMappingCollection {
23         private List<DataTableMapping> items; // delay creation until AddWithoutEvents, Insert, CopyTo, GetEnumerator
24
25         public DataTableMappingCollection() {
26         }
27
28         // explicit ICollection implementation
29         bool System.Collections.ICollection.IsSynchronized {
30             get { return false;}
31         }
32         object System.Collections.ICollection.SyncRoot {
33             get { return this;}
34         }
35
36         // explicit IList implementation
37         bool System.Collections.IList.IsReadOnly {
38             get { return false;}
39         }
40          bool System.Collections.IList.IsFixedSize {
41             get { return false;}
42         }
43         object System.Collections.IList.this[int index] {
44             get {
45                 return this[index];
46             }
47             set {
48                 ValidateType(value);
49                 this[index] = (DataTableMapping) value;
50             }
51         }
52
53         object ITableMappingCollection.this[string index] {
54             get {
55                 return this[index];
56             }
57             set {
58                 ValidateType(value);
59                 this[index] = (DataTableMapping) value;
60             }
61         }
62         ITableMapping ITableMappingCollection.Add(string sourceTableName, string dataSetTableName) {
63             return Add(sourceTableName, dataSetTableName);
64         }
65         ITableMapping ITableMappingCollection.GetByDataSetTable(string dataSetTableName) {
66             return GetByDataSetTable(dataSetTableName);
67         }
68
69         [
70         Browsable(false),
71         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
72         ResDescriptionAttribute(Res.DataTableMappings_Count),
73         ]
74         public int Count {
75             get {
76                 return ((null != items) ? items.Count : 0);
77             }
78         }
79
80         private Type ItemType {
81             get { return typeof(DataTableMapping); }
82         }
83
84         [
85         Browsable(false),
86         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
87         ResDescriptionAttribute(Res.DataTableMappings_Item),
88         ]
89         public DataTableMapping this[int index] {
90             get {
91                 RangeCheck(index);
92                 return items[index];
93             }
94             set {
95                 RangeCheck(index);
96                 Replace(index, value);
97             }
98         }
99
100         [
101         Browsable(false),
102         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
103         ResDescriptionAttribute(Res.DataTableMappings_Item),
104         ]
105         public DataTableMapping this[string sourceTable] {
106             get {
107                 int index = RangeCheck(sourceTable);
108                 return items[index];
109             }
110             set {
111                 int index = RangeCheck(sourceTable);
112                 Replace(index, value);
113             }
114         }
115
116         public int Add(object value) {
117             ValidateType(value);
118             Add((DataTableMapping) value);
119             return Count-1;
120         }
121
122         private DataTableMapping Add(DataTableMapping value) {
123             AddWithoutEvents(value);
124             return value;
125         }
126
127         public void AddRange(DataTableMapping[] values) { // V1.0.3300
128             AddEnumerableRange(values, false);
129         }
130
131         public void AddRange(System.Array values) { // V1.2.3300
132             AddEnumerableRange(values, false);
133         }
134
135         private void AddEnumerableRange(IEnumerable values, bool doClone) {
136             if (null == values) {
137                 throw ADP.ArgumentNull("values");
138             }
139             foreach(object value in values) {
140                 ValidateType(value);
141             }
142             if (doClone) {
143                 foreach(ICloneable value in values) {
144                     AddWithoutEvents(value.Clone() as DataTableMapping);
145                 }
146             }
147             else {
148                 foreach(DataTableMapping value in values) {
149                     AddWithoutEvents(value);
150                 }
151             }
152         }
153
154         /*/// <include file='doc\DataTableMappingCollection.uex' path='docs/doc[@for="DataTableMappingCollection.AddCloneOfRange"]/*' />
155         public void AddCloneOfRange(IEnumerable values) {
156             AddEnumerableRange(values, true);
157         }*/
158
159         public DataTableMapping Add(string sourceTable, string dataSetTable) {
160             return Add(new DataTableMapping(sourceTable, dataSetTable));
161         }
162
163         private void AddWithoutEvents(DataTableMapping value) {
164             Validate(-1, value);
165             value.Parent = this;
166             ArrayList().Add(value);
167         }
168
169         // implemented as a method, not as a property because the VS7 debugger
170         // object browser calls properties to display their value, and we want this delayed
171         private List<DataTableMapping> ArrayList() {
172             if (null == this.items) {
173                 this.items = new List<DataTableMapping>();
174             }
175             return this.items;
176         }
177
178         public void Clear() {
179             if (0 < Count) {
180                 ClearWithoutEvents();
181             }
182         }
183
184         private void ClearWithoutEvents() {
185             if (null != items) {
186                 foreach(DataTableMapping item in items) {
187                     item.Parent = null;
188                 }
189                 items.Clear();
190             }
191         }
192
193         public bool Contains(string value) {
194             return (-1 != IndexOf(value));
195         }
196
197         public bool Contains(object value) {
198             return (-1 != IndexOf(value));
199         }
200
201         public void CopyTo(Array array, int index) {
202             ((ICollection)ArrayList()).CopyTo(array, index);
203         }
204
205         public void CopyTo(DataTableMapping[] array, int index) {
206             ArrayList().CopyTo(array, index);
207         }
208
209         public DataTableMapping GetByDataSetTable(string dataSetTable) {
210             int index = IndexOfDataSetTable(dataSetTable);
211             if (0 > index) {
212                 throw ADP.TablesDataSetTable(dataSetTable);
213             }
214             return items[index];
215         }
216
217         public IEnumerator GetEnumerator() {
218             return ArrayList().GetEnumerator();
219         }
220
221         public int IndexOf(object value) {
222             if (null != value) {
223                 ValidateType(value);
224                 for (int i = 0; i < Count; ++i) {
225                     if (items[i] == value) {
226                         return i;
227                     }
228                 }
229             }
230             return -1;
231         }
232
233         public int IndexOf(string sourceTable) {
234             if (!ADP.IsEmpty(sourceTable)) {
235                 for (int i = 0; i < Count; ++i) {
236                     string value = items[i].SourceTable;
237                     if ((null != value) && (0 == ADP.SrcCompare(sourceTable, value))) {
238                         return i;
239                     }
240                 }
241             }
242             return -1;
243         }
244
245         public int IndexOfDataSetTable(string dataSetTable) {
246             if (!ADP.IsEmpty(dataSetTable)) {
247                 for (int i = 0; i < Count; ++i) {
248                     string value = items[i].DataSetTable;
249                     if ((null != value) && (0 == ADP.DstCompare(dataSetTable, value))) {
250                         return i;
251                     }
252                 }
253             }
254             return -1;
255         }
256
257         public void Insert(int index, Object value) {
258             ValidateType(value);
259             Insert(index, (DataTableMapping) value);
260         }
261
262         public void Insert(int index, DataTableMapping value) {
263             if (null == value) {
264                 throw ADP.TablesAddNullAttempt("value");
265             }
266             Validate(-1, value);
267             value.Parent = this;
268             ArrayList().Insert(index, value);
269         }
270
271         private void RangeCheck(int index) {
272             if ((index < 0) || (Count <= index)) {
273                 throw ADP.TablesIndexInt32(index, this);
274             }
275         }
276
277         private int RangeCheck(string sourceTable) {
278             int index = IndexOf(sourceTable);
279             if (index < 0) {
280                 throw ADP.TablesSourceIndex(sourceTable);
281             }
282             return index;
283         }
284
285         public void RemoveAt(int index) {
286             RangeCheck(index);
287             RemoveIndex(index);
288         }
289
290         public void RemoveAt(string sourceTable) {
291             int index = RangeCheck(sourceTable);
292             RemoveIndex(index);
293         }
294
295         private void RemoveIndex(int index) {
296             Debug.Assert((null != items) && (0 <= index) && (index < Count), "RemoveIndex, invalid");
297             items[index].Parent = null;
298             items.RemoveAt(index);
299         }
300
301         public void Remove(object value) {
302             ValidateType(value);
303             Remove((DataTableMapping) value);
304         }
305
306         public void Remove (DataTableMapping value) {
307             if (null == value) {
308                 throw ADP.TablesAddNullAttempt ("value");
309             }
310             int index = IndexOf (value);
311
312             if (-1 != index) {
313                 RemoveIndex (index);
314             }
315             else {
316                 throw ADP.CollectionRemoveInvalidObject (ItemType, this);
317             }
318         }
319
320         private void Replace (int index, DataTableMapping newValue) {
321             Validate(index, newValue);
322             items[index].Parent = null;
323             newValue.Parent = this;
324             items[index] = newValue;
325         }
326
327         private void ValidateType(object value) {
328             if (null == value) {
329                 throw ADP.TablesAddNullAttempt("value");
330             }
331             else if (!ItemType.IsInstanceOfType(value)) {
332                 throw ADP.NotADataTableMapping(value);
333             }
334         }
335
336         private void Validate(int index, DataTableMapping value) {
337             if (null == value) {
338                 throw ADP.TablesAddNullAttempt("value");
339             }
340             if (null != value.Parent) {
341                 if (this != value.Parent) {
342                     throw ADP.TablesIsNotParent(this);
343                 }
344                 else if (index != IndexOf(value)) {
345                     throw ADP.TablesIsParent(this);
346                 }
347             }
348             String name = value.SourceTable;
349             if (ADP.IsEmpty(name)) {
350                 index = 1;
351                 do {
352                     name = ADP.SourceTable + index.ToString(System.Globalization.CultureInfo.InvariantCulture);
353                     index++;
354                 } while (-1 != IndexOf(name));
355                 value.SourceTable = name;
356             }
357             else {
358                 ValidateSourceTable(index, name);
359             }
360         }
361
362         internal void ValidateSourceTable(int index, string value) {
363             int pindex = IndexOf(value);
364             if ((-1 != pindex) && (index != pindex)) { // must be non-null and unique
365                 throw ADP.TablesUniqueSourceTable(value);
366             }
367         }
368
369         [ EditorBrowsableAttribute(EditorBrowsableState.Advanced) ] // MDAC 69508
370         static public DataTableMapping GetTableMappingBySchemaAction(DataTableMappingCollection tableMappings, string sourceTable, string dataSetTable, MissingMappingAction mappingAction) {
371             if (null != tableMappings) {
372                 int index = tableMappings.IndexOf(sourceTable);
373                 if (-1 != index) {
374 #if DEBUG
375                     if (AdapterSwitches.DataSchema.TraceWarning) {
376                         Debug.WriteLine("mapping match on SourceTable \"" + sourceTable + "\"");
377                     }
378 #endif
379                     return tableMappings.items[index];
380                 }
381             }
382             if (ADP.IsEmpty(sourceTable)) {
383                 throw ADP.InvalidSourceTable("sourceTable");
384             }
385             switch (mappingAction) {
386                 case MissingMappingAction.Passthrough:
387 #if DEBUG
388                     if (AdapterSwitches.DataSchema.TraceInfo) {
389                         Debug.WriteLine("mapping passthrough of SourceTable \"" + sourceTable + "\" -> \"" + dataSetTable + "\"");
390                     }
391 #endif
392                     return new DataTableMapping(sourceTable, dataSetTable);
393
394                 case MissingMappingAction.Ignore:
395 #if DEBUG
396                     if (AdapterSwitches.DataSchema.TraceWarning) {
397                         Debug.WriteLine("mapping filter of SourceTable \"" + sourceTable + "\"");
398                     }
399 #endif
400                     return null;
401
402                 case MissingMappingAction.Error:
403 #if DEBUG
404                     if (AdapterSwitches.DataSchema.TraceError) {
405                         Debug.WriteLine("mapping error on SourceTable \"" + sourceTable + "\"");
406                     }
407 #endif
408                     throw ADP.MissingTableMapping(sourceTable);
409
410                 default:
411                     throw ADP.InvalidMissingMappingAction(mappingAction);
412             }
413         }
414     }
415 }