using Sarand.Net.Standard.Base.App; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Dbas; using Sarand.Net.Standard.Base.Utils; using Sarand.Net.Standard.Dbas.Data; using Saxonite.Base.App; using Saxonite.Net.Standard.Base.App; using Saxonite.Net.Standard.Base.Bus; using Saxonite.Net.Standard.Base.Consoles; using System; using System.Collections.Generic; using System.Linq; namespace Saxonite.Net.Core.Web.Base.Consoles { //======================================================================= public abstract class SaxActivityConsole_Web : SaxActivityConsole { //------------------------------------------------------------------- // Data members. private readonly SaxInternals internals; private readonly String alias_ActivityIndex = "ActIdx"; protected class IndexStatsData { public int EntriesInserted { get; set; } public int EntriesUpdated { get; set; } public int EntriesDeleted { get; set; } } //------------------------------------------------------------------- // Protected construction. protected SaxActivityConsole_Web(SaxSessionContext sessionContext) : base(sessionContext) { internals = new SaxInternals(sessionContext); } protected override void Dispose(bool disposing) { if (disposing) { internals.Dispose(); } base.Dispose(disposing); } //------------------------------------------------------------------- // Query Activity Index Entries for User Context. //------------------------------------------------------------------- private class ActivityData_Web : IndexResults.ActivityData { public ActivityData_Web(ItemId itemId, DateTime effectiveOn) : base(itemId, effectiveOn) { } public void SetCaption(String caption) { Caption = caption; } public void SetBlurb(String blurb) { Blurb = blurb; } public void SetSport(SysId sportId, String sportName) { SportId = sportId; SportName = sportName; } public void SetRegion(SysId regionId, String regionName) { RegionId = regionId; RegionName = regionName; } public static int CompareActivityIndices(ActivityData_Web item1, ActivityData_Web item2) { int effectiveCompare = item1.EffectiveOn.CompareTo(item2.EffectiveOn); if (effectiveCompare != 0) return effectiveCompare * -1; return 1; } } public override IndexResults QueryIndex(IndexContext context) { String fn = GetType().Name + ".QueryIndex"; IndexResults results = new IndexResults(); if (!context.IsValid()) return results; // Columns to query. ColumnDfn colItemType = internals.ActivityMgr.GetActivityIndexColumnDfn(SaxActivityIndex.Column.ItemType); ColumnDfn colItemId = internals.ActivityMgr.GetActivityIndexColumnDfn(SaxActivityIndex.Column.ItemId); String colDataNameEffectiveOn = "EffectiveOn"; // Query the index. ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext); DbQuery query = new DbQuery(db.DbmsType); query.Tables.Add(SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.ActivityIndex, false), alias_ActivityIndex); query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, alias_ActivityIndex), colItemType.DataName); query.Columns.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, alias_ActivityIndex), colItemId.DataName); query.Columns.Add("Max(" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_EffectiveOn, alias_ActivityIndex) + ")", colDataNameEffectiveOn); query.GroupBy.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType, alias_ActivityIndex)); query.GroupBy.Add(SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId, alias_ActivityIndex)); query.OrderBy.Add("Max(" + SaxDbDfn_Core.GetColumnNameQual(SaxDbDfn_Core.ColumnIdx.ActivityIndex_EffectiveOn, alias_ActivityIndex) + ") DESC"); // Filter. SaxActivityIndex.Params prmActivityIndex = new SaxActivityIndex.Params(); prmActivityIndex.SportIdsIncluded.AddRange(context.SportIds); prmActivityIndex.RegionIdsIncluded.AddRange(context.RegionIds); prmActivityIndex.EffectiveFrom = context.EffectiveFrom; prmActivityIndex.EffectiveTo = context.EffectiveTo; prmActivityIndex.Alias_ActivityIndex = alias_ActivityIndex; query.Filters.AddRange(internals.ActivityMgr.GetActivityIndexQueryFilter(prmActivityIndex)); // First pass, note the activity Item and effective date. List activityDataList = new List(); using (DbResultSet dbResultSet = DbResultSet_DataReader.ExecuteQuery(db, query.BuildQuery(context.Paging))) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); Sax.DataItemType itemType = (Sax.DataItemType)values.GetLong(colItemType.DataName); ItemId itemId = new ItemId((short)itemType, new SysId(values.GetLong(colItemId.DataName))); DateTime effectiveOn = values.GetDate(colDataNameEffectiveOn); activityDataList.Add(new ActivityData_Web(itemId, effectiveOn)); SaLogger.Info(fn + " Activity found - " + itemType.ToString() + ":" + SysId.ToString(itemId.Id) + ". Effective: " + DateUtil.Format(effectiveOn, "d-MMM-yyyy")); } } activityDataList.Sort(ActivityData_Web.CompareActivityIndices); // Populate activity details. PopulateActivityDetails(activityDataList); // ToDo Remove activities with blank caption. results.Items.AddRange(activityDataList); return results; } //------------------------------------------------------------------- // Populate Activity Details. //------------------------------------------------------------------- private void PopulateActivityDetails(List activities) { PopulateJournalistArticleDetails(activities); PopulateOrganisationOpportunitiesDetails(activities); } private void PopulateJournalistArticleDetails(List activities) { // Extract article Ids. List articleIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.JournalistArticle).Select(ItemId => ItemId.ItemId.Id).ToList(); if (articleIds.IsEmpty()) return; // Article columns - limit to essential information. ColumnDfn colId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Id); ColumnDfn colHeadline = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Headline); ColumnDfn colSummary = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Summary); ColumnDfn colSportId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.SportIdPrimary); ColumnDfn colSportName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Sport_Name); ColumnDfn colRegionId = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.RegionIdPrimary); ColumnDfn colRegionName = Internals.ActivityMgr.GetJournalistArticleColumnDfn(SaxJournalistArticle.Column.Region_Name); List columns = new List() { colId, colHeadline, colSummary, colSportId, colSportName, colRegionId, colRegionName }; // Article filter. SaxJournalistArticle.Params prmArticle = new SaxJournalistArticle.Params(); prmArticle.IdsIncluded.AddRange(articleIds); prmArticle.StatusCat = SaxJournalistArticle.StatusCat.ActiveOnly; using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteJournalistArticleQuery(columns, prmArticle)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); ItemId itemId = new ItemId((short)Sax.DataItemType.JournalistArticle, new SysId(values.GetLong(colId.DataName))); String headline = values.GetString(colHeadline.DataName); String summary = values.GetString(colSummary.DataName); SysId sportId = new SysId(values.GetLong(colSportId.DataName)); String sportName = values.GetString(colSportName.DataName); SysId regionId = new SysId(values.GetLong(colRegionId.DataName)); String regionName = values.GetString(colRegionName.DataName); // Populate to corresponding activities. foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId))) { activity.SetCaption(headline); activity.SetBlurb(summary); activity.SetSport(sportId, sportName); activity.SetRegion(regionId, regionName); } } } } private void PopulateOrganisationOpportunitiesDetails(List activities) { // Extract opportunity Ids. List opportunityIds = activities.FindAll(item => item.ItemId.Type == (int)Sax.DataItemType.OrganisationOpportunity).Select(ItemId => ItemId.ItemId.Id).ToList(); if (opportunityIds.IsEmpty()) return; // Opportunity columns - limit to essential information. ColumnDfn colId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Id); ColumnDfn colPosition = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Position); ColumnDfn colOutline = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Outline); ColumnDfn colSportId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.SportIdPrimary); ColumnDfn colSportName = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Sport_Name); ColumnDfn colRegionId = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.RegionIdPrimary); ColumnDfn colRegionName = Internals.ActivityMgr.GetOrganisationOpportunityColumnDfn(SaxOrganisationOpportunity.Column.Region_Name); List columns = new List() { colId, colPosition, colOutline, colSportId, colSportName, colRegionId, colRegionName }; // Opportunity filter. SaxOrganisationOpportunity.Params prmOpportunity = new SaxOrganisationOpportunity.Params(); prmOpportunity.IdsIncluded.AddRange(opportunityIds); prmOpportunity.StatusCat = SaxOrganisationOpportunity.StatusCat.ActiveOnly; using (DbResultSet dbResultSet = Internals.ActivityMgr.ExecuteOrganisationOpportunityQuery(columns, prmOpportunity)) { while (dbResultSet != null && dbResultSet.NextRecord()) { NamedValue.Map values = dbResultSet.GetRecordValues(); ItemId itemId = new ItemId((short)Sax.DataItemType.OrganisationOpportunity, new SysId(values.GetLong(colId.DataName))); String headline = values.GetString(colPosition.DataName); String summary = values.GetString(colOutline.DataName); SysId sportId = new SysId(values.GetLong(colSportId.DataName)); String sportName = values.GetString(colSportName.DataName); SysId regionId = new SysId(values.GetLong(colRegionId.DataName)); String regionName = values.GetString(colRegionName.DataName); // Populate to corresponding activities. foreach (ActivityData_Web activity in activities.FindAll(item => item.ItemId.Equals(itemId))) { activity.SetCaption(headline); activity.SetBlurb(summary); activity.SetSport(sportId, sportName); activity.SetRegion(regionId, regionName); } } } } //------------------------------------------------------------------- // Store Activity Index. //------------------------------------------------------------------- protected override bool StoreActivityIndexData(IndexData indexData, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".StoreActivityIndexData"; if (!ItemId.IsValid(indexData.ItemId)) return false; if (!ValidActivityItemTypes.Contains((Sax.DataItemType)indexData.ItemId.Type)) { SaLogger.Warn(fn + " Invalid item type specified for Activity Index: " + ((Sax.DataItemType)indexData.ItemId.Type).ToString()); return false; } IndexStatsData stats = new IndexStatsData(); // Index entries required for activity. List indexEntries = GetEntriesForIndex(indexData); // Retrieve existing index entries for the item. List itemIndexEntries = internals.ActivityMgr.GetActivityIndexListForItem(indexData.ItemId); foreach (SaxActivityIndex itemIndexEntry in itemIndexEntries) { // Is the index entry still required. // Logic only compares the Ids (item, sport, region) and then updates the effective date if a match is found. // Based on the fact that and change in the effective date will impact all entries in the index for the item // and this approach minimises the number of updates required as Ids can't be changed in code (protected setters). IndexEntryData indexEntry = indexEntries.Find(item => item.MatchesIds(itemIndexEntry)); if (indexEntry != null) { // Match found - if the effective date differs, update it. if (!itemIndexEntry.EffectiveOn.Equals(indexEntry.EffectiveOn)) { itemIndexEntry.EffectiveOn = indexEntry.EffectiveOn; if (internals.ActivityMgr.UpdateActivityIndex(itemIndexEntry, dbUpdateInfo)) stats.EntriesUpdated++; else SaLogger.Warn(fn + " Failed to update Activity Index - " + internals.ActivityMgr.ErrorStateMessage); } // Remove the entry from the 'required' list. // Entries remaining in this list will be created. indexEntries.Remove(indexEntry); } else { // Index entry no longer required. if (internals.ActivityMgr.DeleteActivityIndex(itemIndexEntry, dbUpdateInfo)) stats.EntriesDeleted++; else SaLogger.Warn(fn + " Failed to delete Activity Index - " + internals.ActivityMgr.ErrorStateMessage); } } // The remaining required Index entries will be created. foreach (IndexEntryData indexEntry in indexEntries) { SaxActivityIndex itemIndexEntry = internals.ActivityMgr.CreateActivityIndex(indexEntry.ItemId, indexEntry.SportId, indexEntry.RegionId, indexEntry.EffectiveOn); if (internals.ActivityMgr.InsertActivityIndex(itemIndexEntry, dbUpdateInfo)) stats.EntriesInserted++; else SaLogger.Warn(fn + " Failed to insert Activity Index - " + internals.ActivityMgr.ErrorStateMessage); } // Log statistics. List statsLog = new List(); if (stats.EntriesInserted > 0) statsLog.Add("Inserted: " + stats.EntriesInserted); if (stats.EntriesUpdated > 0) statsLog.Add("Updated: " + stats.EntriesUpdated); if (stats.EntriesDeleted > 0) statsLog.Add("Deleted: " + stats.EntriesDeleted); SaLogger.Info(fn + " Activity Index stored for " + ((Sax.DataItemType)indexData.ItemId.Type).ToString() + ":" + indexData.ItemId.Id.ToLong() + "." + statsLog.Concat("", "", ". ")); return true; } //------------------------------------------------------------------- protected override bool ClearActivityIndex(ItemId itemId, DbUpdateInfo dbUpdateInfo) { String fn = GetType().Name + ".ClearActivityIndex"; String tableName = SaxDbDfn_Core.GetTableName(SaxDbDfn_Core.TableIdx.ActivityIndex); String filter = SaxDbDfn_Core.GetColumnName(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemType) + "=" + itemId.Type + " And " + SaxDbDfn_Core.GetColumnName(SaxDbDfn_Core.ColumnIdx.ActivityIndex_ItemId) + "=" + itemId.Id.ToLong(); ISacsDatabase db = SaxGlobals.App.GetCoreDatabase(SessionContext); int recordsDeleted = db.ExecuteDelete(tableName, filter); SaLogger.Info(fn + " Records deleted: " + recordsDeleted + ". Filter: " + filter, true); return true; } //------------------------------------------------------------------- } //======================================================================= }