2005.07.08 11:12 PM

FlexWiki Notes - Multiple Namespaces

Support for multiple namespaces in FlexWiki is a great feature. I use namespaces extensively to separate content by working groups within a single federation (i.e., FlexWiki instance). When I do this, I like to create a single namespace to act as a repository for content shared by all the namespaces, and then make this namespace the federation's DefaultNamespace (see NamespaceMap.xml). I also like to use this namespace as the gateway for accessing the federation's other namespaces. In other words, on its home page topic I like to provide an index of the federation's other available namespaces with links to their respective home pages. Kind of a namespace portal.

Here's the rub. I could maintain this namespace portal topic page by hand. In other words, anytime a new namespace is added or an old one removed or an existing one's description or contact properties are changed I could navigate to the default namespace's home page, double-click it, and make the necessary additions, removals, and/or changes. But I don't want to. What I want is for the page to maintain itself. What I want is a little WikiTalk on the default namespace's home page that programmatically enumerates the federation's other namespaces and builds the portal for me. What I want is this:

@@
 [
  "||{^!C3}'''Wiki Index'''||",
  Newline,
  "||'''Wiki'''||'''Description'''||'''Contact'''||",
  Newline,
  federation.Namespaces.Select
  {
    each |
    each.Name.Equals(federation.DefaultNamespace).Not
  }
  .Collect
  {  
    e | 
      [ 
        "||", 
        "\"", 
        e.Name, 
        "\":", 
        federation.LinkMaker.LinkToTopic([e.Name, ".", e.HomePage].ToOneString), 
        "||", 
        e.Description, 
        "||", 
        "\"", 
        e.Contact, 
        "\":", 
        "mailto:",
        e.Contact, 
        "||", 
        Newline 
      ]
  }
] 
@@

Unfortunately, I can't have (exactly) that without making some modifications to the FlexWiki engine. Specifically, I can't have the "federation.DefaultNamespace" and "e.HomePage" without some engine modifications, because these properties don't exist out-of-the-box (well, they do exist; they're just not exposed to WikiTalk). Of course, I could still have my WikiTalk without these two things, but then I would have to hardcode the name of the default namespace and hardcode a single name for the home page of the other namespaces. Maybe I'm nuts, but that kind of thing drives me crazy.

Luckily, adding support for these two properties is easy. At least it is once you know how WikiTalk resolves something like "federation.DefaultNamespace" into an object instance and property at runtime. Figuring this out took a little spelunking (it's probably documented somewhere, but I couldn't find it, and in the end found it easier to just read the code). I'll summarize.

During page resolution, the FlexWiki engine will find itself in the TranslateBehaviorsAndEverythingElse function in the FlexWiki.Formatting.Formatter class instantiating a new FlexWiki.Formatting.BehaviorInterpreter to resolve the content between the "@@" behavior delimiters. A call is made to the BehaviorInterpreter's Parse method, which uses a FlexWiki.BehaviorParser to shred the WikiTalk into various kinds of ExposableParseTreeNode objects (DereferencePTN, MethodReferencePTN, StringPTN, IntegerPTN, etc.), all of which include an Expose method that returns an IBELObject. Once this is done, BehaviorInterpreter's EvaluateToPresentation method is called. This leads to the BehaviorInterpreter's EvaluateToObject method where some context manipulation and external wiki importing occurs. The important thing, from our perspective, is the creation of a new FlexWiki.ExecutionContext, which spins up a new FlexWiki.TypeRegistry instance. This TypeRegistry instance is lazy-loaded on the first Registry member access with all of the classes in all of the appdomain's loaded assemblies found to have the FlexWiki.ExposedClass custom attribute. These are added to a HashTable as FlexWiki.BELType objects, loaded via the BELType object's static BELTypeForType method. Later, when a MethodReferencePTN, like DefaultNamespace above, is asked to Expose itself, it will call on the ExecutionContext's FindAndInvoke method, which will call the FlexWiki.Home object's ValueOf method (Home was instantiated during creation of the ExecutionContext), which by way of its FlexWiki.BELObject lineage resolves to the ValueOf method of the abstract base class FlexWiki.ReflectedValueSource and results in a reflection-based method invocation. The method itself is retrieved from a HashTable of FlexWiki.BELMember objects via the BELMembers property of a BELType object, which is returned by the ReflectedValueSource's Type property, which actually gets the BELType using the BELType object's static BELTypeForType method (same as above). The BELMembers property lazy-loads the HashTable of BELMember objects by calling the BELType AddInstanceMembers function, which enumerates the BELType's underlying FlexWiki.CLRType (System.Type) members using reflection, keeping all of those found to have the FlexWiki.ExposedMethod custom attribute.

Did I mention that FlexWiki might be a wee-bit over-engineered?

So, after all that, it turns out that all we need to do to expose the existing FlexWiki.Federation.DefaultNamespace property to WikiTalk is decorate it with the following attribute:

[ExposedMethod("DefaultNamespace", ExposedMethodFlags.CachePolicyNone, "Answer the default namespace")]

And, all we need to do to expose the existing FlexWiki.ContentBase.HomePage property to WikiTalk is decorate it with the following attribute:

[ExposedMethod("HomePage", ExposedMethodFlags.CachePolicyNone, "Answer the name of the home page for this namespace")]

Compile and deploy, and the WikiTalk above should produce a lovely table showing all of the federation's namespaces along with their descriptions, links to their home pages, and mailto links for their contacts. And the best part is I never have to touch this page again.

Before I go, there's one other thing I like to do when using multiple namespaces this way. By default, the title of each topic page includes only the formatted topic name (meaning the Pascal casing is converted to spaces). It doesn't include the namespace. This unqualified title can be problematic when navigating between lots of namespaces (particularly if you keep multiple browser windows open). So I always change the content of the default.aspx TITLE element from this:

  <%= GetTitle() %>

Which calls this:

protected string GetTitle()
{
  string title = TheFederation.GetTopicProperty(GetTopicName(), "Title");
  if (title == null || title == "")
    title = GetTopicName().FormattedName;
  return HTMLStringWriter.Escape(title);
}

To this:

  <%= GetTopicName().ToString() %>

The topic name isn't formatted this way, but at least it's qualified with the namespace.

FlexWiki Notes - Getting Started
FlexWiki Notes


Comments

It was pointed out to me that I could have just used the behavior @@AllNamespacesWithDetails@@ to generate the namespace table. And that's true, I could have.

If I had, though, I wouldn't have been able to control which columns appear in the table (perhaps at some point I'll want to include a home page property), or control the table's format (like the addition of column headings), or exclude the default namespace. But, more importantly, I wouldn't have had an opportunity to delve into and explain the process by which objects are exposed for use in WikiTalk.

That said, it might be worthwhile to explore FlexWiki's behavior code a little bit. Maybe someday.

ewbi.develops | 2005.07.21 04:40 PM

Nice post. And nice job digging around in my somewhat over-engineered code :-)

David Ornstein | 2005.08.01 09:35 PM

Thanks. I really meant it in the very nicest possible way. :-)

Honestly, though, FlexWiki is a gas to work with, and it's solving problems for us everyday. I continue to recommend it highly to my clients, and I really appreciate the effort everyone has poured into over the years.

ewbi.develops | 2005.08.01 10:38 PM

i've been playing around with flexwiki namespaces. do you know if there is a way to have namespaces within namespaces (e.g. have namespaces "management" and "marketing" within the business namespace)

j | 2008.08.11 01:14 PM

j - My first thought is "no"; however, it's been years since I was in that code, so I can't be sure, plus it has come through a recent rewrite, too, so might have changed in this regard. Wish I had time to peek at the code - if you do take a look and confirm that it does/n't support it, please let us know. Good luck!

ewbi.develops | 2008.08.12 11:02 PM

hi. I've recently started using a FlexWiki at work. I'd like to learn more about writing my own WikiTalk scripts, but I can't seem to find an online reference to the language or library when searching google. How did you learn this stuff?

Thx!

new intern | 2009.06.04 07:56 AM

I'm afraid you're in a tough spot. When I learned all this 4-5 years ago there was an on-line guide, an entire FlexWiki wiki, but all that is gone now. After Craig Andera left the project back in Jan 2008, after releasing the 2.0 code base, it just died. The only thing left is the SourceForge project for downloading the 2.0 code and wandering through bugs:

http://sourceforge.net/projects/flexwiki/

Besides what you might scrape up elsewhere on the web, and I'm not seeing anything of value as relates to WikiTalk, I'm afraid you're probably stuck figuring it out by spelunking the FlexWiki source yourself. Or hiring someone who knows it in order to get some training (or to help you convert to a different wiki, perhaps).

Good luck.

ewbi.develops | 2009.06.04 09:21 AM

Whoa, just after writing that I had a thought: it turns out you can still access the old FlexWiki wiki contents using the Internet Archive Wayback Machine:

http://web.archive.org/web/20071231143500/www.flexwiki.com/default.aspx/FlexWiki/WikiTalk.html

The presentation is a little funky, but it's all there as far as I can tell.

ewbi.develops | 2009.06.04 09:26 AM


TrackBack

TrackBack URL:  http://www.typepad.com/services/trackback/6a00d8341c7bd453ef00d8344e550253ef

Listed below are links to weblogs that reference FlexWiki Notes - Multiple Namespaces: