Fixed handling of modifier keys in KeyEventArgs constructor (bug #6707)
[mono.git] / mcs / class / System.Web.DynamicData / System.Web.DynamicData / MetaModel.cs
1 //
2 // MetaModel.cs
3 //
4 // Authors:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //      Marek Habersack <mhabersack@novell.com>
7 //
8 // Copyright (C) 2008 Novell Inc. http://novell.com
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.Collections.ObjectModel;
35 using System.Collections.Specialized;
36 using System.ComponentModel;
37 using System.Globalization;
38 using System.Security.Permissions;
39 using System.Security.Principal;
40 using System.Web.Caching;
41 using System.Web.DynamicData.ModelProviders;
42
43 namespace System.Web.DynamicData
44 {
45         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47         public class MetaModel
48         {
49                 const string DEFAULT_DYNAMIC_DATA_VIRTUAL_FOLDER_PATH = "~/DynamicData/";
50                 
51                 static object registered_models_lock = new object ();
52                 
53                 static MetaModel default_model;
54                 static Exception registration_exception;
55                 static Dictionary<Type, MetaModel> registered_models;
56
57                 string dynamicDataFolderVirtualPath;
58                 
59                 public static MetaModel Default {
60                         get { return default_model; }
61                         internal set { default_model = value; }
62                 }
63
64                 public static MetaModel GetModel (Type contextType)
65                 {
66                         if (contextType == null)
67                                 throw new ArgumentNullException ("contextType");
68
69                         MetaModel m;
70                         if (!TryGetModel (contextType, out m))
71                                 throw new InvalidOperationException (String.Format ("Type '{0}' is not registered as a MetaModel", contextType));
72
73                         return m;
74                 }
75
76                 public static void ResetRegistrationException ()
77                 {
78                         registration_exception = null;
79                 }
80
81                 public MetaModel ()
82                 {
83                         if (default_model == null)
84                                 default_model = this;
85
86                         FieldTemplateFactory ftf = new FieldTemplateFactory ();
87                         ftf.Initialize (this);
88                         FieldTemplateFactory = ftf;
89                         
90                         Tables = new ReadOnlyCollection<MetaTable> (new MetaTable [0]);
91                         VisibleTables = new List<MetaTable> ();
92                 }
93
94                 public string DynamicDataFolderVirtualPath {
95                         get {
96                                 if (dynamicDataFolderVirtualPath == null)
97                                         return DEFAULT_DYNAMIC_DATA_VIRTUAL_FOLDER_PATH;
98
99                                 return dynamicDataFolderVirtualPath;
100                         }
101                         
102                         set {
103                                 if (!String.IsNullOrEmpty (value))
104                                         dynamicDataFolderVirtualPath = VirtualPathUtility.AppendTrailingSlash (value);
105                                 else
106                                         dynamicDataFolderVirtualPath = value;
107                         }
108                 }
109
110                 public IFieldTemplateFactory FieldTemplateFactory { get; set; }
111
112                 public ReadOnlyCollection<MetaTable> Tables { get; private set; }
113
114                 public List<MetaTable> VisibleTables { get; private set; }
115
116                 void CheckRegistrationError ()
117                 {
118                         if (registration_exception != null)
119                                 throw new InvalidOperationException ("An error occured during context model registration", registration_exception);
120                 }
121                 
122                 public string GetActionPath (string tableName, string action, object row)
123                 {
124                         return GetTable (tableName).GetActionPath (action, row);
125                 }
126
127                 internal static void GetDataFieldAttribute <T> (AttributeCollection attributes, ref T backingField) where T: Attribute
128                 {
129                         if (backingField != null)
130                                 return;
131
132                         foreach (Attribute attr in attributes) {
133                                 if (attr == null || !typeof (T).IsAssignableFrom (attr.GetType ()))
134                                         continue;
135
136                                 backingField = attr as T;
137                                 break;
138                         }
139                 }
140                 
141                 public MetaTable GetTable (string uniqueTableName)
142                 {
143                         MetaTable mt;
144                         if (TryGetTable (uniqueTableName, out mt))
145                                 return mt;
146                         throw new ArgumentException (String.Format ("Table '{0}' does not exist in registered context", uniqueTableName));
147                 }
148
149                 public MetaTable GetTable (Type entityType)
150                 {
151                         if (entityType == null)
152                                 throw new ArgumentNullException ("entityType");
153
154                         foreach (var t in Tables) {
155                                 if (t.EntityType == entityType)
156                                         return t;
157                         }
158                         
159                         throw new ArgumentException (String.Format ("Entity type '{0}' does not exist in registered context", entityType));
160                 }
161
162                 public MetaTable GetTable (string tableName, Type contextType)
163                 {
164                         if (tableName == null)
165                                 throw new ArgumentNullException ("tableName");
166
167                         MetaModel model;
168                         if (contextType != null && !TryGetModel (contextType, out model))
169                                 throw new ArgumentException ("Unknown context type '" + contextType + "'. This context type has not been registered.");
170                         
171                         return GetModel (contextType).GetTable (tableName);
172                 }
173                 
174                 internal static ICustomTypeDescriptor GetTypeDescriptor (Type type)
175                 {
176                         return TypeDescriptor.GetProvider (type).GetTypeDescriptor (type);
177                 }
178
179                 public void RegisterContext (Func<object> contextFactory)
180                 {
181                         RegisterContext (contextFactory, null);
182                 }
183
184                 public void RegisterContext (Type contextType)
185                 {
186                         RegisterContext (contextType, null);
187                 }
188
189                 public void RegisterContext (DataModelProvider dataModelProvider)
190                 {
191                         RegisterContext (dataModelProvider, null);
192                 }
193
194                 public void RegisterContext (Type contextType, ContextConfiguration configuration)
195                 {
196                         if (contextType == null)
197                                 throw new ArgumentNullException ("contextType");
198                         CheckRegistrationError ();
199                         RegisterContext (() => Activator.CreateInstance (contextType), configuration);
200                         RegisterModel (contextType, this, configuration);
201                 }
202
203                 public void RegisterContext (Func<object> contextFactory, ContextConfiguration configuration)
204                 {
205                         if (contextFactory == null)
206                                 throw new ArgumentNullException ("contextFactory");
207                         CheckRegistrationError ();
208                         try {
209                                 // FIXME: entity framework support is not done.
210                                 RegisterContextCore (new DLinqDataModelProvider (contextFactory), configuration);
211                         } catch (Exception ex) {
212                                 registration_exception = ex;
213                                 throw;
214                         }
215                 }
216
217                 public void RegisterContext (DataModelProvider dataModelProvider, ContextConfiguration configuration)
218                 {
219                         if (dataModelProvider == null)
220                                 throw new ArgumentNullException ("dataModelProvider");
221                         CheckRegistrationError ();
222                         try {
223                                 RegisterContextCore (dataModelProvider, configuration);
224                         } catch (Exception ex) {
225                                 registration_exception = ex;
226                                 throw;
227                         }
228                 }
229
230                 void RegisterContextCore (DataModelProvider dataModelProvider, ContextConfiguration configuration)
231                 {
232                         RegisterModel (dataModelProvider.ContextType, this, configuration);
233                         
234                         var l = new List<MetaTable> (Tables);
235                         foreach (var t in dataModelProvider.Tables)
236                                 l.Add (new MetaTable (this, t, configuration));
237                         
238                         Tables = new ReadOnlyCollection<MetaTable> (l);
239
240                         foreach (MetaTable t in l)
241                                 t.Init ();
242                         
243                         VisibleTables = l;
244                 }
245
246                 static void RegisterModel (Type contextType, MetaModel model, ContextConfiguration configuration)
247                 {
248                         lock (registered_models_lock) {
249                                 if (registered_models == null)
250                                         registered_models = new Dictionary <Type, MetaModel> ();
251
252                                 if (registered_models.ContainsKey (contextType))
253                                         return;
254
255                                 registered_models.Add (contextType, model);
256                         }
257                         RegisterTypeDescriptionProvider (contextType, configuration);
258                 }
259
260                 static void RegisterTypeDescriptionProvider (Type type, ContextConfiguration config)
261                 {
262                         Func <Type, TypeDescriptionProvider> factory = config == null ? null : config.MetadataProviderFactory;
263                         if (config == null || factory == null)
264                                 return;
265
266                         TypeDescriptionProvider provider = factory (type);
267                         if (provider == null)
268                                 return;
269
270                         TypeDescriptor.AddProvider (provider, type);
271                 }
272
273                 public bool TryGetTable (string uniqueTableName, out MetaTable table)
274                 {
275                         if (uniqueTableName == null)
276                                 throw new ArgumentNullException ("uniqueTableName");
277                         foreach (var t in Tables)
278                                 if (t.Name == uniqueTableName) {
279                                         table = t;
280                                         return true;
281                                 }
282                         table = null;
283                         return false;
284                 }
285
286                 static bool TryGetModel (Type contextType, out MetaModel model)
287                 {
288                         model = null;
289                         if (registered_models != null && registered_models.TryGetValue (contextType, out model))
290                                 return model != null;
291
292                         return false;
293                 }
294                 
295         }
296 }