As I briefly described in my last post (“How to extend Notes 8: dynamic extensions using Java“) it’s possible to create new extensions to Lotus Notes using Java and hence inject functionality into the client dynamically. It’s very cool functionality and it allows you to inject anything from content types and recognizers to sidebar panels.
In this post I’ll build on three previous posts and show you how to use dynamic extensions in Lotus Notes in combination with a Java action that uses multiple capture groups for an end-to-end solution that may be deployed as a single Java extension (aka plugin). The result is a plugin that may be deployed to a client workstations which allows you to act on text recognized by the LiveText sub-system but where you have the power of Java for processing.
All the posts in the series may be found under the extending_notes8 tag.
We need three pieces of information:
- The code to dynamically inject our custom recognizer and content type into Lotus Notes without the need for an extension.xml file. This is what the LiveText sub-system uses to highlight the text for us.
- The Java action to act on the LiveText selection.
- The plugin.xml file to bind it all together.
The first piece is the code that injects the custom recognizer and content type under a known id. This code may be run in lots of ways but to make it easy for this example I choose a sidebar panel. Below is the createPartControl-method from that class.
public void createPartControl(final Composite parent) { try { // define XML final String extensionXml = ...; // get extension registry and load extension // into registry final IExtensionRegistry reg = Platform.getExtensionRegistry(); InputStream ins = new ByteArrayInputStream(extensionXml.getBytes()); Bundle bundle = Activator.getDefault().getBundle(); IContributor contr = ContributorFactoryOSGi.createContributor(bundle); reg.addContribution(ins, contr, false, null, null, null); } catch (Throwable t) { t.printStackTrace(); } }
The above code injects the recognizer and content type with an id of DCCT.ExampleContentType.1234567890 into the client.
The next part we need is the action class (again implementing org.eclipse.ui.IObjectActionDelegate) to act on the LiveText selection. Most of the code you’ve seen before in a previous post but again it goes and get the text from the underlying document as document properties.
public void selectionChanged(IAction action, ISelection selection) { IDocumentContent doc = null; // cast/adapt selection if (selection instanceof StructuredSelection) { Object sel = ((StructuredSelection)selection).getFirstElement(); if (sel instanceof IDocumentContent) { doc = (IDocumentContent)sel; } } else if (selection instanceof IDocumentContent) { doc = (IDocumentContent)selection; } else { // try and adapt IAdapterManager amgr = Platform.getAdapterManager(); doc = (IDocumentContent)amgr.getAdapter(selection, IDocumentContent.class); } if (null == doc) { this.contents = null; this.prodFamily = null; this.partNumber = null; return; } // get data from document property this.contents = doc.getProperties().getProperty("contents"); this.prodFamily = doc.getProperties().getProperty("pf"); this.partNumber = doc.getProperties().getProperty("pn"); }
The last piece is the plugin.xml to put it all together using the org.eclipse.ui.popupMenus extension point. Notice how we use the content type id we know (bold text below) from our dynamically deployed content type.
<extension point="org.eclipse.ui.popupMenus"> <objectContribution id="com.lekkimworld.extnotes8.dynext.objCtr1" objectClass="com.ibm.rcp.content.IDocumentContent"> <visibility> <and> <objectState name="content.type" value="DCCT.ExampleContentType.1234567890"> </objectState> <objectState name="contents" value="*"> </objectState> </and> </visibility> <action class="com.lekkimworld.extnotes8.dynext.MyAction" enablesFor="*" id="com.lekkimworld.extnotes8.dynext.action1" label="Do me!"> </action> </objectContribution> </extension>
The result when deployed to a Lotus Notes client is something like the screenshot below where you get a Java action to act on a LiveText recognition. Only change this time is that all the functionality is provided from your plugin. No separate extension.xml is necessary for the recognizer or the content type.
That’s how it’s done. I’ve uploaded an Eclipse project to the blog so you can download it and install it in your Eclipse as a demo. You can download the project here.
Hi Mikkel,
Thanks for uploading the file, download here takes me to the login page. can you pl. fix it?
thanks,
bernd
LikeLike
Sorry – fixed the link.
LikeLike
Hi Mikkel,
Thanks for spending the time to write this up, it is very useful.
I myself am trying to take the reverse approach and make available existing live text functionality into a java SWT label. I am able to use the ContentTypeRegistry registry = ContentTypeRegistry.getDefault(); to get all the content types such as address, etc. but I am not able to figure out how to get the actions that I already have mapped.
I can get my eclipse popup contributions but I am unsure how to relate that to my content types… Any ideas?
LikeLike
I think you would have to loop through the org.eclipse.ui.popupMenu contributions and see which fit the bill that is which ones maps to the content type you have in mind. By mapping to I mean which one(s) have an objectState where the content.type attribute points to your content type id.
LikeLike
I’ve discovered a lot in the past few days. For example there is a com.ibm.rcp.annotation.regex.RegexRegistry that you can use to get all your custom regex (by pure luck, as I haven’t seen any documentation). I’ve done this to get all my regex, see if my java input matches the regex, if so, I can look up which content types match the ID. I can then build DocumentContent objects from the input and the content type.
But I am still not sure how to fire off the org.eclipse.osgi.popupmenu from my java tree or table which contains the input live text (DocumentContent objects). Any ideas? I am struggling to find documentation on this.
LikeLike