2004-03-15 Umadevi S (sumadevi@novell.com)
[mono.git] / mcs / class / System.Data / System.Data / Constraint.cs
1 //
2 // System.Data.Constraint.cs
3 //
4 // Author:
5 //      Franklin Wise <gracenote@earthlink.net>
6 //      Daniel Morgan
7 //      Tim Coleman (tim@timcoleman.com)
8 //   
9 //
10 // (C) Ximian, Inc. 2002
11 // Copyright (C) Tim Coleman, 2002
12 //
13
14 using System;
15 using System.Collections;
16 using System.ComponentModel;
17 using System.Runtime.InteropServices;
18 using System.Runtime.Serialization;
19
20 namespace System.Data {
21         [Serializable]
22         internal delegate void DelegateConstraintNameChange (object sender, string newName);
23
24         [DefaultProperty ("ConstraintName")]    
25         [Serializable]
26         [TypeConverterAttribute (typeof (ConstraintConverter))]
27         public abstract class Constraint 
28         {
29                 internal event DelegateConstraintNameChange BeforeConstraintNameChange;
30
31                 //if constraintName is not set then a name is 
32                 //created when it is added to
33                 //the ConstraintCollection
34                 //it can not be set to null, empty or duplicate
35                 //once it has been added to the collection
36                 private string _constraintName;
37                 private PropertyCollection _properties;
38
39                 private Index _index;
40
41                 //Used for membership checking
42                 private ConstraintCollection _constraintCollection;
43
44                 DataSet dataSet;
45
46                 protected Constraint () 
47                 {
48                         dataSet = null;
49                         _properties = new PropertyCollection();
50                 }
51
52                 protected internal virtual DataSet _DataSet {
53                         get { return dataSet; }
54                 }
55
56                 [DataCategory ("Data")]
57                 [DataSysDescription ("Indicates the name of this constraint.")]
58                 [DefaultValue ("")]
59                 public virtual string ConstraintName {
60                         get{ return "" + _constraintName; } 
61                         set{
62                                 //This should only throw an exception when it
63                                 //is a member of a ConstraintCollection which
64                                 //means we should let the ConstraintCollection
65                                 //handle exceptions when this value changes
66                                 _onConstraintNameChange(value);
67                                 _constraintName = value;
68                         }
69                 }
70
71                 [Browsable (false)]
72                 [DataCategory ("Data")]
73                 [DataSysDescription ("The collection that holds custom user information.")]
74                 public PropertyCollection ExtendedProperties {
75                         get { return _properties; }
76                 }
77
78                 [DataSysDescription ("Indicates the table of this constraint.")]
79                 public abstract DataTable Table {
80                         get;
81                 }
82
83                 internal ConstraintCollection ConstraintCollection {
84                         get{ return _constraintCollection; }
85                         set{ _constraintCollection = value; }
86                 }
87                 
88                 private void _onConstraintNameChange (string newName)
89                 {
90                         if (null != BeforeConstraintNameChange)
91                         {
92                                 BeforeConstraintNameChange (this, newName);
93                         }
94                 }
95
96                 //call once before adding a constraint to a collection
97                 //will throw an exception to prevent the add if a rule is broken
98                 internal virtual void AddToConstraintCollectionSetup (ConstraintCollection collection)
99                 {
100                 }
101                                         
102                 internal virtual void AssertConstraint ()
103                 {
104                 }
105                 
106                 internal virtual void AssertConstraint (DataRow row)
107                 {
108                 }
109
110                 internal virtual void RollbackAssert (DataRow row)
111                 {
112                 }
113
114                 //call once before removing a constraint to a collection
115                 //can throw an exception to prevent the removal
116                 internal virtual void RemoveFromConstraintCollectionCleanup (ConstraintCollection collection)
117                 {
118                 }
119
120                 [MonoTODO]
121                 protected void CheckStateForProperty ()
122                 {
123                         throw new NotImplementedException ();
124                 }
125
126                 protected internal void SetDataSet (DataSet dataSet)
127                 {
128                         this.dataSet = dataSet;
129                 }
130
131                 internal Index Index
132                 {
133                         get {
134                                 return _index;
135                         }
136                         set {
137                                 _index = value;
138                         }
139                 }
140
141                 protected internal void UpdateIndex (DataRow row)
142                 {
143                         if (row.RowState == DataRowState.Detached || row.RowState == DataRowState.Unchanged)
144                                 Index.Insert (new Node (row), DataRowVersion.Default);
145                         else if ((row.RowState == DataRowState.Modified) || (row.RowState == DataRowState.Added)) {
146                                 // first we check if the values of the key changed.
147                                 bool keyChanged = false;
148                                 for (int i = 0; i < Index.Columns.Length; i++) {
149                                         if (row[Index.Columns[i], DataRowVersion.Default] != row[Index.Columns[i], DataRowVersion.Current]) {
150                                                 keyChanged = true;
151                                         }
152                                 }
153                                 // if key changed we first try to insert a new node 
154                                 // and,if succeded, we delete the row's old node.
155                                 if (keyChanged) 
156                                 {
157                                         // insert new node for the row
158                                         // note : may throw if not succeded
159                                         Index.Insert (new Node (row), DataRowVersion.Default);
160
161                                         // delete the row's node
162                                         Index.Delete(row);                                      
163                                 }
164                         }
165                 }
166
167                 protected internal void RollbackIndex (DataRow row)
168                 {
169                         Node n = Index.Find(row, DataRowVersion.Default);
170                         if ( n == null)
171                                 throw new ConstraintException("Row was not found in constraint index");
172
173                         // first remove the node inserted as a result of last AssertConstraint on the row 
174                         Index.Delete(n);
175                         
176                         // if the row is not detached we should add back to the index 
177                         // node corresponding to row value before AssertConstraint was called
178                         if(row.RowState != DataRowState.Detached){
179                                 // since index before we updated index was ok, insert should always suceed
180                                 // maybe we still need to try/catch here
181                                 Index.Insert(new Node(row), DataRowVersion.Current);
182                         }
183                 }
184
185
186                 /// <summary>
187                 /// Gets the ConstraintName, if there is one, as a string. 
188                 /// </summary>
189                 public override string ToString () 
190                 {
191                         return "" + _constraintName;
192                 }
193
194         }
195 }