crashanalysercmd/Libraries/Engine/CrashItemLib/Crash/Base/DataBinding/CIDBModel.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Text;
       
    19 using System.Collections.Generic;
       
    20 using System.Reflection;
       
    21 using System.ComponentModel;
       
    22 
       
    23 namespace CrashItemLib.Crash.Base.DataBinding
       
    24 {
       
    25     public class CIDBModel : IEnumerable<CIDBRow>
       
    26 	{
       
    27 		#region Constructors
       
    28         public CIDBModel( CIElement aElement, bool aAutoPopulate )
       
    29         {
       
    30             iElement = aElement;
       
    31             iAutoPopulate = aAutoPopulate;
       
    32         }
       
    33 		#endregion
       
    34 
       
    35         #region API
       
    36         public void Add( CIDBColumn aColumn )
       
    37         {
       
    38             aColumn.Model = this;
       
    39             iColumns.Add( aColumn );
       
    40         }
       
    41 
       
    42         public void Add( CIDBRow aRow )
       
    43         {
       
    44             aRow.Model = this;
       
    45             iRows.Add( aRow );
       
    46         }
       
    47 
       
    48         public void Add( params CIDBCell[] aCells )
       
    49         {
       
    50             CIDBRow row = new CIDBRow( aCells );
       
    51             Add( row );
       
    52         }
       
    53 
       
    54         public void ClearRows()
       
    55         {
       
    56             iRows.Clear();
       
    57         }
       
    58 
       
    59         public void ClearColumns()
       
    60         {
       
    61             iColumns.Clear();
       
    62         }
       
    63 
       
    64         public void TryAutoPopulateColumns( CIElement aElement )
       
    65         {
       
    66             Type customAttributeType = typeof( CIDBAttributeColumn );
       
    67             Type thisObjectType = aElement.GetType();
       
    68 
       
    69             object[] attribs = thisObjectType.GetCustomAttributes( customAttributeType, true );
       
    70             if ( attribs != null && attribs.Length > 0 )
       
    71             {
       
    72                 ExtractAttributeColumns( attribs, aElement );
       
    73             }
       
    74         }
       
    75 
       
    76         public void TryAutoPopulateCells( CIElement aElement )
       
    77         {
       
    78             if ( AutoPopulate )
       
    79             {
       
    80                 SortedDictionary<int, CIDBRow> rows = new SortedDictionary<int, CIDBRow>();
       
    81                 
       
    82                 Type customAttributeType = typeof( CIDBAttributeCell );
       
    83                 Type thisObjectType = aElement.GetType();
       
    84 
       
    85                 // Get properties featuring the CIDBAttribute 
       
    86                 PropertyInfo[] propertyInfo = thisObjectType.GetProperties();
       
    87                 foreach ( PropertyInfo p in propertyInfo )
       
    88                 {
       
    89                     object[] attribs = p.GetCustomAttributes( customAttributeType, true );
       
    90                     if ( attribs != null && attribs.Length > 0 )
       
    91                     {
       
    92                         object propertyValue = p.GetValue( aElement, null );
       
    93                         ExtractAttributeCells( p.ToString(), aElement, attribs, propertyValue, rows );
       
    94                     }
       
    95                 }
       
    96 
       
    97                 // Same, but get methods featuring the CIDBAttribute 
       
    98                 MethodInfo[] methodInfo = thisObjectType.GetMethods();
       
    99                 foreach ( MethodInfo m in methodInfo )
       
   100                 {
       
   101                     object[] attribs = m.GetCustomAttributes( customAttributeType, true );
       
   102                     if ( attribs != null && attribs.Length > 0 )
       
   103                     {
       
   104                         // We only support this attribute on methods that don't contain
       
   105                         // any arguments
       
   106                         int paramCount = m.GetParameters().Length;
       
   107                         if ( paramCount != 0 )
       
   108                         {
       
   109                             throw new NotSupportedException( "Method: " + m.ToString() + " has CIDBAttribute but non-empty parameter list -> Not supported" );
       
   110                         }
       
   111 
       
   112                         // Get property value 
       
   113                         object propertyValue = m.Invoke( aElement, null );
       
   114                         ExtractAttributeCells( m.ToString(), aElement, attribs, propertyValue, rows );
       
   115                     }
       
   116                 }
       
   117 
       
   118                 // Since the list is already sorted for us, just add the items in order
       
   119                 foreach ( KeyValuePair<int, CIDBRow> kvp in rows )
       
   120                 {
       
   121                     this.Add( kvp.Value );
       
   122                 }
       
   123             }
       
   124         }
       
   125         #endregion
       
   126 
       
   127         #region Properties
       
   128         public bool AutoPopulate
       
   129         {
       
   130             get { return iAutoPopulate; }
       
   131         }
       
   132 
       
   133         public CIElement Element
       
   134         {
       
   135             get { return iElement; }
       
   136         }
       
   137 
       
   138         public List<CIDBColumn> Columns
       
   139         {
       
   140             get { return iColumns; }
       
   141         }
       
   142 
       
   143         public List<CIDBRow> Rows
       
   144         {
       
   145             get { return iRows; }
       
   146         }
       
   147         #endregion
       
   148 
       
   149         #region Internal methods
       
   150         private void ExtractAttributeColumns( object[] aColumnAttributes, CIElement aElement )
       
   151         {
       
   152             bool foundColumnAttributes = false;
       
   153             SortedDictionary<int, CIDBColumn> columns = new SortedDictionary<int,CIDBColumn>();
       
   154 
       
   155             foreach ( object obj in aColumnAttributes )
       
   156             {
       
   157                 if ( obj is CIDBAttributeColumn )
       
   158                 {
       
   159                     CIDBAttributeColumn attribute = (CIDBAttributeColumn) obj;
       
   160 
       
   161                     // Make a column
       
   162                     CIDBColumn col = new CIDBColumn( attribute.Caption );
       
   163                     col.Width = attribute.Width;
       
   164                     col.WidthSet = attribute.WidthSet;
       
   165                     col.TakesUpSlack = attribute.TakesUpSlack;
       
   166 
       
   167                     if ( columns.ContainsKey( attribute.Order ) )
       
   168                     {
       
   169                         throw new Exception( string.Format( "Column: [{0}] in element: [{1}] specifies order: {2} which is already in use",
       
   170                                                             attribute.Caption, aElement, attribute.Order ) );
       
   171                     }
       
   172 
       
   173                     columns.Add( attribute.Order, col );
       
   174                     foundColumnAttributes = true;
       
   175                 }
       
   176             }
       
   177 
       
   178             // Since the list is already sorted for us, just add the items in order
       
   179             foreach ( KeyValuePair<int, CIDBColumn> kvp in columns )
       
   180             {
       
   181                 this.Add( kvp.Value );
       
   182             }
       
   183 
       
   184             // We'll override the auto populate feature if we find a valid
       
   185             // column attribute
       
   186             iAutoPopulate = foundColumnAttributes;
       
   187         }
       
   188 
       
   189         private void ExtractAttributeCells( string aEntityName, CIElement aElement, object[] aCIDBAttributeEntries, object aValue, SortedDictionary<int, CIDBRow> aRows )
       
   190         {
       
   191             foreach ( object obj in aCIDBAttributeEntries )
       
   192             {
       
   193                 if ( obj is CIDBAttributeCell )
       
   194                 {
       
   195                     CIDBAttributeCell attribute = (CIDBAttributeCell) obj;
       
   196 
       
   197                     // If the property is an 'auto expand' entry, then don't look at this
       
   198                     // property, but instead look at the object itself
       
   199                     if ( attribute.Options == CIDBAttributeCell.TOptions.EAutoExpand )
       
   200                     {
       
   201                         // The object must be an element
       
   202                         CIElement element = aValue as CIElement;
       
   203                         if ( element == null )
       
   204                         {
       
   205                             throw new ArgumentException( "CIDBAttributeCell(TOptions.EAutoExpand) may only be applied to CIElement objects" );
       
   206                         }
       
   207 
       
   208                         TryAutoPopulateCells( element );
       
   209                     }
       
   210                     else
       
   211                     {
       
   212                         // Whether or not to create a row
       
   213                         bool makeRow = true;
       
   214 
       
   215                         // Convert attribute value to string. If the object is an enum, we'll check if it has
       
   216                         // a System.ComponentModel.Description attached to it, and use that in preference to a raw
       
   217                         // value.
       
   218                         string defaultValueString = ( attribute.DefaultValue != null ) ? attribute.DefaultValue.ToString() : null;
       
   219                         string propertyValueString = aValue.ToString();
       
   220                         if ( aValue.GetType().BaseType == typeof( Enum ) )
       
   221                         {
       
   222                             // Check if it supports System.ComponentModel.Description
       
   223                             FieldInfo fi = aValue.GetType().GetField( propertyValueString );
       
   224                             if ( fi != null )
       
   225                             {
       
   226                                 DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes( typeof( DescriptionAttribute ), false );
       
   227                                 if ( attributes != null && attributes.Length > 0 )
       
   228                                 {
       
   229                                     propertyValueString = attributes[ 0 ].Description;
       
   230                                 }
       
   231                             }
       
   232                         }
       
   233                         else if ( attribute.Format.Length > 0 && aValue is IFormattable )
       
   234                         {
       
   235                             string formatSpec = attribute.Format;
       
   236                             IFormattable formattable = (IFormattable) aValue;
       
   237                             propertyValueString = formattable.ToString( formatSpec, null );
       
   238 
       
   239                             // Also get the default value if available
       
   240                             bool defaultIsFormattable = attribute.DefaultValue is IFormattable;
       
   241                             if ( attribute.DefaultValue != null && defaultIsFormattable )
       
   242                             {
       
   243                                 formattable = (IFormattable) attribute.DefaultValue;
       
   244                                 defaultValueString = formattable.ToString( formatSpec, null );
       
   245                             }
       
   246                         }
       
   247 
       
   248                         // If the value of the property is the same as the default, then don't
       
   249                         // show it.
       
   250                         if ( defaultValueString != null )
       
   251                         {
       
   252                             makeRow = ( defaultValueString.CompareTo( propertyValueString ) != 0 );
       
   253                         }
       
   254 
       
   255                         // Make a row
       
   256                         if ( makeRow )
       
   257                         {
       
   258                             CIDBRow row = new CIDBRow();
       
   259                             row.Add( new CIDBCell( attribute.Caption ) );
       
   260                             row.Add( new CIDBCell( propertyValueString, attribute.ForeColor, attribute.BackColor, attribute.Format ) );
       
   261 
       
   262                             // Add the row if it doesn't exist. If it does, then that implies
       
   263                             // duplicate ordering, which we treat as a programming error.
       
   264                             if ( aRows.ContainsKey( attribute.Order ) )
       
   265                             {
       
   266                                 throw new Exception( string.Format( "Entity: [{0}] in element: [{1}] specifies order: {2} which is already in use",
       
   267                                                                     aEntityName, aElement, attribute.Order ) );
       
   268                             }
       
   269 
       
   270                             aRows.Add( attribute.Order, row );
       
   271                         }
       
   272                     }
       
   273                 }
       
   274             }
       
   275         }
       
   276         #endregion
       
   277 
       
   278         #region From IEnumerable<CIDBRow>
       
   279         public IEnumerator<CIDBRow> GetEnumerator()
       
   280         {
       
   281             foreach ( CIDBRow row in iRows )
       
   282             {
       
   283                 yield return row;
       
   284             }
       
   285         }
       
   286 
       
   287         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
       
   288         {
       
   289             foreach ( CIDBRow row in iRows )
       
   290             {
       
   291                 yield return row;
       
   292             }
       
   293         }
       
   294         #endregion
       
   295 
       
   296         #region Data members
       
   297         private readonly CIElement iElement;
       
   298         private bool iAutoPopulate = false;
       
   299         private List<CIDBColumn> iColumns = new List<CIDBColumn>();
       
   300         private List<CIDBRow> iRows = new List<CIDBRow>();
       
   301 		#endregion
       
   302     }
       
   303 }