using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Linq; using FLocal.Core; using FLocal.Core.DB; using FLocal.Common; using FLocal.Common.actions; namespace FLocal.Common.dataobjects { public class PMMessage : SqlObject { public const string ENUM_DIRECTION_INCOMING = "Incoming"; public const string ENUM_DIRECTION_OUTGOING = "Outgoing"; public class TableSpec : ISqlObjectTableSpec { public const string TABLE = "PMMessages"; public const string FIELD_ID = "Id"; public const string FIELD_OWNERID = "OwnerId"; public const string FIELD_INTERLOCUTORID = "InterlocutorId"; public const string FIELD_DIRECTION = "Direction"; public const string FIELD_POSTDATE = "PostDate"; public const string FIELD_TITLE = "Title"; public const string FIELD_BODY = "Body"; public const string FIELD_BODYUBB = "BodyUBB"; public const string FIELD_INCOMINGPMID = "IncomingPMId"; public const string FIELD_ISREAD = "IsRead"; public static readonly TableSpec instance = new TableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } public void refreshSqlObject(int id) { Refresh(id); } } protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } private int _ownerId; public int ownerId { get { this.LoadIfNotLoaded(); return this._ownerId; } } public Account owner { get { return Account.LoadById(this.ownerId); } } private int _interlocutorId; public int interlocutorId { get { this.LoadIfNotLoaded(); return this._interlocutorId; } } public Account interlocutor { get { return Account.LoadById(this.interlocutorId); } } public Account poster { get { if(this.direction == ENUM_DIRECTION_INCOMING) { return this.interlocutor; } else { return this.owner; } } } private string _direction; public string direction { get { this.LoadIfNotLoaded(); return this._direction; } } private DateTime _postDate; public DateTime postDate { get { this.LoadIfNotLoaded(); return this._postDate; } } private string _title; public string title { get { this.LoadIfNotLoaded(); return this._title; } } private string _body; public string body { get { this.LoadIfNotLoaded(); return this._body; } } private string _bodyUBB; public string bodyUBB { get { this.LoadIfNotLoaded(); return this._bodyUBB; } } private int? _incomingPMId; public int? incomingPMId { get { this.LoadIfNotLoaded(); return this._incomingPMId; } } private bool _isRead; public bool isRead { get { this.LoadIfNotLoaded(); return this._isRead; } } public PMConversation conversation { get { return PMConversation.LoadByAccounts(this.owner, this.interlocutor); } } protected override void doFromHash(Dictionary data) { this._ownerId = int.Parse(data[TableSpec.FIELD_OWNERID]); this._interlocutorId = int.Parse(data[TableSpec.FIELD_INTERLOCUTORID]); this._direction = data[TableSpec.FIELD_DIRECTION]; this._postDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_POSTDATE]).Value; this._title = data[TableSpec.FIELD_TITLE]; this._body = data[TableSpec.FIELD_BODY]; this._bodyUBB = data[TableSpec.FIELD_BODYUBB]; this._incomingPMId = Util.ParseInt(data[TableSpec.FIELD_INCOMINGPMID]); this._isRead = Util.string2bool(data[TableSpec.FIELD_ISREAD]); } public XElement exportToXml(UserContext context, params XElement[] additional) { if((context.account == null) || (context.account.id != this.owner.id)) { throw new AccessViolationException(); } XElement result = new XElement("message", new XElement("id", this.id), new XElement("poster", this.poster.exportToXml(context)), new XElement("owner", this.owner.exportToXml(context)), new XElement("interlocutor", this.interlocutor.exportToXml(context)), new XElement("postDate", this.postDate.ToXml()), new XElement("title", this.title), new XElement("body", context.outputParams.preprocessBodyIntermediate(this.body)), new XElement("bodyUBB", this.bodyUBB) ); if(additional.Length > 0) { result.Add(additional); } return result; } private readonly object MarkAsRead_locker = new object(); public void MarkAsRead(Account account) { if(account.id != this.owner.id) throw new AccessViolationException(); if(!this.isRead) { lock(MarkAsRead_locker) { //so we can safely decrease ReadPrivateMessages counter //Note that this code implicitly uses assumption of single-instance Common.dll; race condition is possible with more than one server if(!this.isRead) { AccountIndicator indicator = AccountIndicator.LoadByAccount(this.owner); ChangeSetUtil.ApplyChanges( new UpdateChange( TableSpec.instance, new Dictionary { { TableSpec.FIELD_ISREAD, new ScalarFieldValue("1") }, }, this.id ), new UpdateChange( AccountIndicator.TableSpec.instance, new Dictionary { { AccountIndicator.TableSpec.FIELD_UNREADPRIVATEMESSAGES, new IncrementFieldValue(IncrementFieldValue.DECREMENTOR) }, }, indicator.id ) ); } } } } } }