/* * Box Social™ * http://boxsocial.net/ * Copyright © 2007, David Lachlan Smith * * $Id:$ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; using System.Data; using System.Reflection; using System.Diagnostics; using System.Text; using System.Web; using System.Web.Caching; using BoxSocial.IO; namespace BoxSocial.Internals { public abstract class Item { public const long MYSQL_TEXT = 65535L; public const long MYSQL_MEDIUM_TEXT = 16777215L; public const long MYSQL_LONG_TEXT = 4294967295L; public const long NAMESPACE = 31L; public const long IP = 50L; /// /// Database object /// protected Mysql db; /// /// Core token /// protected Core core; private Assembly assembly; private List updatedItems; public delegate void ItemLoadHandler(); public delegate void ItemChangeAuthenticationProviderHandler(object sender, ItemChangeAuthenticationProviderEventArgs e); public delegate void ItemDeletedEventHandler(object sender, ItemDeletedEventArgs e); public event ItemLoadHandler ItemLoad; public event ItemChangeAuthenticationProviderHandler ItemChangeAuthenticationProvider; public event EventHandler OnUpdate; public event EventHandler OnDelete; public event EventHandler ItemUpdated; public event ItemDeletedEventHandler ItemDeleted; public Bbcode Bbcode { get { return core.Bbcode; } } private Functions Functions { get { return core.Functions; } } protected Item(Core core) { this.core = core; this.db = core.Db; assembly = Assembly.GetCallingAssembly(); updatedItems = new List(); } public static string GetPrimaryKey(Type type) { List fields = GetFields(type); string keyField = string.Empty; foreach (DataFieldInfo field in fields) { if ((field.Key & DataFieldKeys.Primary) == DataFieldKeys.Primary) { keyField = field.Name; } } if (string.IsNullOrEmpty(keyField)) { // Error throw new NoPrimaryKeyException(); } return keyField; } protected void LoadItem(long primaryKey, params FieldValuePair[] keyFields) { LoadItem(this.GetType(), primaryKey, keyFields); } protected void LoadItem(long primaryKey) { LoadItem(this.GetType(), primaryKey, null); } protected void LoadItem(Type type, long primaryKey, params FieldValuePair[] keyFields) { // 1. Discover primary key // 2. Build query // 3. Execute query // 4. Fill results string tableName = GetTable(type); List fields = GetFields(type); string keyField = string.Empty; SelectQuery query = new SelectQuery(tableName); foreach (DataFieldInfo field in fields) { if ((field.Key & DataFieldKeys.Primary) == DataFieldKeys.Primary) { keyField = field.Name; } query.AddFields(field.Name); } if (string.IsNullOrEmpty(keyField)) { // Error throw new NoPrimaryKeyException(); } query.AddCondition(keyField, primaryKey); if (keyFields != null) { foreach (FieldValuePair fvp in keyFields) { query.AddCondition(fvp.Field, fvp.Value); } } /*DataTable itemTable = Query(query); if (itemTable.Rows.Count == 1) { loadItemInfo(type, itemTable.Rows[0]); } else { // Error throw new InvalidItemException(this.GetType().FullName); }*/ loadItemInfo(type, core.Db.ReaderQuery(query)); } protected void LoadItem(string uniqueIndex, object value) { LoadItem(uniqueIndex, value, false); } protected void LoadItem(string uniqueIndex, object value, bool caseInsensitive) { // 1. check index is unique // 2. Build query // 3. Execute query // 4. Fill results string tableName = GetTable(this.GetType()); List fields = GetFields(this.GetType()); string keyField = string.Empty; SelectQuery query = new SelectQuery(tableName); foreach (DataFieldInfo field in fields) { if (field.Name == uniqueIndex) { if ((field.Key & (DataFieldKeys.Unique | DataFieldKeys.Primary)) != DataFieldKeys.None) { keyField = field.Name; } else { throw new FieldNotUniqueIndexException(field.Name); } } query.AddFields(field.Name); } if (value is string && caseInsensitive) { query.AddCondition(new QueryFunction(keyField, QueryFunctions.ToLowerCase), ((string)value).ToLower()); } else { query.AddCondition(keyField, value); } /*DataTable itemTable = Query(query); if (itemTable.Rows.Count == 1) { loadItemInfo(itemTable.Rows[0]); if (ItemLoad != null) { ItemLoad(); } } else { // Error throw new InvalidItemException(this.GetType().FullName); }*/ loadItemInfo(this.GetType(), core.Db.ReaderQuery(query)); } protected void LoadItem(string ownerIdIndex, string ownerTypeIndex, Primitive owner) { // 1. check indexes are unique // 2. Build query // 3. Execute query // 4. Fill results string tableName = GetTable(this.GetType()); List fields = GetFields(this.GetType()); SelectQuery query = new SelectQuery(tableName); foreach (DataFieldInfo field in fields) { if (field.Name == ownerIdIndex || field.Name == ownerTypeIndex) { if ((field.Key & DataFieldKeys.Unique) != DataFieldKeys.Unique) { throw new FieldNotUniqueIndexException(); } } query.AddFields(field.Name); } query.AddCondition(ownerIdIndex, owner.Id); query.AddCondition(ownerTypeIndex, owner.TypeId); /*DataTable itemTable = Query(query); if (itemTable.Rows.Count == 1) { loadItemInfo(itemTable.Rows[0]); if (ItemLoad != null) { ItemLoad(); } } else { // Error throw new InvalidItemException(this.GetType().FullName); }*/ loadItemInfo(this.GetType(), core.Db.ReaderQuery(query)); } protected List getSubTypes() { List types = new List(); Type currentType = this.GetType(); Type[] allTypes = currentType.Assembly.GetTypes(); foreach (Type type in allTypes) { List fields = GetFields(type); foreach (DataFieldInfo field in fields) { if (field.ParentType == currentType) { types.Add(type); break; } } } return types; } protected void UpdateThis() { StackTrace st = new StackTrace(); StackFrame sf = st.GetFrame(1); updatedItems.Add(sf.GetMethod().Name); } protected void SetProperty(string key, object value) { try { Type thisType = this.GetType(); FieldInfo fi = thisType.GetField(key, BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); if ((fi.GetValue(this) == null && value != null )|| (!fi.GetValue(this).Equals(value))) { fi.SetValue(this, value); if (!updatedItems.Contains(key)) { updatedItems.Add(key); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } protected bool HasPropertyUpdated(string key) { if (updatedItems.Contains(key)) { return true; } else { return false; } } protected DataTable Query(SelectQuery query) { return db.Query(query); } protected long Query(InsertQuery query) { return db.Query(query); } protected long Query(UpdateQuery query) { return db.Query(query); } protected long Query(DeleteQuery query) { return db.Query(query); } public string Namespace { get { return GetNamespace(this.GetType()); } } public abstract string Uri { get; } protected List getTags() { List tags = new List(); return tags; } protected Primitive fillOwner(long ownerId, long ownerTypeId) { Primitive owner; Type type = core.GetPrimitiveType(ownerTypeId); if (type.IsSubclassOf(typeof(Primitive))) { owner = System.Activator.CreateInstance(type, new object[] { core, ownerId }) as Primitive; return owner; } else { return null; } } /// /// returns the field that is linked to the parent of a given type /// /// /// public static string GetParentField(Type parentType) { string returnValue = null; Type[] types = parentType.Assembly.GetTypes(); foreach (Type type in types) { List fields = GetFields(type); foreach (DataFieldInfo field in fields) { if (field.ParentType == parentType) { if (string.IsNullOrEmpty(returnValue)) { returnValue = field.Name; } else { // TODO: create a new exception throw new Exception("Multiple children types"); } } } } if (!string.IsNullOrEmpty(returnValue)) { return returnValue; } else { // TODO: Exception throw new Exception("No parent of type " + parentType.Name + " found."); } } public static string GetParentField(Type parentType, Type childType) { string returnValue = null; List fields = GetFields(childType); foreach (DataFieldInfo field in fields) { if (field.ParentType == parentType) { if (string.IsNullOrEmpty(returnValue)) { returnValue = field.Name; } else { // TODO: create a new exception throw new Exception("Multiple children types."); } } } if (!string.IsNullOrEmpty(returnValue)) { return returnValue; } else { // TODO: Exception throw new Exception("No parent of type " + childType.Name + " found."); } } public SelectQuery GetSelectQueryStub() { return GetSelectQueryStub(this.GetType()); } public static SelectQuery GetSelectQueryStub(Type type) { return GetSelectQueryStub(type, true); } /// /// /// /// /// Check for redefined _GetSelectQueryStub /// public static SelectQuery GetSelectQueryStub(Type type, bool check) { SelectQuery query; if (check && type.GetMethod(type.Name + "_GetSelectQueryStub", Type.EmptyTypes) != null) { query = (SelectQuery)type.InvokeMember(type.Name + "_GetSelectQueryStub", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { }); //GetSelectQueryStub(typeToGet); } else { query = new SelectQuery(GetTable(type)); query.AddFields(GetFieldsPrefixed(type)); /*Type[] interfaces = type.GetInterfaces(); foreach (Type i in interfaces) { if (i == typeof(IPermissibleItem)) { //query.AddFields(GetFieldsPrefixed(typeof(AccessControlGrant))); /* * / } }*/ } return query; } public SelectQuery getSelectQueryStub() { Type type = this.GetType(); SelectQuery query = new SelectQuery(GetTable(type)); query.AddFields(GetFieldsPrefixed(type)); return query; } private static Object itemFieldsCacheLock = new Object(); private static Dictionary> itemFieldsCache = null; private static void populateItemFieldsCache() { object o = null; System.Web.Caching.Cache cache; if (HttpContext.Current != null && HttpContext.Current.Cache != null) { cache = HttpContext.Current.Cache; } else { cache = new Cache(); } try { if (cache != null) { o = cache.Get("itemFields"); } } catch (NullReferenceException) { } lock (itemFieldsCacheLock) { if (o != null && o is Dictionary>) { itemFieldsCache = (Dictionary>)o; } else { itemFieldsCache = new Dictionary>(); } } } internal protected static List GetFields(Type type) { return GetFields(type, false); } internal protected static List GetRawFields(Type type) { return GetFields(type, true); } internal protected static List GetFields(Type type, bool getRawFields) { List returnValue = new List(); if (itemFieldsCache != null) { if (itemFieldsCache.ContainsKey(type) && (!getRawFields)) { return itemFieldsCache[type]; } } else { populateItemFieldsCache(); } foreach (FieldInfo fi in type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { foreach (Attribute attr in Attribute.GetCustomAttributes(fi, typeof(DataFieldAttribute))) { DataFieldAttribute dfattr = (DataFieldAttribute)attr; if (dfattr.FieldName != null) { if ((fi.FieldType == typeof(ItemKey)) && (!getRawFields)) { DataFieldInfo dfiId; DataFieldInfo dfiTypeId; dfiId = new DataFieldInfo(dfattr.FieldName + "_id", typeof(long), dfattr.MaxLength, dfattr.Index); dfiTypeId = new DataFieldInfo(dfattr.FieldName + "_type_id", typeof(long), dfattr.MaxLength, dfattr.Index); dfiId.ParentType = dfattr.ParentType; dfiId.ParentFieldName = dfattr.ParentFieldName; dfiTypeId.ParentType = dfattr.ParentType; dfiTypeId.ParentFieldName = dfattr.ParentFieldName; returnValue.Add(dfiId); returnValue.Add(dfiTypeId); } else { DataFieldInfo dfi; dfi = new DataFieldInfo(dfattr.FieldName, fi.FieldType, dfattr.MaxLength, dfattr.Index); dfi.ParentType = dfattr.ParentType; dfi.ParentFieldName = dfattr.ParentFieldName; returnValue.Add(dfi); } } else { returnValue.Add(new DataFieldInfo(fi.Name, fi.FieldType, 255)); } } } if ((!itemFieldsCache.ContainsKey(type)) && (!getRawFields)) { lock (itemFieldsCacheLock) { itemFieldsCache.Add(type, returnValue); } } System.Web.Caching.Cache cache; if (HttpContext.Current != null && HttpContext.Current.Cache != null) { cache = HttpContext.Current.Cache; } else { cache = new Cache(); } if (cache != null) { try { cache.Add("itemFields", itemFieldsCache, null, Cache.NoAbsoluteExpiration, new TimeSpan(12, 0, 0), CacheItemPriority.High, null); } catch (NullReferenceException) { } } return returnValue; } internal static object GetFieldValue(DataFieldInfo dfi, Item item) { foreach (FieldInfo fi in item.GetType().GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { foreach (Attribute attr in Attribute.GetCustomAttributes(fi, typeof(DataFieldAttribute))) { DataFieldAttribute dfattr = (DataFieldAttribute)attr; if (dfattr.FieldName != null) { if (dfi.Name == dfattr.FieldName) { return fi.GetValue(item); } } } } return 0; } public static string[] GetFieldsPrefixed(Type type) { string tableName = GetTable(type); List fields = GetFields(type); string[] returnValue = new string[fields.Count]; for (int i = 0; i < fields.Count; i++) { returnValue[i] = string.Format("`{0}`.`{1}`", tableName, fields[i].Name); } return returnValue; } protected string Table { get { return GetTable(this.GetType()); } } protected string[] FieldsPrefixed { get { return GetFieldsPrefixed(this.GetType()); } } public static string GetTable(Type type) { return DataFieldAttribute.GetTable(type); } internal protected static string GetNamespace(Type type) { foreach (Attribute attr in type.GetCustomAttributes(typeof(DataTableAttribute), false)) { DataTableAttribute dtattr = (DataTableAttribute)attr; if (attr != null) { if (dtattr.Namespace != null) { return dtattr.Namespace; } } } return type.FullName; } public long Update() { return Update(this.GetType()); } public long Update(Type type) { if (this is IPermissibleItem) { IPermissibleItem iThis = (IPermissibleItem)this; if (!iThis.Access.Can("EDIT")) { throw new UnauthorisedToUpdateItemException(); } } if (ItemChangeAuthenticationProvider != null) { ItemChangeAuthenticationProvider(this, new ItemChangeAuthenticationProviderEventArgs(ItemChangeAction.Edit)); } if (OnUpdate != null) { OnUpdate(this, new EventArgs()); } if (updatedItems.Count == 0) { return 0; } SelectQuery sQuery = new SelectQuery(Item.GetTable(type)); UpdateQuery uQuery = new UpdateQuery(Item.GetTable(type)); foreach (FieldInfo fi in type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { foreach (Attribute attr in Attribute.GetCustomAttributes(fi, typeof(DataFieldAttribute))) { if (updatedItems.Contains(fi.Name)) { DataFieldAttribute dfattr = (DataFieldAttribute)attr; if (dfattr.FieldName != null) { uQuery.AddField(dfattr.FieldName, fi.GetValue(this)); } else { uQuery.AddField(fi.Name, fi.GetValue(this)); } } } } List fields = GetRawFields(type); bool foundKey = false; bool containsUniqueFields = false; foreach (DataFieldInfo field in fields) { if ((field.Key & DataFieldKeys.Primary) == DataFieldKeys.Primary) { sQuery.AddFields(field.Name); //sQuery.AddCondition(field.Name, ConditionEquality.NotEqual, GetFieldValue(field, this)); sQuery.AddCondition(field.Name, GetFieldValue(field, this)); uQuery.AddCondition(field.Name, GetFieldValue(field, this)); foundKey = true; } } foreach (DataFieldInfo field in fields) { if ((field.Key & DataFieldKeys.Unique) == DataFieldKeys.Unique) { containsUniqueFields = true; if (field.Type == typeof(ItemKey)) { sQuery.AddCondition(field.Name + "_id", ((ItemKey)GetFieldValue(field, this)).Id); sQuery.AddCondition(field.Name + "_type_id", ((ItemKey)GetFieldValue(field, this)).TypeId); //uQuery.AddCondition(field.Name + "_id", ((ItemKey)GetFieldValue(field, this)).Id); //uQuery.AddCondition(field.Name + "_type_id", ((ItemKey)GetFieldValue(field, this)).TypeId); } else { sQuery.AddCondition(field.Name, GetFieldValue(field, this)); //uQuery.AddCondition(field.Name, GetFieldValue(field, this)); } } } if (!foundKey) { foreach (DataFieldInfo field in fields) { if ((field.Key & DataFieldKeys.Unique) == DataFieldKeys.Unique) { if (field.Type == typeof(ItemKey)) { uQuery.AddCondition(field.Name + "_id", ((ItemKey)GetFieldValue(field, this)).Id); uQuery.AddCondition(field.Name + "_type_id", ((ItemKey)GetFieldValue(field, this)).TypeId); } else { uQuery.AddCondition(field.Name, GetFieldValue(field, this)); } if (updatedItems.Contains(field.Name)) { /* cannot change a unique key */ foundKey = false; break; } else { foundKey = true; // continue, all must match } } } } if (!foundKey) { // Error throw new NoPrimaryKeyException(); } // check uniqueness if (containsUniqueFields) { long uniqueness = db.Query(sQuery).Rows.Count; if (uniqueness != 1) { throw new RecordNotUniqueException(); } } long result = db.Query(uQuery); if (result > 0) { if (ItemUpdated != null) { ItemUpdated(this, new EventArgs()); } } return result; } protected void AuthenticateAction(ItemChangeAction action) { if (ItemChangeAuthenticationProvider != null) { ItemChangeAuthenticationProvider(this, new ItemChangeAuthenticationProviderEventArgs(action)); } } public static Item Create(Core core, Type type, params FieldValuePair[] fields) { return Create(core, type, false, fields); } public static Item Create(Core core, Type type, bool suppress, params FieldValuePair[] fields) { core.Db.BeginTransaction(); InsertQuery iQuery = new InsertQuery(GetTable(type)); foreach (FieldValuePair field in fields) { iQuery.AddField(field.Field, field.Value); } long id = core.Db.Query(iQuery); if (id > 0) { if (!suppress) { Item newItem = System.Activator.CreateInstance(type, new object[] { core, id }) as Item; return newItem; } else { return null; } } else { throw new InvalidItemException(type.FullName); } } public static long DeleteItem(Type type, long itemId) { /*if (this is IPermissibleItem) { IPermissibleItem iThis = (IPermissibleItem)this; //iThis.Access.SetSessionViewer(core.session); if (!iThis.Access.Can("DELETE")) { throw new UnauthorisedToDeleteItemException(); } }*/ return 0; } public long Delete() { return Delete(false); } public long Delete(bool parentDeleted) { if (this is IPermissibleItem) { IPermissibleItem iThis = (IPermissibleItem)this; //iThis.Access.SetSessionViewer(core.session); if (!iThis.Access.Can("DELETE")) { throw new UnauthorisedToDeleteItemException(); } } AuthenticateAction(ItemChangeAction.Delete); db.BeginTransaction(); DeleteQuery dQuery = new DeleteQuery(Item.GetTable(this.GetType())); List fields = GetFields(this.GetType()); bool foundKey = false; foreach (DataFieldInfo field in fields) { if ((field.Key & (DataFieldKeys.Primary | DataFieldKeys.Unique)) != DataFieldKeys.None) { dQuery.AddCondition(field.Name, GetFieldValue(field, this)); foundKey = true; } } if (!foundKey) { // Error throw new NoPrimaryKeyException(); } long result = db.Query(dQuery); if (result > 0) { if (ItemDeleted != null) { ItemDeleted(this, new ItemDeletedEventArgs(parentDeleted)); } } return result; } protected void loadItemInfo(System.Data.Common.DbDataReader reader) { loadItemInfo(this.GetType(), reader); } protected void loadItemInfo(Type type, System.Data.Common.DbDataReader reader) { int fieldsLoaded = 0; int objectFields = 0; Dictionary fields = new Dictionary(); foreach (FieldInfo fi in type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { foreach (Attribute attr in Attribute.GetCustomAttributes(fi, typeof(DataFieldAttribute))) { DataFieldAttribute dfattr = (DataFieldAttribute)attr; objectFields++; string columnPrefix; if (dfattr.FieldName != null) { columnPrefix = dfattr.FieldName; } else { columnPrefix = fi.Name; } fields.Add(columnPrefix, fi); if (fi.FieldType == typeof(ItemKey)) { fields.Add(columnPrefix + "_id", fi); fields.Add(columnPrefix + "_type_id", fi); } } } /* buffer for item */ long ikBufferId = 0; long ikBufferTypeId = 0; if (reader.HasRows) { bool rowRead = false; /* past participle */ while (reader.Read()) { /* only read one row */ if (rowRead) { // Error reader.Close(); reader.Dispose(); throw new InvalidItemException(this.GetType().FullName + " :: Row Count"); } else { rowRead = true; } for (int i = 0; i < reader.FieldCount; i++) { string column = reader.GetName(i); object value = null; if (fields.ContainsKey(column)) { FieldInfo fi = fields[column]; if (!reader.IsDBNull(i)) { value = reader.GetValue(i); } else { if (fi.FieldType == typeof(string)) { fieldsLoaded++; continue; } } /*try {*/ if (fi.FieldType == typeof(ItemKey)) { if (ikBufferId > 0 && column.EndsWith("_type_id")) { fi.SetValue(this, new ItemKey(ikBufferId, (long)value)); fieldsLoaded++; } else if (ikBufferTypeId > 0 && column.EndsWith("_id")) { fi.SetValue(this, new ItemKey((long)value, ikBufferTypeId)); fieldsLoaded++; } else { if (column.EndsWith("_id")) { ikBufferId = (long)value; } else if (column.EndsWith("_type_id")) { ikBufferTypeId = (long)value; } } } else if (fi.FieldType == typeof(bool) && !(value is bool)) { if (value is byte) { fi.SetValue(this, ((byte)value > 0) ? true : false); fieldsLoaded++; } else if (value is sbyte) { fi.SetValue(this, ((sbyte)value > 0) ? true : false); fieldsLoaded++; } } else { fi.SetValue(this, value); fieldsLoaded++; } /*} catch (Exception ex) { Display.ShowMessage("Type error on load", Bbcode.Strip(column + " expected type " + fi.FieldType + " type returned was " + value.GetType() + "\n\n" + ex)); }*/ } } } } if (fieldsLoaded != objectFields) { reader.Close(); reader.Dispose(); throw new InvalidItemException(this.GetType().FullName + " :: fieldsLoaded != objectFields"); } reader.Close(); reader.Dispose(); if (ItemLoad != null) { ItemLoad(); } } protected void loadItemInfo(DataRow itemRow) { loadItemInfo(this.GetType(), itemRow); } protected void loadItemInfo(Type type, DataRow itemRow) { List columns = new List(); List columnsAttributed = new List(); int columnCount = 0; foreach (DataColumn column in itemRow.Table.Columns) { columns.Add(column.ColumnName); } foreach (FieldInfo fi in type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { foreach (Attribute attr in Attribute.GetCustomAttributes(fi)) { if (attr is DataFieldAttribute) { DataFieldAttribute dfattr = (DataFieldAttribute)attr; if (fi.FieldType == typeof(ItemKey)) { string columnPrefix; if (dfattr.FieldName != null) { columnPrefix = dfattr.FieldName; } else { columnPrefix = fi.Name; } columnsAttributed.Add(columnPrefix); columnsAttributed.Add(columnPrefix + "_id"); columnsAttributed.Add(columnPrefix + "_type_id"); fi.SetValue(this, new ItemKey((long)itemRow[columnPrefix + "_id"], (long)itemRow[columnPrefix + "_type_id"])); } else { string columnName; if (dfattr.FieldName != null) { columnName = dfattr.FieldName; } else { columnName = fi.Name; } columnsAttributed.Add(columnName); if (columns.Contains(columnName)) { columnCount++; if (!(itemRow[columnName] is DBNull)) { try { if (fi.FieldType == typeof(bool) && !(itemRow[columnName] is bool)) { if (itemRow[columnName] is byte) { fi.SetValue(this, ((byte)itemRow[columnName] > 0) ? true : false); } else if (itemRow[columnName] is sbyte) { fi.SetValue(this, ((sbyte)itemRow[columnName] > 0) ? true : false); } } else { fi.SetValue(this, itemRow[columnName]); } } catch (Exception ex) { core.Display.ShowMessage("Type error on load", core.Bbcode.Strip(columnName + " expected type " + fi.FieldType + " type returned was " + itemRow[columnName].GetType() + "\n\n" + ex)); } } else { // This works only when the non repeated columns are not entirely TEXT if (fi.FieldType == typeof(string)) { columnCount++; } else { throw new InvalidItemException(this.GetType().FullName); } } } } } } } if (columnCount == 0) { throw new InvalidItemException(this.GetType().FullName); } if (ItemLoad != null) { ItemLoad(); } } protected void MoveUp(string orderField) { // TODO: make sure isn't INestableItem IOrderableItem oItem = (IOrderableItem)this; UpdateQuery uQuery = new UpdateQuery(GetTable(this.GetType())); uQuery.AddField(orderField, new QueryOperation(orderField, QueryOperations.Addition, 1)); uQuery.AddCondition(orderField, oItem.Order); oItem.AddSequenceConditon(uQuery); core.Db.Query(uQuery); oItem.Order--; this.Update(); } protected void MoveDown(string orderField) { // TODO: make sure isn't INestableItem IOrderableItem oItem = (IOrderableItem)this; UpdateQuery uQuery = new UpdateQuery(GetTable(this.GetType())); uQuery.AddField(orderField, new QueryOperation(orderField, QueryOperations.Subtraction, 1)); uQuery.AddCondition(orderField, oItem.Order); oItem.AddSequenceConditon(uQuery); core.Db.Query(uQuery); oItem.Order++; this.Update(); } public static void IncrementItemColumn(Core core, Type type, long id, string column, int value) { UpdateQuery uQuery = new UpdateQuery(GetTable(type)); uQuery.AddField(column, new QueryOperation(column, QueryOperations.Addition, value)); uQuery.AddCondition(GetPrimaryKey(type), id); core.Db.Query(uQuery); } } public enum ItemChangeAction { Edit, Delete, Create, } public class ItemChangeAuthenticationProviderEventArgs : EventArgs { private ItemChangeAction action; public ItemChangeAction Action { get { return action; } } public ItemChangeAuthenticationProviderEventArgs(ItemChangeAction action) { this.action = action; } } public class ItemDeletedEventArgs : EventArgs { private bool parentDeleted; public bool ParentDeleted { get { return parentDeleted; } } public ItemDeletedEventArgs(bool parentDeleted) { this.parentDeleted = parentDeleted; } } public class InvalidItemException : Exception { public InvalidItemException() { } public InvalidItemException(string type) : base("Type: " + type) { } } public class NoPrimaryKeyException : Exception { } public class RecordNotUniqueException : Exception { } public class FieldNotUniqueIndexException : Exception { public FieldNotUniqueIndexException() : base () { } public FieldNotUniqueIndexException(string field) : base("Field: " + field) { } } public class UnauthorisedToCreateItemException : Exception { } public class UnauthorisedToUpdateItemException : Exception { } public class UnauthorisedToDeleteItemException : Exception { } }