5e813c6e5a33496ba61ebb4d4da1ceea7ed325d5
[mono.git] / mcs / class / System.Data / System.Data / DataColumnCollection.cs
1 //
2 // System.Data.DataColumnCollection.cs
3 //
4 // Author:
5 //   Christopher Podurgiel (cpodurgiel@msn.com)
6 //
7 // (C) Chris Podurgiel
8 //
9
10 using System;
11 using System.Collections;
12 using System.ComponentModel;
13
14 namespace System.Data
15 {
16         /// <summary>
17         /// Represents a collection of DataColumn objects for a DataTable.
18         /// </summary>
19         public class DataColumnCollection : InternalDataCollectionBase
20         {
21                 
22
23                 
24                 // The defaultNameIndex is used to create a default name for a column if one wasn't given.
25                 private int defaultNameIndex;
26
27                 //table should be the DataTable this DataColumnCollection belongs to.
28                 private DataTable parentTable = null;
29
30                 // Internal Constructor.  This Class can only be created from other classes in this assembly.
31                 internal DataColumnCollection(DataTable table):base()
32                 {
33                         defaultNameIndex = 1;
34                         parentTable = table;
35                 }
36
37
38
39                 /// <summary>
40                 /// Gets the DataColumn from the collection at the specified index.
41                 /// </summary>
42                 public virtual DataColumn this[int index]
43                 {
44                         get
45                         {
46                                 return (DataColumn) base.List[index];
47                         }
48                 }
49
50                 /// <summary>
51                 /// Gets the DataColumn from the collection with the specified name.
52                 /// </summary>
53                 public virtual DataColumn this[string name]
54                 {
55                         get
56                         {
57                                 foreach (DataColumn column in base.List)
58                                 {
59                                         if (column.ColumnName == name)
60                                         {
61                                                 return column;
62                                         }
63                                 }
64
65                                 return null;
66                 
67                         }
68                 }
69
70
71                 /// <summary>
72                 /// Gets a list of the DataColumnCollection items.
73                 /// </summary>
74                 protected override ArrayList List 
75                 {
76                         get
77                         {
78                                 return base.List;
79                         }
80                 }
81
82
83                 //Add Logic
84                 //
85                 //Changing Event
86                 //DefaultValue set and AutoInc set check
87                 //?Validate Expression??
88                 //Name check and creation
89                 //Set Table
90                 //Check Unique if true then add a unique constraint
91                 //?Notify Rows of new column ?
92                 //Add to collection
93                 //Changed Event
94
95                 /// <summary>
96                 /// Creates and adds a DataColumn object to the DataColumnCollection.
97                 /// </summary>
98                 /// <returns></returns>
99                 public virtual DataColumn Add()
100                 {
101                         //FIXME:
102                         DataColumn column = new DataColumn("Column" + defaultNameIndex.ToString());
103                         CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
104                         
105                         column.SetTable(parentTable);
106                         base.List.Add(column);
107                         OnCollectionChanged(e);
108                         defaultNameIndex++;
109                         return column;
110                 }
111
112                 /// <summary>
113                 /// Creates and adds the specified DataColumn object to the DataColumnCollection.
114                 /// </summary>
115                 /// <param name="column">The DataColumn to add.</param>
116                 public void Add(DataColumn column)
117                 {       
118                         //FIXME:
119                         if(Contains(column.ColumnName))
120                         {
121                                 throw new DuplicateNameException("A column named " + column.ColumnName + " already belongs to this DataTable.");
122                         }
123                         else
124                         {
125                                 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
126                                 
127                                 column.SetTable( parentTable);
128                                 base.List.Add(column);
129                                 OnCollectionChanged(e);
130                                 return;
131                         }
132                 }
133
134                 /// <summary>
135                 /// Creates and adds a DataColumn object with the specified name to the DataColumnCollection.
136                 /// </summary>
137                 /// <param name="columnName">The name of the column.</param>
138                 /// <returns>The newly created DataColumn.</returns>
139                 public virtual DataColumn Add(string columnName)
140                 {
141                         
142                         //FIXME: this wont work.  If the user decides to add a column named
143                         //"ColumnXX" where XX is a number these two will conflict.
144                         if (columnName == null || columnName == String.Empty)
145                         {
146                                 columnName = "Column" + defaultNameIndex.ToString();
147                                 defaultNameIndex++;
148                         }
149                         
150                         if(Contains(columnName))
151                         {
152                                 throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable.");
153                         }
154                         else
155                         {
156                                 DataColumn column = new DataColumn(columnName);
157                                 
158                                 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
159                                 column.SetTable(parentTable);
160                                 base.List.Add(column);
161                                 OnCollectionChanged(e);
162                                 return column;
163                         }
164                 }
165
166                 /// <summary>
167                 /// Creates and adds a DataColumn object with the specified name and type to the DataColumnCollection.
168                 /// </summary>
169                 /// <param name="columnName">The ColumnName to use when cretaing the column.</param>
170                 /// <param name="type">The DataType of the new column.</param>
171                 /// <returns>The newly created DataColumn.</returns>
172                 public virtual DataColumn Add(string columnName, Type type)
173                 {
174                         if (columnName == null || columnName == "")
175                         {
176                                 //FIXME: this wont work.  If the user decides to add a column named
177                                 //"ColumnXX" where XX is a number these two will conflict.
178                                 columnName = "Column" + defaultNameIndex.ToString();
179                                 defaultNameIndex++;
180                         }
181
182                         if(Contains(columnName))
183                         {
184                                 throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable.");
185                         }
186                         else
187                         {
188                                 DataColumn column = new DataColumn(columnName, type);
189                                 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
190                                 column.SetTable(parentTable);
191                                 base.List.Add(column);
192                                 OnCollectionChanged(e);
193                                 return column;
194                         }
195                 }
196
197                 /// <summary>
198                 /// Creates and adds a DataColumn object with the specified name, type, and expression to the DataColumnCollection.
199                 /// </summary>
200                 /// <param name="columnName">The name to use when creating the column.</param>
201                 /// <param name="type">The DataType of the new column.</param>
202                 /// <param name="expression">The expression to assign to the Expression property.</param>
203                 /// <returns>The newly created DataColumn.</returns>
204                 public virtual DataColumn Add(string columnName, Type type,     string expression)
205                 {
206                         //FIXME: See Add Logic
207                         if (columnName == null || columnName == "")
208                         {
209                                 columnName = "Column" + defaultNameIndex.ToString();
210                                 defaultNameIndex++;
211                         }
212                         
213                         if(Contains(columnName))
214                         {
215                                 throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable.");
216                         }
217                         else
218                         {
219                                 DataColumn column = new DataColumn(columnName, type, expression);
220                                 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
221                                 column.SetTable(parentTable);
222                                 base.List.Add(column);
223                                 OnCollectionChanged(e);
224                                 return column;
225                         }
226                 }
227
228                 /// <summary>
229                 /// Copies the elements of the specified DataColumn array to the end of the collection.
230                 /// </summary>
231                 /// <param name="columns">The array of DataColumn objects to add to the collection.</param>
232                 public void AddRange(DataColumn[] columns)
233                 {
234                         foreach (DataColumn column in columns)
235                         {
236                                 Add(column);
237                         }
238                         return;
239                 }
240
241                 /// <summary>
242                 /// Checks whether a given column can be removed from the collection.
243                 /// </summary>
244                 /// <param name="column">A DataColumn in the collection.</param>
245                 /// <returns>true if the column can be removed; otherwise, false.</returns>
246                 public bool CanRemove(DataColumn column)
247                 {
248                                                 
249                         //Check that the column does not have a null reference.
250                         if (column == null)
251                         {
252                 return false;
253                         }
254
255                         
256                         //Check that the column is part of this collection.
257                         if (!Contains(column.ColumnName))
258                         {
259                                 return false;
260                         }
261
262
263                         
264                         //Check if this column is part of a relationship. (this could probably be written better)
265                         foreach (DataRelation childRelation in parentTable.ChildRelations)
266                         {
267                                 foreach (DataColumn childColumn in childRelation.ChildColumns)
268                                 {
269                                         if (childColumn == column)
270                                         {
271                                                 return false;
272                                         }
273                                 }
274
275                                 foreach (DataColumn parentColumn in childRelation.ParentColumns)
276                                 {
277                                         if (parentColumn == column)
278                                         {
279                                                 return false;
280                                         }
281                                 }
282                         }
283
284                         //Check if this column is part of a relationship. (this could probably be written better)
285                         foreach (DataRelation parentRelation in parentTable.ParentRelations)
286                         {
287                                 foreach (DataColumn childColumn in parentRelation.ChildColumns)
288                                 {
289                                         if (childColumn == column)
290                                         {
291                                                 return false;
292                                         }
293                                 }
294
295                                 foreach (DataColumn parentColumn in parentRelation.ParentColumns)
296                                 {
297                                         if (parentColumn == column)
298                                         {
299                                                 return false;
300                                         }
301                                 }
302                         }
303
304                         
305                         //Check if another column's expression depends on this column.
306                         
307                         foreach (DataColumn dataColumn in List)
308                         {
309                                 if (dataColumn.Expression.ToString().IndexOf(column.ColumnName) > 0)
310                                 {
311                                         return false;
312                                 }
313                         }
314                         
315                         //TODO: check constraints
316
317                         return true;
318                 }
319
320                 /// <summary>
321                 /// Clears the collection of any columns.
322                 /// </summary>
323                 public void Clear()
324                 {
325                         CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
326                         base.List.Clear();
327                         OnCollectionChanged(e);
328                         return;
329                 }
330
331                 /// <summary>
332                 /// Checks whether the collection contains a column with the specified name.
333                 /// </summary>
334                 /// <param name="name">The ColumnName of the column to check for.</param>
335                 /// <returns>true if a column exists with this name; otherwise, false.</returns>
336                 public bool Contains(string name)
337                 {
338                         return (IndexOf(name) != -1);
339                 }
340
341                 /// <summary>
342                 /// Gets the index of a column specified by name.
343                 /// </summary>
344                 /// <param name="column">The name of the column to return.</param>
345                 /// <returns>The index of the column specified by column if it is found; otherwise, -1.</returns>
346                 public virtual int IndexOf(DataColumn column)
347                 {
348                         return base.List.IndexOf(column);
349                 }
350
351                 /// <summary>
352                 /// Gets the index of the column with the given name (the name is not case sensitive).
353                 /// </summary>
354                 /// <param name="columnName">The name of the column to find.</param>
355                 /// <returns>The zero-based index of the column with the specified name, or -1 if the column doesn't exist in the collection.</returns>
356                 public int IndexOf(string columnName)
357                 {
358                         
359                         DataColumn column = this[columnName];
360                         
361                         if (column != null)
362                         {
363                                 return IndexOf(column);
364                         }
365                         else
366                         {
367                                 return -1;
368                         }
369                 }
370
371                 /// <summary>
372                 /// Raises the OnCollectionChanged event.
373                 /// </summary>
374                 /// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
375                 protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent)
376                 {
377                         if (CollectionChanged != null) 
378                         {
379                                 CollectionChanged(this, ccevent);
380                         }
381                 }
382
383                 /// <summary>
384                 /// Raises the OnCollectionChanging event.
385                 /// </summary>
386                 /// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
387                 protected internal virtual void OnCollectionChanging(CollectionChangeEventArgs ccevent)
388                 {
389                         if (CollectionChanged != null) 
390                         {
391                                 //FIXME: this is not right
392                                 //CollectionChanged(this, ccevent);
393                                 throw new NotImplementedException();
394                         }
395                 }
396
397                 /// <summary>
398                 /// Removes the specified DataColumn object from the collection.
399                 /// </summary>
400                 /// <param name="column">The DataColumn to remove.</param>
401                 public void Remove(DataColumn column)
402                 {
403                         //TODO: can remove first with exceptions
404                         //and OnChanging Event
405                         CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
406                         base.List.Remove(column);
407                         OnCollectionChanged(e);
408                         return;
409                 }
410
411                 /// <summary>
412                 /// Removes the DataColumn object with the specified name from the collection.
413                 /// </summary>
414                 /// <param name="name">The name of the column to remove.</param>
415                 public void Remove(string name)
416                 {
417                         //TODO: can remove first with exceptions
418                         //and OnChanging Event
419                         DataColumn column = this[name];
420                         CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
421                         base.List.Remove(column);
422                         OnCollectionChanged(e);
423                         return;
424                 }
425
426                 /// <summary>
427                 /// Removes the column at the specified index from the collection.
428                 /// </summary>
429                 /// <param name="index">The index of the column to remove.</param>
430                 public void RemoveAt(int index)
431                 {
432                         //TODO: can remove first with exceptions
433                         //and OnChanging Event
434                         CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
435                         base.List.RemoveAt(index);
436                         OnCollectionChanged(e);
437                         return;
438                 }
439
440                 /// <summary>
441                 /// Occurs when the columns collection changes, either by adding or removing a column.
442                 /// </summary>
443                 public event CollectionChangeEventHandler CollectionChanged;
444
445         }
446 }