using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using dasBlog.Storage;
using System.Collections.ObjectModel;
using newtelligence.DasBlog.Runtime;
using System.Xml;
using System.IO;
using System.Threading;
using System.Collections;
using System.Diagnostics;
namespace dasBlog.Services.Interop{
class StorageBusBlogDataService : IBlogDataService, IBlogDataServiceInitialize
{
private Moniker scopeUri;
private Moniker postsUri;
private ILoggingDataService loggingService;
private TrackingTools trackingTools;
public StorageBusBlogDataService()
{
}
public StorageBusBlogDataService(string scopeName):this()
{
Initialize(scopeName, null);
}
public void Initialize(string scopeName, ILoggingDataService logService)
{
this.scopeUri = Moniker.FromScopeName(scopeName);
this.postsUri = new Moniker(scopeName, PathSegmentName.Posts);
this.loggingService = logService;
trackingTools = new TrackingTools(this, loggingService);
}
public Entry GetEntry(string entryId)
{
Moniker entryUri = new Moniker(postsUri, entryId);
TextEntry entry = entryUri.Get<TextEntry>();
if (entry != null)
{
return EntryFromTextEntry(entry);
}
else
{
return null;
}
}
public Entry GetEntryForEdit(string entryId)
{
return GetEntry(entryId);
}
public EntryCollection GetEntriesForDay(DateTime start, TimeZone tz, string acceptLanguages, int maxDays, int maxEntries, string categoryName)
{
return new EntryCollection((from entry in
postsUri.Select<TextEntry>(
MonikerMatch.Exact,
new DateRangeQueryDescription(DateTime.MinValue, start.Date.AddDays(1)))
orderby entry.Created descending
where entry.Language == null || acceptLanguages.Contains(entry.Language)
select EntryFromTextEntry(entry)).Take(maxEntries).ToArray());
}
public EntryCollection GetEntriesForMonth(DateTime summary, TimeZone tz, string acceptLanguages)
{
return new EntryCollection((from te in postsUri.Select<TextEntry>(MonikerMatch.Exact,
new DateRangeQueryDescription(tz.ToLocalTime(new DateTime(summary.Year, summary.Month, 1)),
tz.ToLocalTime(new DateTime(summary.Year, summary.Month, 1).AddMonths(1).AddDays(-1))))
where te.Language == null || te.Language == acceptLanguages || acceptLanguages.Contains(te.Language)
select EntryFromTextEntry(te)).ToArray());
}
public EntryCollection GetAllEntries(bool infoOnly)
{
if (!infoOnly)
{
return new EntryCollection((from te in postsUri.SelectAll<TextEntry>()
select EntryFromTextEntry(te)).ToArray());
}
else
{
return new EntryCollection((from te in postsUri.Select<TextEntry>(MonikerMatch.Exact,new IdOnlyQueryDescription())
select EntryFromTextEntry(te)).ToArray());
}
}
private LogEntry LogEntryFromTracking(Tracking trk )
{
return new LogEntry
{
RequestTime = DateTime.Now,
ReferrerUrl = trk.Referer,
ReferrerTitle = trk.RefererTitle,
ReferrerName = trk.RefererBlogName,
UrlRequested = trk.PermaLink,
UserIP = trk.RefererIPAddress,
TargetId = new Moniker(postsUri, trk.TargetEntryId).ToString(),
TargetTitle = trk.TargetTitle,
TrackingType = trk.TrackingType.ToString(),
};
}
private Tracking TrackingFromLogEntry(LogEntry lge)
{
return new Tracking
{
TrackingType = (TrackingType)Enum.Parse(typeof(TrackingType),lge.TrackingType),
Referer = lge.ReferrerUrl,
RefererBlogName = lge.ReferrerName,
RefererTitle = lge.ReferrerTitle,
PermaLink = lge.UrlRequested,
RefererIPAddress = lge.UserIP,
TargetEntryId = new Moniker(lge.TargetId).ItemId,
TargetTitle = lge.TargetTitle,
};
}
private TextEntry TextEntryFromEntry(Entry entry)
{
TextEntry textEntry = new TextEntry
{
AllowComments = entry.AllowComments,
CategoriesAsString = entry.Categories,
Content = entry.Content,
Created = entry.CreatedUtc,
Featured = entry.ShowOnFrontPage,
Language = entry.Language,
LastChange = entry.ModifiedUtc,
Author = new AuthorDescription { DisplayName = entry.Author },
Published = entry.IsPublic,
Summary = entry.Description,
Syndicated = entry.Syndicated,
Title = entry.Title,
Reference = entry.Link,
Id = new Moniker(this.postsUri, entry.EntryId)
};
return textEntry;
}
private TextEntry TextEntryFromComment(Comment entry)
{
return new TextEntry
{
Content = entry.Content,
Created = entry.CreatedUtc,
LastChange = entry.ModifiedUtc,
Author = new AuthorDescription { DisplayName = entry.Author, Email = entry.AuthorEmail },
Published = entry.IsPublic,
Title = entry.TargetTitle,
Parent = new Moniker(this.postsUri,entry.TargetEntryId).ToString(),
Id = new Moniker(this.postsUri,entry.TargetEntryId, PathSegmentName.Comments, entry.EntryId)
};
}
private static Entry EntryFromTextEntry(TextEntry entry)
{
return new Entry
{
AllowComments = entry.AllowComments.HasValue?entry.AllowComments.Value:false,
Author = entry.Author.DisplayName,
Categories = entry.CategoriesAsString,
Content = entry.Content,
CreatedUtc = entry.Created,
Description = entry.Summary,
EntryId = entry.Id.ItemId,
Syndicated = entry.Published.HasValue ? entry.Published.Value : false,
IsPublic = entry.Published.HasValue ? entry.Published.Value : false,
Language = entry.Language,
Title = entry.Title,
ShowOnFrontPage = entry.Featured.HasValue?entry.Featured.Value:false
};
}
private static Comment CommentFromTextEntry(TextEntry entry)
{
return new Comment
{
Author = entry.Author.DisplayName,
AuthorEmail = entry.Author.Email,
TargetEntryId = new Moniker(entry.Parent).ItemId,
Content = entry.Content,
CreatedUtc = entry.Created,
EntryId = entry.Id.ItemId,
IsPublic = entry.Published.GetValueOrDefault(),
Language = entry.Language,
ModifiedUtc = entry.LastChange,
};
}
public EntryCollection GetEntriesForCategory(string categoryName, string acceptLanguages)
{
return new EntryCollection((from entry in postsUri.Select<TextEntry>(MonikerMatch.Exact,
new TagQueryDescription(categoryName))
where entry.Language == null || acceptLanguages.Contains(entry.Language)
orderby entry.Created
select EntryFromTextEntry(entry)).ToArray());
}
public EntryCollection GetEntriesForUser(string user)
{
return null;
}
public DateTime[] GetDaysWithEntries(TimeZone tz)
{
var entries = postsUri.Aggregate(MonikerMatch.Exact, "datecreated");
return (from agg in entries select DateTime.Parse(agg.Value)).ToArray();
}
public DayEntry GetDayEntry(DateTime date)
{
return new DayEntry
{
DateUtc = date,
Entries = GetEntriesForDay(date, TimeZone.CurrentTimeZone, null, int.MaxValue, int.MaxValue, null),
DateLocalTime = date.ToLocalTime(),
};
}
public DayExtra GetDayExtra(DateTime date)
{
IList<TextEntry> entriesOnDay =
postsUri.Select<TextEntry>(
MonikerMatch.Exact,
new DateRangeQueryDescription(date.Date, date.Date.AddDays(1).AddMilliseconds(-1)));
var allComments = new CommentCollection(
(from TextEntry post in entriesOnDay
from TextEntry comment in new Moniker(post.Id, PathSegmentName.Comments).SelectAll<TextEntry>()
select CommentFromTextEntry(comment)).ToArray());
DayExtra extra = new DayExtra();
extra.DateUtc = date.ToUniversalTime();
extra.Comments.AddRange(allComments);
return extra;
}
public void DeleteEntry(string entryId, CrosspostSiteCollection crosspostSites)
{
new Moniker(postsUri, entryId).Delete();
}
public EntrySaveState SaveEntry(Entry entry, params object[] trackingInfos)
{
if (!entry.IsNew)
{
Moniker entryMk = new Moniker(postsUri, entry.EntryId);
TextEntry textEntry = entryMk.Get<TextEntry>();
if (textEntry != null)
{
Entry currentEntry = EntryFromTextEntry(textEntry);
if (currentEntry != null && !currentEntry.Equals(entry))
{
// we will only change the mod date if there has been a change to a few things
if (currentEntry.CompareTo(entry) == 1)
{
currentEntry.ModifiedUtc = DateTime.Now.ToUniversalTime();
}
currentEntry.Categories = entry.Categories;
currentEntry.Syndicated = entry.Syndicated;
currentEntry.Content = entry.Content;
currentEntry.CreatedUtc = entry.CreatedUtc;
currentEntry.Description = entry.Description;
currentEntry.anyAttributes = entry.anyAttributes;
currentEntry.anyElements = entry.anyElements;
currentEntry.Author = entry.Author;
currentEntry.IsPublic = entry.IsPublic;
currentEntry.Language = entry.Language;
currentEntry.AllowComments = entry.AllowComments;
currentEntry.Link = entry.Link;
currentEntry.ShowOnFrontPage = entry.ShowOnFrontPage;
currentEntry.Title = entry.Title;
currentEntry.Crossposts.Clear();
currentEntry.Crossposts.AddRange(entry.Crossposts);
currentEntry.Attachments.Clear();
currentEntry.Attachments.AddRange(entry.Attachments);
entryMk.Store<TextEntry>(TextEntryFromEntry(currentEntry));
trackingTools.RunActions(trackingInfos, currentEntry);
return EntrySaveState.Updated;
}
else
{
throw new InvalidOperationException("Item doesn't exist");
}
}
}
else
{
postsUri.Store<TextEntry>(TextEntryFromEntry(entry));
trackingTools.RunActions(trackingInfos, entry);
return EntrySaveState.Added;
}
return EntrySaveState.Failed;
}
public CategoryCacheEntryCollection GetCategories()
{
return new CategoryCacheEntryCollection(
(from PropertyAggregate agg in postsUri.Aggregate(MonikerMatch.Exact, "tag")
select new CategoryCacheEntry
{
Name = agg.Value,
IsPublic = true
}).ToArray());
}
private void InternalSendMail(SendMailInfo info)
{
try
{
info.SendMyMessage();
}
catch (Exception e)
{
ErrorTrace.Trace(TraceLevel.Error, e);
if (loggingService != null)
{
//CDO is very touchy and it's useful to get ALL the inner exceptions to diagnose the problem.
string exMessage = e.ToString();
Exception inner = e.InnerException;
while (inner != null)
{
exMessage += " INNER: " + inner.ToString();
inner = inner.InnerException;
}
loggingService.AddEvent(new EventDataItem(EventCodes.SmtpError, exMessage.Replace("\n", "<br>"), "InternalSendMail"));
}
}
}
public void RunActions(object[] actions)
{
trackingTools.RunActions(actions,null);
}
public void AddTracking(Tracking tracking, params object[] actions)
{
ThreadPool.QueueUserWorkItem(delegate(object o)
{
Moniker mkTrackings = new Moniker(postsUri, tracking.TargetEntryId, PathSegmentName.Trackings);
mkTrackings.Store(LogEntryFromTracking(tracking));
RunActions(actions);
});
}
public void DeleteTracking(string entryId, string trackingPermalink, TrackingType trackingType)
{
ThreadPool.QueueUserWorkItem(delegate(object o)
{
Moniker mkTrackings = new Moniker(postsUri, entryId, PathSegmentName.Trackings);
foreach (var tracking in mkTrackings.Select<LogEntry>(MonikerMatch.Exact, new QueryDescription("ReferrerUrl", new QueryArgument("ReferrerUrl", trackingPermalink))))
{
tracking.Id.Delete();
}
});
}
public TrackingCollection GetTrackingsFor(string entryId)
{
TrackingCollection trackings = new TrackingCollection();
Moniker mkTrackings = new Moniker(postsUri, entryId, PathSegmentName.Trackings);
foreach (LogEntry lge in mkTrackings.SelectAll<LogEntry>())
{
trackings.Add(TrackingFromLogEntry(lge));
}
return trackings;
}
public void AddComment(Comment comment, params object[] actions)
{
new Moniker(postsUri, comment.TargetEntryId, PathSegmentName.Comments).Store(TextEntryFromComment(comment));
RunActions(actions);
}
public Comment GetCommentById(string entryId, string commentIdx)
{
TextEntry entry = new Moniker(postsUri, entryId, PathSegmentName.Comments, commentIdx).Get<TextEntry>();
if (entry != null)
{
return CommentFromTextEntry(entry);
}
else
{
return null;
}
}
public void ApproveComment(string entryId, string commentIdx)
{
Moniker commentId = new Moniker(postsUri, entryId, PathSegmentName.Comments, commentIdx);
TextEntry entry = commentId.Get<TextEntry>();
if (entry != null)
{
entry.Published = true;
commentId.Store<TextEntry>(entry);
}
}
public void DeleteComment(string entryId, string commentIdx)
{
new Moniker(postsUri, entryId, PathSegmentName.Comments, commentIdx).Delete();
}
public CommentCollection GetCommentsFor(string entryId)
{
return new CommentCollection(
(from TextEntry comment in new Moniker(postsUri, entryId, PathSegmentName.Comments).Select<TextEntry>(
MonikerMatch.Exact,
null)
select CommentFromTextEntry(comment)).ToArray());
}
public CommentCollection GetPublicCommentsFor(string entryId)
{
return new CommentCollection(
(from TextEntry comment in new Moniker(postsUri, entryId, PathSegmentName.Comments).Select<TextEntry>(
MonikerMatch.Exact,
null)
where comment.Published == true
select CommentFromTextEntry(comment)).ToArray());
}
public CommentCollection GetCommentsFor(string entryId, bool allComments)
{
return GetCommentsFor(entryId);
}
public CommentCollection GetAllComments()
{
return new CommentCollection(
(from TextEntry post in postsUri.SelectAll<TextEntry>()
from TextEntry comment in new Moniker(post.Id, PathSegmentName.Comments).SelectAll<TextEntry>()
select CommentFromTextEntry(comment)).ToArray());
}
public DateTime GetLastEntryUpdate()
{
return DateTime.Now;
}
public DateTime GetLastCommentUpdate()
{
return DateTime.Now;
}
public EntryCollection /*IBlogDataService*/ GetEntries(
DayEntryCollection.CriteriaHandler dayEntryCriteria,
Predicate<Entry> entryCriteria,
int maxDays, int maxEntries)
{
IStorageNode storageNode = StorageBus.Current.FindNode(postsUri);
return new EntryCollection((from entry in
postsUri.SelectAll<TextEntry>()
orderby entry.Created descending
select EntryFromTextEntry(entry)).Where((e)=>entryCriteria(e)).Take(maxEntries).ToArray());
}
public string AddFile(string entryId, string fileName, string contentType, long contentLength, System.IO.Stream contentData)
{
Moniker mediaUri;
if (string.IsNullOrEmpty(entryId))
{
mediaUri = new Moniker(scopeUri, PathSegmentName.Media);
}
else
{
mediaUri = new Moniker(postsUri, entryId, PathSegmentName.Media);
}
IStreamStorageNode node = StorageBus.Current.FindNode(mediaUri) as IStreamStorageNode;
if (node != null)
{
var result = node.SetStream(
new StreamStorageSetRequest
{
moniker = mediaUri,
Stream = contentData,
name = Path.GetFileName(fileName),
contentType = contentType
}
);
}
return fileName;
}
public string[] GetFileList(string entryId)
{
Moniker mediaUri;
if (string.IsNullOrEmpty(entryId))
{
mediaUri = new Moniker(scopeUri, PathSegmentName.Media);
}
else
{
mediaUri = new Moniker(postsUri, entryId, PathSegmentName.Media);
}
return (from item in mediaUri.SelectAll<StreamStorageInfo>()
select item.Id.ItemId).ToArray();
}
public void DeleteFiles(string entryId)
{
if (string.IsNullOrEmpty(entryId))
{
return;
}
Moniker mediaUri = new Moniker(postsUri, entryId, PathSegmentName.Media);
var list = mediaUri.SelectAll<StreamStorageInfo>();
foreach ( var item in list )
{
item.Id.Delete();
}
}
}
}
|