/// <summary> /// Initializer /// </summary> /// <remarks>This modifies the input FeedInfoList by replacing its INewsItem contents /// with SearchHitNewsItems</remarks> /// <param name="tag">Object used by caller</param> /// <param name="matchingFeeds"></param> /// <param name="matchingFeedsCount">integer stores the count of matching feeds</param> /// <param name="matchingItemsCount">integer stores the count of matching INewsItem's (over all feeds)</param> public SearchFinishedEventArgs( object tag, FeedInfoList matchingFeeds, int matchingFeedsCount, int matchingItemsCount) : this(tag, matchingFeeds, new List <INewsItem>(), matchingFeedsCount, matchingItemsCount) { var temp = new List <INewsItem>(); foreach (FeedInfo fi in matchingFeeds) { foreach (var ni in fi.ItemsList) { if (ni is SearchHitNewsItem) { temp.Add(ni); } else { temp.Add(new SearchHitNewsItem(ni)); } } fi.ItemsList.Clear(); fi.ItemsList.AddRange(temp); MatchingItems.AddRange(temp); temp.Clear(); } //foreach }
/// <summary> /// Initiate a remote (web) search using the engine incl. search expression specified /// by searchFeedUrl. We assume, the specified Url will return a RSS feed. /// This can be used e.g. to get a RSS search result from feedster. /// </summary> /// <param name="searchFeedUrl">Complete Url of the search engine incl. search expression</param> /// <param name="tag">optional, can be used by the caller</param> public void SearchRemoteFeed(string searchFeedUrl, object tag) { var unreturnedMatchItems = new List <INewsItem>(1); try { unreturnedMatchItems = RssParser.DownloadItemsFromFeed(searchFeedUrl); } catch (Exception remoteSearchException) { unreturnedMatchItems.Add(FeedSource.CreateHelpNewsItemFromException(remoteSearchException)); } int feedmatches = 1; int itemmatches = unreturnedMatchItems.Count; var fi = new FeedInfo(String.Empty, String.Empty, unreturnedMatchItems, String.Empty, String.Empty, String.Empty, new Dictionary <XmlQualifiedName, string>(), String.Empty); var fil = new FeedInfoList(String.Empty) { fi }; RaiseSearchFinishedEvent(tag, fil, feedmatches, itemmatches); }
/// <summary> /// Initializer /// </summary> /// <param name="tag">Object used by caller</param> /// <param name="matchingFeeds">The matching feeds.</param> /// <param name="matchingNewsItems">The matching news items.</param> /// <param name="matchingFeedsCount">integer stores the count of matching feeds</param> /// <param name="matchingItemsCount">integer stores the count of matching INewsItem's (over all feeds)</param> public SearchFinishedEventArgs( object tag, FeedInfoList matchingFeeds, IEnumerable <INewsItem> matchingNewsItems, int matchingFeedsCount, int matchingItemsCount) { MatchingFeedsCount = matchingFeedsCount; MatchingItemsCount = matchingItemsCount; MatchingFeeds = matchingFeeds; MatchingItems = new List <INewsItem>(matchingNewsItems); Tag = tag; }
/// <summary> /// <summary> /// Notify the user interface that the search has finished /// </summary> /// <param name="tag"></param> /// <param name="matchingFeeds">The feeds that matched the search</param> /// <param name="matchingFeedsCount">Number of feeds matched by the search</param> /// <param name="matchingItemsCount">Number of items matched by the search</param> private void RaiseSearchFinishedEvent(object tag, FeedInfoList matchingFeeds, int matchingFeedsCount, int matchingItemsCount) { try { if (SearchFinished != null) { SearchFinished(this, new SearchFinishedEventArgs(tag, matchingFeeds, matchingFeedsCount, matchingItemsCount)); } } catch (Exception e) { _log.ErrorFormat("SearchFinished() event code raises exception: {0}", e); } }
/// <summary> /// Search for NewsItems, that match a provided criteria collection within a optional search scope. /// </summary> /// <param name="criteria">SearchCriteriaCollection containing the defined search criteria</param> /// <param name="scope">Search scope: an array of NewsFeed</param> /// <param name="tag">optional object to be used by the caller to identify this search</param> /// <param name="cultureName">Name of the culture.</param> /// <param name="returnFullItemText">if set to <c>true</c>, full item texts are returned instead of the summery.</param> public void SearchNewsItems(SearchCriteriaCollection criteria, INewsFeed[] scope, object tag, string cultureName, bool returnFullItemText) { // if scope is an empty array: search all, else search only in spec. feeds int feedmatches = 0; int itemmatches = 0; IList <INewsItem> unreturnedMatchItems = new List <INewsItem>(); var fiList = new FeedInfoList(String.Empty); Exception ex; bool valid = SearchHandler.ValidateSearchCriteria(criteria, cultureName, out ex); if (ex != null) // report always any error (warnings) { // render the error in-line (search result): fiList.Add(FeedSource.CreateHelpNewsItemFromException(ex).FeedDetails); feedmatches = fiList.Count; unreturnedMatchItems = fiList.GetAllNewsItems(); itemmatches = unreturnedMatchItems.Count; } if (valid) { try { // do the search (using lucene): LuceneSearch.Result r = SearchHandler.ExecuteSearch(criteria, scope, this.Sources.Select(entry => entry.Source), cultureName); // we iterate r.ItemsMatched to build a // NewsItemIdentifier and ArrayList list with items, that // match the read status (if this was a search criteria) // then call FindNewsItems(NewsItemIdentifier[]) to get also // the FeedInfoList. // Raise ONE event, instead of two to return all (counters, lists) SearchCriteriaProperty criteriaProperty = null; foreach (ISearchCriteria sc in criteria) { criteriaProperty = sc as SearchCriteriaProperty; if (criteriaProperty != null && PropertyExpressionKind.Unread == criteriaProperty.WhatKind) { break; } } ItemReadState readState = ItemReadState.Ignore; if (criteriaProperty != null) { readState = criteriaProperty.BeenRead ? ItemReadState.BeenRead : ItemReadState.Unread; } if (r != null && r.ItemMatchCount > 0) { /* append results */ var nids = new SearchHitNewsItem[r.ItemsMatched.Count]; r.ItemsMatched.CopyTo(nids, 0); //look in every feed source to find source feed for matching news items IEnumerable <FeedInfoList> results = Sources.Select(entry => entry.Source.FindNewsItems(nids, readState, returnFullItemText)); foreach (FeedInfoList fil in results) { fiList.AddRange(fil); } feedmatches = fiList.Count; unreturnedMatchItems = fiList.GetAllNewsItems(); itemmatches = unreturnedMatchItems.Count; } } catch (Exception searchEx) { // render the error in-line (search result): fiList.Add(FeedSource.CreateHelpNewsItemFromException(searchEx).FeedDetails); feedmatches = fiList.Count; unreturnedMatchItems = fiList.GetAllNewsItems(); itemmatches = unreturnedMatchItems.Count; } } RaiseSearchFinishedEvent(tag, fiList, unreturnedMatchItems, feedmatches, itemmatches); }
/// <summary> /// Transform a NewsItem, FeedInfo or FeedInfoList using the specified stylesheet /// </summary> /// <param name="stylesheet">The stylesheet to use for transformation</param> /// <param name="transformTarget">The object to transform</param> /// <param name="xslArgs"></param> /// <returns>The results of the transformation</returns> public virtual string ToHtml(string stylesheet, object transformTarget, XsltArgumentList xslArgs) { string link = String.Empty, content = String.Empty; if (transformTarget == null) { return("<html><head><title>empty</title></head><body></body></html>"); } // use a streamed output to get the "disable-output-escaping" // working: StringWriter swr = new StringWriter(); try { XPathDocument doc; if (transformTarget is INewsItem) { INewsItem item = (INewsItem)transformTarget; link = item.FeedLink; content = item.Content; doc = new XPathDocument(new XmlTextReader(new StringReader(item.ToString(NewsItemSerializationFormat.NewsPaper, false))), XmlSpace.Preserve); } else if (transformTarget is IFeedDetails) { IFeedDetails feed = (IFeedDetails)transformTarget; link = feed.Link; doc = new XPathDocument(new XmlTextReader(new StringReader(feed.ToString(NewsItemSerializationFormat.NewsPaper, false))), XmlSpace.Preserve); } else if (transformTarget is FeedInfoList) { FeedInfoList feeds = (FeedInfoList)transformTarget; doc = new XPathDocument(new XmlTextReader(new StringReader(feeds.ToString())), XmlSpace.Preserve); } else { throw new ArgumentException("transformTarget"); } XslCompiledTransform transform; if (this.stylesheetTable.ContainsKey(stylesheet)) { transform = this.stylesheetTable[stylesheet].CompiledTransform; } else { transform = this.stylesheetTable[String.Empty].CompiledTransform; } // support simple localizations (some common predefined strings to display): xslArgs.AddExtensionObject("urn:localization-extension", new LocalizerExtensionObject()); transform.Transform(doc, xslArgs, swr); } catch (ThreadAbortException) { // ignored } catch (Exception e) { this.OnTransformationError(this, new FeedExceptionEventArgs(e, link, SR.ExceptionNewsItemTransformation)); return(content); // try to display unformatted simple text } return(swr.ToString()); }
/// <summary> /// The worker method. /// </summary> /// <param name="task"></param> protected override Exception DoTaskWork(ThreadWorkerTaskBase task) { //if ((Task)task.TaskID == Task.AnonymousDelegate) //{ // Action action = (Action)task.Arguments[0]; // if (action == null) // throw new InvalidOperationException("no Action delegate specified"); // action(); // // default event if no result(s) from processing: // RaiseBackgroundTaskFinished(task, 1, 1, null, null); // return null; //} RssBanditApplication app = ((ThreadWorkerTask)task).Application; int maxTasks = 0, currentTask = 0; bool force; UltraTreeNode feedNode; string stylesheet, html; switch ((Task)task.TaskID) { case Task.LoadAllFeedSourcesSubscriptions: List <FeedSourceEntry> entries = (List <FeedSourceEntry>)task.Arguments[0]; var finished = new ManualResetEvent(false); int max = entries.Count; int current = 0; for (int i = 0; i < max; i++) { IndexedFeedSourceEntry e = new IndexedFeedSourceEntry(entries[i], i); PriorityThreadPool.QueueUserWorkItem( delegate(object state) { IndexedFeedSourceEntry fs = (IndexedFeedSourceEntry)state; int threadCurrent = fs.Index + 1; try { app.LoadFeedSourceSubscriptions(fs.Entry, true); this.RaiseBackroundTaskProgress(task, max, threadCurrent, null, fs.Entry); } catch (Exception loadEx) { this.RaiseBackroundTaskProgress(task, max, threadCurrent, loadEx, fs.Entry); } finally { if (Interlocked.Increment(ref current) >= max) { if (finished != null) { finished.Set(); } } } }, e, 1); } if (max > 0) { finished.WaitOne(Timeout.Infinite, true); } break; case Task.LoadFeedSourceSubscriptions: app.LoadFeedSourceSubscriptions((FeedSourceEntry)task.Arguments[0], true); break; // code mocved to FlaggedItemsFeed migrate method: //case Task.LoadSpecialFeeds: // app.InitializeFlaggedItems(); // break; case Task.RefreshFeeds: force = (bool)task.Arguments[0]; app.FeedSources.ForEach(s => s.RefreshFeeds(force)); break; case Task.RefreshCommentFeeds: force = (bool)task.Arguments[0]; app.CommentFeedsHandler.RefreshFeeds(force); break; case Task.RefreshCategoryFeeds: FeedSourceEntry entry = (FeedSourceEntry)task.Arguments[0]; string category = (string)task.Arguments[1]; force = (bool)task.Arguments[2]; entry.Source.RefreshFeeds(category, force); break; case Task.LoadCommentFeed: INewsItem item = (INewsItem)task.Arguments[0]; if (item == null) { throw new InvalidOperationException("Non-Null task argument 'item' expected."); } object result = null; if ((item.Feed != null) && (item.Feed.owner is IFacebookFeedSource)) { IFacebookFeedSource fbSource = item.Feed.owner as IFacebookFeedSource; result = fbSource.GetCommentsForItem(item); } else { NewsFeed cmtFeed = new NewsFeed(); cmtFeed.link = item.CommentRssUrl; cmtFeed.title = item.Feed.title; if (!string.IsNullOrEmpty(item.Feed.authUser)) { // take over credential settings string u = null, p = null; FeedSource.GetFeedCredentials(item.Feed, ref u, ref p); FeedSource.SetFeedCredentials(cmtFeed, u, p); } result = RssParser.DownloadItemsFromFeed(cmtFeed, app.Proxy, FeedSource.Offline); } RaiseBackgroundTaskFinished(task, maxTasks, currentTask, null, new object[] { result, item, task.Arguments[1], task.Arguments[2] }); return(null); case Task.TransformFeed: IFeedDetails feed = (IFeedDetails)task.Arguments[0]; feedNode = (UltraTreeNode)task.Arguments[1]; stylesheet = (string)task.Arguments[2]; html = app.FormatFeed(stylesheet, feed); RaiseBackgroundTaskFinished(task, maxTasks, currentTask, null, new object[] { feedNode, html }); return(null); case Task.TransformCategory: FeedInfoList feeds = (FeedInfoList)task.Arguments[0]; feedNode = (UltraTreeNode)task.Arguments[1]; stylesheet = (string)task.Arguments[2]; html = app.FormatFeeds(stylesheet, feeds); RaiseBackgroundTaskFinished(task, maxTasks, currentTask, null, new object[] { feedNode, html }); return(null); default: throw new InvalidOperationException("Unhandled ThreadWorker Task: " + task.TaskID); } // default event if no result(s) from processing: RaiseBackgroundTaskFinished(task, maxTasks, currentTask, null, null); return(null); }