2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / System.Web.DynamicData / Test / ModelProviders / DynamicDataContainerColumnProvider.cs
index a262f455653ec2577a85c2e43dee7cf18150f74e..1619ffbe19e521dae77a1f543662178f342f906c 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Web;
 using System.Web.DynamicData;
 using System.Web.DynamicData.ModelProviders;
@@ -9,25 +10,124 @@ using MonoTests.DataSource;
 
 namespace MonoTests.ModelProviders
 {
-    public class DynamicDataContainerColumnProvider : ColumnProvider
-    {
-        DynamicDataColumn column;
-
-        public DynamicDataContainerColumnProvider (DynamicDataContainerTableProvider owner, DynamicDataColumn column)
-            : base (owner)
-        {
-            if (column == null)
-                throw new ArgumentNullException ("column");
-
-            this.column = column;
-
-            Type columnType = column.DataType;
-            if (columnType == null)
-                throw new InvalidOperationException ("column.DataType must not be null for column '" + column.Name + "'");
-
-            Name = column.Name;
-            ColumnType = columnType;
-            Nullable = columnType.IsGenericType && typeof (Nullable<>).IsAssignableFrom (columnType.GetGenericTypeDefinition ());
-        }
-    }
+       public class DynamicDataContainerColumnProvider <T> : ColumnProvider
+       {
+               DynamicDataColumn column;
+               bool associationResolved;
+
+               public override AssociationProvider Association {
+                       get {
+                               ResolveAssociations ();
+                               return base.Association;
+                       }
+
+                       protected set {
+                               base.Association = value;
+                       }
+               }
+
+               public DynamicDataContainerColumnProvider (DynamicDataContainerTableProvider <T> owner, DynamicDataColumn column)
+                       : base (owner)
+               {
+                       if (column == null)
+                               throw new ArgumentNullException ("column");
+
+                       this.column = column;
+
+                       Type columnType = column.DataType;
+                       if (columnType == null)
+                               throw new InvalidOperationException ("column.TContext must not be null for column '" + column.Name + "'");
+
+                       Name = column.Name;
+                       ColumnType = columnType;
+                       Nullable = columnType.IsGenericType && typeof (Nullable<>).IsAssignableFrom (columnType.GetGenericTypeDefinition ());
+                       IsPrimaryKey = column.PrimaryKey;
+                       EntityTypeProperty = GetPropertyInfo (owner.EntityType, Name);
+                       IsCustomProperty = column.CustomProperty;
+                       IsGenerated = column.Generated;
+                       MaxLength = GetMaxLength (EntityTypeProperty);
+                       IsSortable = column.Sortable;
+               }
+
+               public void ResolveAssociations ()
+               {
+                       if (associationResolved)
+                               return;
+
+                       associationResolved = true;
+                       string associated = column.AssociatedTo;
+                       if (String.IsNullOrEmpty (associated))
+                               return;
+
+                       string[] names = associated.Split (new char[] { '.' });
+                       if (names.Length != 2)
+                               throw new ApplicationException ("Only associations of type Table.Column are supported");
+                       string tableName = names[0];
+                       string columnName = names[1];
+                       
+                       TableProvider tableProvider = null;
+                       try {
+                               tableProvider = Table.DataModel.Tables.First<TableProvider> ((TableProvider tp) => {
+                                       if (tp.Name == tableName)
+                                               return true;
+                                       return false;
+                               });
+                       } catch {
+                               return;
+                       }
+
+                       if (tableProvider == null)
+                               return;
+
+                       ColumnProvider toColumn = null;
+
+                       try {
+                               toColumn = tableProvider.Columns.First<ColumnProvider> ((ColumnProvider cp) => {
+                                       if (cp.Name == columnName)
+                                               return true;
+                                       return false;
+                               });
+                       } catch {
+                               return;
+                       }
+
+                       if (toColumn == null)
+                               return;
+
+                       IsForeignKeyComponent = true;
+                       Association = new DynamicDataAssociationProvider (column.AssociationDirection, this, toColumn);
+               }
+
+               int GetMaxLength (PropertyInfo pi)
+               {
+                       if (pi == null)
+                               return 0;
+
+                       object[] attrs = pi.GetCustomAttributes (typeof (DynamicDataStringLengthAttribute), true);
+                       if (attrs == null || attrs.Length == 0)
+                               return 0;
+
+                       var attr = attrs[0] as DynamicDataStringLengthAttribute;
+                       if (attr == null)
+                               return 0;
+
+                       return attr.MaxLength;
+               }
+
+               PropertyInfo GetPropertyInfo (Type type, string name)
+               {
+                       try {
+                               PropertyInfo ret = type.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy).
+                                       First<PropertyInfo> ((pi) => {
+                                               if (String.Compare (pi.Name, name, StringComparison.Ordinal) == 0)
+                                                       return true;
+                                               return false;
+                                       }
+                               );
+                               return ret;
+                       } catch (InvalidOperationException ex) {
+                               return null;
+                       }
+               }
+       }
 }