public DynamicTopic DynamicTopicFor(string topic) { if (_Topics == null) _Topics = new Hashtable(); DynamicTopic answer = (DynamicTopic)(_Topics[topic]); if (answer != null) return answer; RelativeTopicName rel = new RelativeTopicName(topic); ArrayList alternatives = new ArrayList(); if (rel.Namespace != null) // if they left the namespace unspec'd { alternatives.Add(new AbsoluteTopicName(topic)); } else { alternatives.Add(new AbsoluteTopicName(topic, Name)); // always try this one first alternatives.AddRange(rel.AllAbsoluteTopicNamesFor(CurrentFederation.ContentBaseForNamespace(Name))); } foreach (AbsoluteTopicName tn in alternatives) { ContentBase cb = CurrentFederation.ContentBaseForTopic(tn); if (!cb.TopicExists(tn)) continue; answer = new DynamicTopic(CurrentFederation, tn); _Topics[topic] = answer; return answer; } return null; }
/// <summary> /// Main formatting function. The process of formatting the input to the output starts here. /// </summary> public void Format() { if (Federation.GetPerformanceCounter(Federation.PerformanceCounterNames.TopicFormat) != null) Federation.GetPerformanceCounter(Federation.PerformanceCounterNames.TopicFormat).Increment(); CurrentState = new NeutralState(this); _CurrentLineIndex = 0; bool inMultilineProperty = false; bool currentMultilinePropertyIsHidden = false; string multiLinePropertyDelim = null; bool inPreBlock=false; bool inExtendedPreBlock = false; string preBlockKey=null; _Output.Begin(); for (int lineNumber = 0; lineNumber < _Source.Count; lineNumber++) { StyledLine eachLine = (StyledLine)(_Source[lineNumber]); string each = eachLine.Text; _Output.Style = eachLine.Style; each = StripHTMLSpecialCharacters(each); if ( inPreBlock ) { if ((each.StartsWith("}+") || each.StartsWith("}@")) && each.Substring(2).Trim() == preBlockKey ) { Ensure(typeof(NeutralState)); inPreBlock = false; preBlockKey = null; } else { if (false == currentMultilinePropertyIsHidden) { each = each.Replace("\t", " "); if (inExtendedPreBlock) { each = ProcessLineElements(each); } _Output.Write(each); _Output.WriteEndLine(); } _CurrentLineIndex++; } continue; } else if ( !inMultilineProperty && (each.StartsWith("{+") || each.StartsWith("{@")) ) { Ensure(typeof(PreState)); inPreBlock = true; inExtendedPreBlock = each.StartsWith("{+"); preBlockKey = each.Substring(2).Trim(); continue; } // Make all the 8-space sequences into tabs each = Regex.Replace(each, " {8}", "\t"); // See if this is the first line of a multiline property. if (!inMultilineProperty && ContentBase.MultilinePropertyRegex.IsMatch(each)) { // OK, here we go -- time to output the header Match m = ContentBase.MultilinePropertyRegex.Match(each); string name = m.Groups["name"].Value; string val = m.Groups["val"].Value; string leader = m.Groups["leader"].Value; string delim = m.Groups["delim"].Value; multiLinePropertyDelim = ContentBase.ClosingDelimiterForOpeningMultilinePropertyDelimiter(delim); currentMultilinePropertyIsHidden = leader == ":"; if (currentMultilinePropertyIsHidden) // just write the anchor for hidden page properties { _Output.WriteOpenAnchor(name); _Output.WriteCloseAnchor(); _Output.WriteLine(""); } else { // Don't bother showing out hidden page properties val = val.Trim(); // Do the normal processing name = StripHTMLSpecialCharacters(name); string linkedName = LinkWikiNames(name); val = StripHTMLSpecialCharacters(val); val = ProcessLineElements(val); _Output.WriteOpenProperty(linkedName); _Output.WriteOpenAnchor(name); if (ContentBase.IsBehaviorPropertyDelimiter(delim)) _Output.Write(delim); _Output.Write(val); } inMultilineProperty = true; continue; } if (inMultilineProperty) { if (each.StartsWith(multiLinePropertyDelim)) { // We're done! if (!currentMultilinePropertyIsHidden) { if (ContentBase.IsBehaviorPropertyDelimiter(multiLinePropertyDelim)) { _Output.Write(multiLinePropertyDelim); } // Make sure we close off things like tables before we close the property. Ensure(typeof(NeutralState)); _Output.WriteCloseAnchor(); _Output.WriteCloseProperty(); } inMultilineProperty = false; currentMultilinePropertyIsHidden = false; continue; } // If it's a line for a property behavior, just show it -- don't perform any processing if (ContentBase.IsBehaviorPropertyDelimiter(multiLinePropertyDelim)) { if (!currentMultilinePropertyIsHidden) { _Output.WriteSingleLine(each); } continue; } } if (Formatter.StripExternalWikiDef(_ExternalWikiMap, each)) continue; // empty line resets everything (except pre and multiline properties ) if (each.Trim().Length == 0) { if (!(CurrentState is PreState) || (CurrentState is PreState && !IsNextLinePre())) Ensure(typeof(NeutralState)); _Output.WriteEndLine(); } else if ((each.StartsWith("----")) && (false == currentMultilinePropertyIsHidden)) { Ensure(typeof(NeutralState)); _Output.WriteRule(); } // insert topic -- {{IncludeSomeTopic}} ? else if ((!each.StartsWith(" ") & Regex.IsMatch(each, @"^[\t]*\{\{" + wikiName + @"\}\}[\s]*$")) && (false == currentMultilinePropertyIsHidden)) { Regex nameGetter = new Regex("(?<topic>" + wikiName + ")"); string name = nameGetter.Matches(each)[0].Groups["topic"].Value; RelativeTopicName topicName = new RelativeTopicName(name); // Count the tabs int tabs = 0; string tabber = each; while (tabber.Length > 0 && (tabber.StartsWith("\t"))) { tabs++; tabber = tabber.Substring(1); } Ensure(typeof(NeutralState)); AddCacheRule(ContentBase.CacheRuleForAllPossibleInstancesOfTopic(topicName)); if (ContentBase.TopicExists(topicName)) { if ((!IsBeyondSafeNestingDepth) && (false == currentMultilinePropertyIsHidden)) { _Output.Write(IncludedTopic(topicName, _HeadingLevelBase + tabs)); } } else { EnsureParaOpen(); _Output.Write(LinkWikiNames(each)); EnsureParaClose(); } } // line begins with a space, it's PRE time! else if ((each.StartsWith(" ") || Regex.IsMatch(each, "^[ \t]+[^ \t*1]")) && (false == currentMultilinePropertyIsHidden)) { Ensure(typeof(PreState)); _Output.Write(Regex.Replace(each, "\t", " ")); } else { // OK, it's likely more complicated // Continue if we're inside a multiline hidden property. if (true == currentMultilinePropertyIsHidden) { continue; } // See if this is a bullet line if (each.StartsWith("\t")) { each = ProcessLineElements(each); // Starts with a tab - might be a list (we'll see) // Count the tabs int thisNest = 0; while (each.Length > 0 && (each.StartsWith("\t"))) { thisNest++; each = each.Substring(1); } if (each.StartsWith("*")) { each = each.Substring(1); // We're in a list - make sure we've got the right <ul> nesting setup // Could need more or fewer Ensure(typeof(UnorderedListState)); ((UnorderedListState)(CurrentState)).SetNesting(thisNest); _Output.WriteListItem(each); } else if (each.StartsWith("1.")) { each = each.Substring(2); Ensure(typeof(OrderedListState)); ((OrderedListState)(CurrentState)).SetNesting(thisNest); _Output.WriteListItem(each); } else { // False alarm (just some tabs) _Output.Write(Regex.Replace(each, "\t", " ")); } } else if (each.StartsWith("||") && each.EndsWith("||") && each.Length >= 4) { bool firstRow = !(CurrentState is TableState); Ensure(typeof(TableState)); TableState ts = (TableState)CurrentState; string endless = each.Substring(2, each.Length - 4); // Write the row bool firstCell = true; foreach (string eachCell in Regex.Split(endless, @"\|\|")) { string cellContent = eachCell; // Check the cell for formatting TableCellInfo info = new TableCellInfo(); if (cellContent.StartsWith("{")) { int end = cellContent.IndexOf("}", 1); if (end != -1) { string fmt = cellContent.Substring(1, end - 1); cellContent = cellContent.Substring(end + 1); string result = info.Parse(fmt); if (result != null) cellContent = "(Error: " + result + ") " + cellContent; } } if (firstCell) { if (firstRow) { ts.HasBorder = info.HasBorder; Output.WriteOpenTable(info.TableAlignment, info.HasBorder, info.TableWidth); } _Output.WriteOpenTableRow(); } _Output.WriteTableCell(ProcessLineElements(cellContent), info.IsHighlighted, info.CellAlignment, info.ColSpan, info.RowSpan, ts.HasBorder, info.AllowBreaks, info.CellWidth, info.BackgroundColor); firstCell = false; } _Output.WriteCloseTableRow(); } else { Ensure(typeof(NeutralState)); // See if we've got a heading prefix int heading = -1; if (each.StartsWith("!!!!!!!")) heading = 7; else if (each.StartsWith("!!!!!!")) heading = 6; else if (each.StartsWith("!!!!!")) heading = 5; else if (each.StartsWith("!!!!")) heading = 4; else if (each.StartsWith("!!!")) heading = 3; else if (each.StartsWith("!!")) heading = 2; else if (each.StartsWith("!")) heading = 1; if (heading != -1) { _Output.WriteHeading(ProcessLineElements(each.Substring(heading)), _HeadingLevelBase + heading); } else { // If it's a single-line field, wrap it visually if (ContentBase.PropertyRegex.IsMatch(each)) { Match m = ContentBase.PropertyRegex.Match(each); string name = m.Groups["name"].Value; string val = m.Groups["val"].Value; string leader = m.Groups["leader"].Value; bool isLeader = leader == ":"; // Write out an anchor tag. if (isLeader) // Only bother writing anchor and name for hidden page properties { _Output.WriteOpenAnchor(name); _Output.WriteCloseAnchor(); } else { // Do the normal processing string linkedName = LinkWikiNames(name); val = val.Trim(); val = ProcessLineElements(val); _Output.WriteOpenProperty(linkedName); _Output.WriteOpenAnchor(name); _Output.Write(val); _Output.WriteCloseAnchor(); _Output.WriteCloseProperty(); } } else { // As vanilla as can be -- just send it along each = ProcessLineElements(each); EnsureParaOpen(); _Output.Write(each); } } } } EnsureParaClose(); if (false == currentMultilinePropertyIsHidden) { _Output.WriteEndLine(); } _CurrentLineIndex++; } _Output.End(); CurrentState = null; // Make sure to do this so the last state gets Exit() }
private string LinkWikiNames (string input) { StringBuilder answer = new StringBuilder(); string str = input; ArrayList processed = new ArrayList(); while (str.Length > 0) { Match m = extractWikiLinks.Match(str); if (!m.Success) break; string each = m.Groups["topic"].ToString(); string before = m.Groups["before"].ToString(); string after = m.Groups["after"].ToString(); string relabel = m.Groups["relabel"].ToString(); string anchor = m.Groups["anchor"].ToString(); RelativeTopicName relName = new RelativeTopicName(TopicName.StripEscapes(each)); // Ignore apparent links to non-existent namespaces. if ((null == relName.Namespace) || (null != TheFederation.ContentBaseForNamespace(relName.Namespace))) { // Build a list of all the possible absoluteNames for this topic ArrayList absoluteNames = new ArrayList(); // Start with the singulars in the various reachable namespaces, then add the plurals absoluteNames.AddRange(ContentBase.AllAbsoluteTopicNamesThatExist(relName)); AddCacheRule(ContentBase.CacheRuleForAllPossibleInstancesOfTopic(relName)); foreach (TopicName alternate in relName.AlternateForms) { AddCacheRule(ContentBase.CacheRuleForAllPossibleInstancesOfTopic(alternate)); absoluteNames.AddRange(ContentBase.AllAbsoluteTopicNamesThatExist(alternate)); } // Now see if we got any hits or not string rep = beforeOrRelabel + "(" + RegexEscapeTopic(each) + ")" + afterWikiName; AbsoluteTopicName appearedAs = new AbsoluteTopicName(each); // in case it was a plural form, be sure to show it as it appeared string displayname = TopicName.StripEscapes((ContentBase.DisplaySpacesInWikiLinks ? appearedAs.FormattedName : appearedAs.Name)); if (relabel.Length > 0) { displayname = relabel; } if (absoluteNames.Count == 0) { if (!IsUnbracketedOneWordName(each)) { // It doesn't exist, so give the option to create it AbsoluteTopicName abs = relName.AsAbsoluteTopicName(ContentBase.Namespace); str = ReplaceMatch(answer, str, m, before + "<a title=\"Click here to create this topic\" class=\"create\" href=\"" + LinkMaker().LinkToEditTopic(abs) + "\">" + displayname + "</a>" + after); } else str = ReplaceMatch(answer, str, m, m.Value); } else { // We got hits, let's add links if (absoluteNames.Count == 1) { // The simple case is that there's only one link to point to, so we output just a normal link AbsoluteTopicName abs = (AbsoluteTopicName)absoluteNames[0]; string tip = TipForTopic(abs); string tipid = null; string tipHTML = null; bool defaultTip = tip == null; if (defaultTip) { tip = "Click to read this topic"; } tipid = NewUniqueIdentifier(); tipHTML = Formatter.EscapeHTML(tip); if (defaultTip) { tipHTML = "<span class=\"DefaultTopicTipText\">" + tipHTML + "</span>"; } tipHTML += "<div class=\"TopicTipStats\">" + TheFederation.GetTopicModificationTime(abs).ToString() + " - " + TheFederation.GetTopicLastModifiedBy(abs) + "</div>"; tipHTML = "<div id=" + tipid +" style=\"display: none\">" + tipHTML + "</div>"; Output.AddToFooter(tipHTML); string replacement = "<a "; if (tip != null) { replacement += "onmouseover=\"TopicTipOn(this, '" + tipid + "', event);\" onmouseout=\"TopicTipOff();\" "; } replacement += "href=\"" + LinkMaker().LinkToTopic(abs); if (anchor.Length > 0) { replacement += "#" + anchor; if (0 == relabel.Length) { displayname += "#" + anchor; } } replacement += "\">" + displayname + "</a>"; str = ReplaceMatch(answer, str, m, before + replacement + after) ; } else { // There's more than one; we need to generate a dynamic menu string clickEvent; clickEvent = "onclick=\"javascript:LinkMenu(new Array("; bool first = true; foreach (AbsoluteTopicName eachAbs in absoluteNames) { if (!first) clickEvent += ", "; first = false; clickEvent += "new Array('" + eachAbs + "', '" + LinkMaker().LinkToTopic(eachAbs) + "')"; } clickEvent += "), event);\""; str = ReplaceMatch(answer, str, m, before + "<a title=\"Different versions of this topic exist. Click to pick one.\" " + clickEvent + ">" + displayname + "</a>" + after) ; } } } else { str = ReplaceMatch(answer, str, m, before + relName.Fullname + after); } } // Add on whatever's not yet been consumed answer.Append(str); return answer.ToString(); }
private string ProcessWikiLinks(string str) { MatchCollection matches = wikiURIRegex.Matches(str); ArrayList processed = new ArrayList(); string answer = str; foreach (Match m in matches) { string uriString = m.Groups["uri"].ToString(); if (processed.Contains(uriString)) { continue; // skip dup } processed.Add(uriString); // Get the pieces string authority = m.Groups["authority"].ToString(); string path = m.Groups["path"].ToString(); string fragment = m.Groups["fragment"].ToString(); // OK, we have a good URI -- let's decide if it's: // wiki://topic // Case 1 - Link to the topic // wiki://topic/rez… // Case 2 - Read the topic, rewrite using the LibraryURL // wiki://topic/#property // Case 3 - Inline the property value if (path == "" || path == "/") { // We've got only a topic RelativeTopicName topicName = new RelativeTopicName(authority); // See if we want the whole topic or just a property (via a fragment) if (fragment != "") { // Case 3 -- Ask for a property AbsoluteTopicName abs = null; bool ambig = false; AddCacheRule(ContentBase.CacheRuleForAllPossibleInstancesOfTopic(topicName)); try { abs = ContentBase.UnambiguousTopicNameFor(topicName); } catch (TopicIsAmbiguousException) { ambig = true; } string replacement; if (abs != null) { // Got a unique URI it! replacement = TheFederation.GetTopicProperty(abs, fragment); } else { if (ambig) replacement = "(ambiguous topic name: " + topicName + ")"; else replacement = "(unknown topic name: " + topicName + ")"; } answer = answer.Replace(uriString, replacement); } else { // Case 1 - a whole topic answer = LinkWikiNames(authority); } } else { // Case 2 - We're being asked for a resource in a resource library AbsoluteTopicName abs = null; RelativeTopicName topicName = new RelativeTopicName(authority); bool ambig = false; AddCacheRule(ContentBase.CacheRuleForAllPossibleInstancesOfTopic(topicName)); try { abs = ContentBase.UnambiguousTopicNameFor(topicName); } catch (TopicIsAmbiguousException) { ambig = true; } string replacement; if (abs != null) { // Got a unique URI it! string uriForLibrary = TheFederation.GetTopicProperty(abs, "URI"); string pathWithoutPrefixSlash = path.TrimStart('/'); string resourceURI = uriForLibrary.Replace("$$$", pathWithoutPrefixSlash); replacement = LinkHyperLinks(resourceURI); } else { if (ambig) replacement = "(ambiguous library topic name: " + topicName + ")"; else replacement = "(unknown library topic name: " + topicName + ")"; } answer = answer.Replace(uriString, replacement); } } return answer; }
/// <summary> /// Answer a list of the wikitext components (IBELObjects) of the given border. If nothing specifies any border; answer the system default /// </summary> /// <param name="name"></param> /// <param name="border"></param> /// <param name="rule"></param> /// <returns></returns> private IEnumerable BorderText(AbsoluteTopicName name, Border border, CompositeCacheRule rule) { ArrayList answer = new ArrayList(); ContentBase cb; string bordersTopicsProperty = "Borders"; ArrayList borderTopics = new ArrayList(); // Start with whatever the namespace defines if (Borders != null) { foreach (string at in ParseListPropertyValue(Borders)) { AbsoluteTopicName abs = new AbsoluteTopicName(at); cb = ContentBaseForTopic(abs); if (abs == null || cb == null) { throw new Exception("Unknown namespace listed in border topic (" + at +") listed in federation configuration Borders property."); } borderTopics.Add(at); } } // If the namespace, specifies border topics, get them cb = ContentBaseForTopic(name); if (cb != null) { borderTopics.AddRange(GetTopicListPropertyValue(cb.DefinitionTopicName, bordersTopicsProperty)); rule.Add(cb.CacheRuleForAllPossibleInstancesOfTopic(cb.DefinitionTopicName)); } // If there are no border topics specified for the federation or the namespace, add the default (_NormalBorders from the local namespace) if (borderTopics.Count == 0) { borderTopics.Add("_NormalBorders"); } // Finally, any border elements form the topic itself (skip the def topic so we don't get double borders!) if (cb == null || cb.DefinitionTopicName.ToString() != name.ToString()) { borderTopics.AddRange(GetTopicListPropertyValue(name, bordersTopicsProperty)); } Set done = new Set(); foreach (string borderTopicName in borderTopics) { // Figure out what the absolute topic name is that we're going to get this topic from RelativeTopicName rel = new RelativeTopicName(borderTopicName); if (rel.Namespace == null) { rel.Namespace = name.Namespace; } AbsoluteTopicName abs = new AbsoluteTopicName(rel.Name, rel.Namespace); if (done.Contains(abs)) { continue; } done.Add(abs); IBELObject s = BorderPropertyFromTopic(name, abs, border, rule); if (s != null) { answer.Add(s); } } return answer; }
protected void DoHead() { AbsoluteTopicName topic = GetTopicName(); LinkMaker lm = TheLinkMaker; // Consider establishing a redirect if there's a redirect to a topic or an URL string redir = TheFederation.GetTopicProperty(GetTopicName(), "Redirect"); if (redir != "") { UriBuilder URI = null; if (IsAbsoluteURL(redir)) { URI = new UriBuilder(redir); } else { // Must be a topic name string trimmed = redir.Trim(); RelativeTopicName rel = new RelativeTopicName(trimmed); IList all = TheFederation.ContentBaseForTopic(GetTopicName()).AllAbsoluteTopicNamesThatExist(rel); if (all.Count == 1) { URI = new UriBuilder(lm.LinkToTopic((TopicName)(all[0]), false, Request.QueryString)); } else { if (all.Count == 0) Response.Write("<!-- Redirect topic does not exist -->\n"); else Response.Write("<!-- Redirect topic is ambiguous -->\n"); } } if (URI != null) { if (Request.QueryString["DelayRedirect"] == "1") Response.Write(@"<meta http-equiv='refresh' content='10;URL=" + URI + "'>\n"); else { Response.Redirect(URI.Uri.ToString()); return; } } } string keywords = TheFederation.GetTopicProperty(GetTopicName(), "Keywords"); if (keywords != "") Response.Write("<META name=\"keywords\" content=\"" + keywords + "\">\n"); string description = TheFederation.GetTopicProperty(GetTopicName(), "Summary"); if (description != "") Response.Write("<META name=\"description\" content=\"" + description + "\">\n"); Response.Write("<META name=\"author\" content=\"" + TheFederation.GetTopicLastModifiedBy(GetTopicName()) + "\">\n"); if (GetTopicName().Version != null) { // Don't index the versions Response.Write("<meta name=\"Robots\" content=\"NOINDEX, NOFOLLOW\">"); } urlForDiffs = lm.LinkToTopic(topic, true); urlForNoDiffs = lm.LinkToTopic(topic, false); }
string TopicLink(string top, bool showDiffs, NameValueCollection extraQueryParms) { StringBuilder builder = new StringBuilder(); RelativeTopicName topic = new RelativeTopicName(top); builder.Append(SiteURL()); builder.Append("default.aspx/"); if (topic.Namespace != null && topic.Namespace != "") builder.Append(HttpUtility.UrlEncode(topic.Namespace) + "/"); builder.Append(topic.Name); if (topic.Version != null) builder.Append("(" + HttpUtility.UrlEncode(topic.Version) + ")"); builder.Append(".html"); // hard coded for now -- later we'll be cooler! StringBuilder query = new StringBuilder(); if (showDiffs) query.Append("diff=y"); if (extraQueryParms != null) { foreach (string each in extraQueryParms) { if (query.Length != 0) query.Append("&"); query.Append(each + "=" + HttpUtility.UrlEncode((string)(extraQueryParms[each]))); } } if (query.Length != 0) builder.Append("?" + query.ToString()); return builder.ToString(); }
/// <summary> /// Rename references (in a given topic) from one topic to a new name /// </summary> /// <param name="topicToLookIn"></param> /// <param name="oldName"></param> /// <param name="newName"></param> /// <returns></returns> public bool RenameTopicReferences(LocalTopicName topicToLookIn, AbsoluteTopicName oldName, AbsoluteTopicName newName, FederationUpdateGenerator gen) { string current = Read(topicToLookIn); MatchCollection wikiNames = Formatter.extractWikiNames.Matches(current); ArrayList processed = new ArrayList(); bool any = false; foreach (Match m in wikiNames) { string each = m.Groups["topic"].ToString(); if (processed.Contains(each)) { continue; // skip dup } processed.Add(each); RelativeTopicName relName = new RelativeTopicName(TopicName.StripEscapes(each)); // See if this is the old name. The only way it can be is if it's unqualified or if it's qualified with the current namespace. bool hit = (relName.Name == oldName.Name) && (relName.Namespace == null || relName.Namespace == oldName.Namespace); if (!hit) continue; // Now see if we got any hits or not string rep = Formatter.beforeWikiName + "(" + Formatter.RegexEscapeTopic(each) + ")" + Formatter.afterWikiName; // if the reference was fully qualified, retain that form in the new reference string replacementName = each.IndexOf(".") > -1 ? newName.Fullname : newName.Name; current = Regex.Replace(current, rep, "${before}" + replacementName + "${after}"); any = true; } if (any) { WriteTopicAndNewVersion(topicToLookIn, current, gen); } return any; }
/// <summary> /// Answer a hash: keys are topic; values are an array of topic names for referenced topics (in this content base) /// </summary> /// <param name="filterToTopic">Specific topic for which reference information is desired (null gets info for all topics)</param> /// <param name="existingOnly">Specific whether to only return the referenced topics that actually exist</param> /// <returns></returns> public Hashtable AllReferencesByTopic(AbsoluteTopicName filterToTopic, bool existingOnly) { Hashtable relativesToRefs = new Hashtable(); Hashtable answer = new Hashtable(); IEnumerable topicList; if (filterToTopic == null) topicList = AllTopics(false); else { ArrayList list = new ArrayList(); list.Add(filterToTopic); topicList = list; } foreach (AbsoluteTopicName topic in topicList) { string current = Federation.Read(topic); MatchCollection wikiNames = Formatter.extractWikiNames.Matches(current); ArrayList processed = new ArrayList(); ArrayList allReferencedTopicsFromTopic = new ArrayList(); foreach (Match m in wikiNames) { string each = m.Groups["topic"].ToString(); if (processed.Contains(each)) { continue; // skip dup } processed.Add(each); RelativeTopicName relName = new RelativeTopicName(TopicName.StripEscapes(each)); // Now either calculate the full list of referenced names and cache it or get it from the cache ArrayList absoluteNames = (ArrayList)(relativesToRefs[relName]); if (absoluteNames == null) { absoluteNames = new ArrayList(); relativesToRefs[relName] = absoluteNames; // Start with the singulars in the various reachable namespaces, then add the plurals if (existingOnly) { absoluteNames.AddRange(AllAbsoluteTopicNamesThatExist(relName)); foreach (TopicName alternate in relName.AlternateForms) absoluteNames.AddRange(AllAbsoluteTopicNamesThatExist(alternate)); } else { absoluteNames.AddRange(relName.AllAbsoluteTopicNamesFor(this)); foreach (TopicName alternate in relName.AlternateForms) absoluteNames.AddRange(alternate.AllAbsoluteTopicNamesFor(this)); } } allReferencedTopicsFromTopic.AddRange(absoluteNames); } answer[topic] = allReferencedTopicsFromTopic; } return answer; }
public string Property(ExecutionContext ctx, string topic, string property) { AbsoluteTopicName abs = null; bool ambig = false; string answer = null; try { ContentBase cb = ctx.CurrentContentBase; if (cb == null) cb = ctx.CurrentFederation.DefaultContentBase; RelativeTopicName rel = new RelativeTopicName(topic); ctx.AddCacheRule(cb.CacheRuleForAllPossibleInstancesOfTopic(rel)); abs = cb.UnambiguousTopicNameFor(rel); } catch (TopicIsAmbiguousException) { ambig = true; } if (abs != null) { // Got a unique one! answer = ctx.CurrentFederation.GetTopicProperty(abs, property); } else { if (ambig) throw new ArgumentException("Ambiguous topic name: " + topic); else throw new ArgumentException("Unknown topic name: " + topic); } return answer; }
public IEnumerable GetAllNewsletterNames(string namespaceFilter) { ArrayList answer = new ArrayList(); foreach (ContentBase cb in TheFederation.ContentBases) { if (namespaceFilter != null && cb.Namespace != namespaceFilter) continue; foreach (string s in TheFederation.GetTopicListPropertyValue(cb.TopicNameFor("WikiNewsletterIndex"), "Newsletters")) { RelativeTopicName rel = new RelativeTopicName(s); answer.AddRange(cb.AllAbsoluteTopicNamesThatExist(rel)); } } return answer; }
// Updated 2004-01-29 by CraigAndera public IEnumerable AllTopicsForNewsletter(AbsoluteTopicName newsletter) { // HybridDictionary switches between using a ListDictionary and a Hashtable // depending on the size of the collection - should be a good choice since we don't // know how big the collection of topic names will be HybridDictionary answer = new HybridDictionary(); ContentBase cb = ContentBaseForNewsletter(newsletter); foreach (string s in TheFederation.GetTopicListPropertyValue(newsletter, "Topics")) { // If the wildcard appears, ignore all the other topics listed - include every topic if (s == "*") { answer.Clear(); foreach (AbsoluteTopicName atn in cb.AllTopics(false)) { answer.Add(atn.Fullname, atn); } // No need to continue iterating after we find the wildcard break; } else { RelativeTopicName rel = new RelativeTopicName(s); foreach (AbsoluteTopicName atn in cb.AllAbsoluteTopicNamesThatExist(rel)) { answer.Add(atn.Fullname, atn); } } } // Now we need to remove any topics that appear in the Exclude field foreach (string s in TheFederation.GetTopicListPropertyValue(newsletter, "Exclude")) { RelativeTopicName rel = new RelativeTopicName(s); foreach (AbsoluteTopicName atn in cb.AllAbsoluteTopicNamesThatExist(rel)) { answer.Remove(atn.Fullname); } } // Do the same for "Excludes", since it's hard to remember which one to use foreach (string s in TheFederation.GetTopicListPropertyValue(newsletter, "Excludes")) { RelativeTopicName rel = new RelativeTopicName(s); foreach (AbsoluteTopicName atn in cb.AllAbsoluteTopicNamesThatExist(rel)) { answer.Remove(atn.Fullname); } } return answer.Values; }