OK I have an evaluation version of the Topologi Collaborative Markup Editor, and I want to write a plugin. How do I do it, as there are no docs provided.

Here goes some Friday afternoon type digging around.

Disclaimer : this is not an official Topologi guide by any stretch of the imagination. Its just my hacking around. Follow these instructions at your own risk. Anything I claim about the Topologi tool is based on my own (mis-)understanding. Please don't take them as any reflection on the products capabilities: it's very cool.

The Plugins Directory

In the distro there's a plugins directory which appears to contain all the plugin code. A number of the existing menu options appear to be written as plugins, e.g Validation, Table Editor, etc.

The sub-directories of the plugin directory seem to match up with particular menu commands, although not all of them have plugins in them. However the process sub-directory does, so we'll start there.

There's also a standard directory structure below each of these directories, as follows:

/central
/local
/peer
/topologi

I suspect these map to the various places where plugins might come from (i.e. a central download server, installed locally, shared by a peer, or bundled with the distro). All the existing plugins are in the topologi directory.

Making a Hello World plugin.

Here's a simple Hello World plugin that will write a message to the status line, and then return. We'll add it to the Tools -> Process menu.

Here's the script:

// Hello Word Plugin for Topologi

import com.topologi.tme1.io.plugins.*;
import com.topologi.tme1.services.statusbar.*;

executePlugIn(PlugInData p, PlugInResultHandler handler) {
   
   p.getStatusLine().handleMessage(
     new StatusMessage(
       "Hello Topologi World", 
       StatusMessage.TIP, 
       StatusMessage.GENERAL_SERVICE, 
       StatusMessage.GENERAL_PRIORITY, 
       (short) 50));

   handler.handleScriptResult(null);
   return;
   
}
   
boolean isEnabled(TopologiDocument td) {
    return true;
}

return (PlugInScript) this;

Several things to note:

  • It looks like scripts are written in using the Bean Scripting Framework
  • The executePlugIn function is the function thats actually called by TME to get the Plugin to do its work. It gets passed in some data, and a handler.
  • If you simply return from a plugin the mouse icon seems to get messed up occasionally: it stays on the 'busy' hourglass. However if you call handler.handlerScriptResult(null) then the cursor is changed correctly. Probably part of the plugin life-cycle.
  • the isEnabled function allows a plugin to check whether its properly enabled or not. For example if might check the document type to ensure that its applicable.
  • PluginScript seems to be the base class for scripts written using the BSH. Looking in MarkupEditor.jar I see a Plugin class, so probably one can write plugins using plain old Java.

To get this to execute we need to:

  1. save the script to the /plugins/process/topologi directory, and then restart the editor. However changes to the script whilst the editor is running do take effect. Actually it seems that you can save a script to any of the sub-directories and they'll be loaded.
  2. naming conventions seem to be a key part of Topologi:
    1. The script must have a .bsh extension
    2. The menu title is taken from the file name, with underscores converted to spaces
    3. For some reason the script doesn't load unless there's a number in the filename. So Hello_World-1.bsh works, but Hello_World.bsh doesn't.

After restarting the editor you should have a new Process menu item. Selecting it will produce a "Hello Topologi World" message in the status bar.

More About Status Messages

A status bar message is described by com.topologi.services.statusbar.StatusMessage.

You create a message with the following parameters in the constructor:

  • The text
  • The type of message (one of several constants: QUERY, TIP, INFO, WARNING, ERROR, OK )
  • The type of service sending the message (one of several constants: PERSON, VALIDATION, PROCESS, PREVIEW, PLUGINS, WWW}}})
  • The message priority (one of several constants)
  • The message time out (a short, probably msecs)

Plugins

Plugins are implemented safely, in that the editor only provides access to various data and services through the PluginData and PluginResultHandler classes. PluginScript.executePlugIn returns void so all changes to the editing environment are made through side-effects of working with those two objects.

Note: I found a loop-hole, you can call System.exit from a PluginScript and the editor exits.

Open Plugins

Found in plugins/open/topologi. There are two basic patterns:

TypeTypical ExampleDescription
Simple Text Filesplugins/open/topologi/txt-01.bshPre-condition checks for null filename (PlugInData.getFilename) and sends status bar message if so. Otherwise sets the DOCUMENT_NOTATION (i.e. its type) and then invokes a TranscodingRunner which presumably loads the file and handles any character set issues
Zip Based Filesplugins/open/topologi/zip-01.bshAs above, excepts delegates to ZipOpenRunner to actually open the file. This creates a new dialog showing the contents of the zip so you can open individual files.
XML Filesplugins/open/topologi/xml-01.bshAfter the pre-conditions, but before invoking the TranscodingRunner the first 1024 bytes of the file are read to find a XAR Processing Instruction. If its found then the DOCUMENT_XAR_FILENAME is set. In some cases a default is also provided.

Open scripts are invoked when you open a file with a particular extension. Again naming conventions appear to apply so zip-01.bsh will be invoked for files with the extension of .zip.

Here's a script for opening Enterprise Application Archive files. Basically its just a copy of zip-01.bsh which I've saved as plugins/open/local/ear-01.bsh. Notice the status bar message that should appear when you open a EAR file (if you don't have one then just rename any zip files to the correct extension)

// Topologi 'Open' Plugin for Enterprise Archive Files

import java.io.*;
import com.topologi.tme1.io.plugins.*;
import com.topologi.tme1.io.plugins.zipopen.*;
import com.topologi.tme1.io.worklistmodel.*;
import com.topologi.tme1.services.statusbar.*;

executePlugIn(PlugInData  p, PlugInResultHandler handler)  {

   // handle bad data
   if (p.getFilename().equals("") && p.getData() == null && p.getBinary() == null)  
   {
      p.getStatusLine().handleMessage(
          new StatusMessage("No data info sent to the plugin script", 
          StatusMessage.TIP, 
          StatusMessage.GENERAL_SERVICE, 
          StatusMessage.GENERAL_PRIORITY, (short) 50));

      handler.handleScriptResult(p);
      return;
   }

   p.getStatusLine().setMessage("I'm running the EAR script");

   ZipOpenRunner runner = new ZipOpenRunner(handler);
   runner.zipCall(p);
}

boolean isEnabled(TopologiDocument td) {
    return true;
}

return (PlugInScript)this;

Close Plugins

These are executed when a particular type of file is closed. You can confirm this with the following script. Save it as plugins/close/local/txt-01.bsh.

// Topologi 'Close' Plugin for txt Files

import java.io.*;
import com.topologi.tme1.io.plugins.*;
import com.topologi.tme1.services.statusbar.*;
import com.topologi.tme1.io.worklistmodel.*;

executePlugIn(PlugInData  p, PlugInResultHandler handler)  {

   p.getStatusLine().setMessage("I'm running the txt close script");

   //be sure to return the PlugInData here rather than null, or 
   //the file won't actually be closed.
   handler.handleScriptResult(p);
   return;

}

boolean isEnabled(TopologiDocument td) {
    return true;
}

return (PlugInScript)this;

Plugin Ideas

Here are some ideas for TME plugins that people might find useful.

  • XML-RPC Import/Export. Specifically using the XML-RPC protocol supported by Blogger and other tools.
  • WEB DAV Import/Export. As above except supporting WEB DAV.

More to follow

Add new attachment

In order to upload a new attachment to this page, please use the following box to find the file, then click on “Upload”.
« This page (revision-1) was last changed on 27-Aug-2002 08:10 by unknown [RSS]
G’day (anonymous guest) My Prefs


Referenced by
Main

JSPWiki v2.6.0 [RSS]