2003-03-27 Ville Palo <vi64pa@kolumbus.fi>
[mono.git] / mcs / class / System.Data / System.Data / DataRowCollection.cs
1 //
2 // System.Data.DataRowCollection.cs
3 //
4 // Author:
5 //   Daniel Morgan <danmorg@sc.rr.com>
6 //   Tim Coleman <tim@timcoleman.com>
7 //
8 // (C) Ximian, Inc 2002
9 // (C) Copyright 2002 Tim Coleman
10 // (C) Copyright 2002 Daniel Morgan
11 //
12
13 using System;
14 using System.Collections;
15 using System.ComponentModel;
16
17 namespace System.Data
18 {
19         /// <summary>
20         /// Collection of DataRows in a DataTable
21         /// </summary>
22         [Serializable]
23         public class DataRowCollection : InternalDataCollectionBase 
24         {
25                 private DataTable table;
26
27                 /// <summary>
28                 /// Internal constructor used to build a DataRowCollection.
29                 /// </summary>
30                 internal DataRowCollection (DataTable table) : base ()
31                 {
32                         this.table = table;
33                 }
34
35                 /// <summary>
36                 /// Gets the row at the specified index.
37                 /// </summary>
38                 public DataRow this[int index] 
39                 {
40                         get { 
41                                 if (index >= Count)
42                                         throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
43
44                                 return (DataRow) list[index]; 
45                         }
46                 }
47
48                 /// <summary>
49                 /// This member overrides InternalDataCollectionBase.List
50                 /// </summary>
51                 protected override ArrayList List 
52                 {
53                         get { return list; }
54                 }               
55
56                 /// <summary>
57                 /// Adds the specified DataRow to the DataRowCollection object.
58                 /// </summary>
59                 public void Add (DataRow row) 
60                 {
61                         //TODO: AutoIncrement
62                         //TODO: validation
63                         if (row == null)
64                                 throw new ArgumentNullException("row", "'row' argument cannot be null.");
65
66                         if (list.IndexOf(row) != -1)
67                                 throw new ArgumentException ("This row already belongs to this table.");
68                                 
69                         foreach (DataColumn Col in row.Table.Columns) {
70
71                                 if (Col.AutoIncrement) {
72                                         row [Col] = Col.AutoIncrementValue();
73                                 }
74                         }
75
76                         list.Add (row);
77                         row.AttachRow ();
78                         row.Table.ChangedDataRow (row, DataRowAction.Add);
79                 }
80
81                 /// <summary>
82                 /// Creates a row using specified values and adds it to the DataRowCollection.
83                 /// </summary>
84                 public virtual DataRow Add (object[] values) 
85                 {
86                         DataRow row = table.NewRow ();
87                         row.ItemArray = values;
88                         Add (row);
89                         return row;
90                 }
91
92                 /// <summary>
93                 /// Clears the collection of all rows.
94                 /// </summary>
95                 public void Clear () 
96                 {
97                         list.Clear ();
98                 }
99
100                 /// <summary>
101                 /// Gets a value indicating whether the primary key of any row in the collection contains
102                 /// the specified value.
103                 /// </summary>
104                 public bool Contains (object key) 
105                 {
106                         return Find (key) != null;
107                 }
108
109                 /// <summary>
110                 /// Gets a value indicating whether the primary key column(s) of any row in the 
111                 /// collection contains the values specified in the object array.
112                 /// </summary>
113                 public bool Contains (object[] keys) 
114                 {
115                         if (table.PrimaryKey.Length != keys.Length)
116                                 throw new ArgumentException ("Expecting " + table.PrimaryKey.Length + " value(s) for the key " + 
117                                                              "being indexed, but received " + keys.Length + " value(s).");
118
119                         return Find (keys) != null;
120                 }
121
122                 /// <summary>
123                 /// Gets the row specified by the primary key value.
124                 /// </summary>
125                 [MonoTODO]
126                 public DataRow Find (object key) 
127                 {
128                         if (table.PrimaryKey.Length == 0)
129                                 throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
130                         if (table.PrimaryKey.Length > 1)
131                                 throw new ArgumentException ("Expecting " + table.PrimaryKey.Length + 
132                                                              " value(s) for the key being indexed, but received 1 value(s).");
133
134                         string primColumnName = table.PrimaryKey [0].ColumnName;
135                         Type coltype = null;
136                         object newKey = null;
137                         
138                         foreach (DataRow row in this) {
139                                 
140                                 object primValue = row [primColumnName];
141                                 if (key == null) {
142                                         if (primValue == null)
143                                                 return row;
144                                         else 
145                                                 continue;
146                                 }
147                                        
148                                 newKey = Convert.ChangeType (key, Type.GetTypeCode(primValue.GetType ()));
149
150                                 if (primValue.Equals (newKey))
151                                         return row;
152                         }
153                                                 
154                         // FIXME: is the correct value null?
155                         return null;
156                 }
157
158                 /// <summary>
159                 /// Gets the row containing the specified primary key values.
160                 /// </summary>
161                 [MonoTODO]
162                 public DataRow Find (object[] keys) 
163                 {
164                         if (table.PrimaryKey.Length == 0)
165                                 throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
166
167                         string  [] primColumnNames = new string [table.PrimaryKey.Length];
168                         
169                         for (int i = 0; i < primColumnNames.Length; i++)
170                                 primColumnNames [i] = table.PrimaryKey [i].ColumnName;
171
172                         Type coltype = null;
173                         object newKey = null;
174                         
175                         foreach (DataRow row in this) {
176                                 
177                                 bool eq = true;
178                                 for (int i = 0; i < keys.Length; i++) {
179                                         
180                                         object primValue = row [primColumnNames [i]];
181                                         object keyValue = keys [i];
182                                         if (keyValue == null) {
183                                                 if (primValue == null)
184                                                         return row;
185                                                 else 
186                                                         continue;
187                                         }
188                                                                        
189                                         newKey = Convert.ChangeType (keyValue, Type.GetTypeCode(primValue.GetType ()));
190
191                                         if (!primValue.Equals (newKey)) {
192                                                 eq = false;
193                                                 break;
194                                         }                                               
195                                 }
196
197                                 if (eq)
198                                         return row;
199                         }
200                                                 
201                         // FIXME: is the correct value null?
202                         return null;
203                 }
204
205                 /// <summary>
206                 /// Inserts a new row into the collection at the specified location.
207                 /// </summary>
208                 public void InsertAt (DataRow row, int pos) 
209                 {
210                         if (pos < 0)
211                                 throw new IndexOutOfRangeException ("The row insert position " + pos + " is invalid.");
212                                 
213                         if (pos >= list.Count)
214                                 list.Add (row);
215                         else
216                                 list.Insert (pos, row);
217                 }
218
219                 /// <summary>
220                 /// Removes the specified DataRow from the collection.
221                 /// </summary>
222                 public void Remove (DataRow row) 
223                 {
224                         // FIXME: This is the way the MS.NET handles this kind of situation. Could be better, but what can you do.
225                         if (row == null || list.IndexOf (row) == -1)
226                                 throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
227
228                         list.Remove (row);
229                         row.DetachRow ();
230                         table.DeletedDataRow (row, DataRowAction.Delete);
231                 }
232
233                 /// <summary>
234                 /// Removes the row at the specified index from the collection.
235                 /// </summary>
236                 public void RemoveAt (int index) 
237                 {                       
238                         if (index < 0 || index >= list.Count)
239                                 throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
240
241                         DataRow row = (DataRow)list [index];
242                         list.RemoveAt (index);                  
243                         table.DeletedDataRow (row, DataRowAction.Delete);
244                 }
245
246                 ///<summary>
247                 ///Internal method used to validate a given DataRow with respect
248                 ///to the DataRowCollection
249                 ///</summary>
250                 [MonoTODO]
251                 internal void ValidateDataRowInternal(DataRow row)
252                 {
253                         //FIXME: this validates constraints in the order they appear
254                         //in the collection. Most probably we need to do it in a 
255                         //specific order like unique/primary keys first, then Foreignkeys, etc
256                         foreach(Constraint constraint in table.Constraints)
257                         {
258                                 constraint.AssertConstraint(row);
259                         }
260
261                 }
262
263         }
264 }