<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>lekkimworld.comIBM</title>
    <link>http://lekkimworld.com/categories/ibm_products/</link>
    <description>A blog by IBM Champion Mikkel Flindt Heisterberg about IBM Notes/Domino, Websphere, IBM Connections, mobile, web, JavaScript, Java and other appdev topics...</description>
    <language>en</language>
    <copyright>Mikkel Flindt Heisterberg (mh [at] intravision [dot] dk</copyright>
    <pubDate>Wed, 08 May 2013 13:44:17 GMT</pubDate>
    <dc:creator>Mikkel Flindt Heisterberg (mh [at] intravision [dot] dk</dc:creator>
    <dc:date>2013-05-08T13:44:17Z</dc:date>
    <dc:language>en</dc:language>
    <dc:rights>Mikkel Flindt Heisterberg (mh [at] intravision [dot] dk</dc:rights>
    <image>
      <title>lekkimworld.comIBM</title>
      <url>http://lekkimworld.com/categories/ibm_products/</url>
    </image>
    <item>
      <title>A TAI code example</title>
      <link>http://lekkimworld.com/2011/06/10/a_tai_code_example.html</link>
      <content:encoded>&lt;p&gt;
To complete &lt;a href="http://lekkimworld.com/tags/tai"&gt;my series posts&lt;/a&gt; on writing Trust Association Interceptors (TAI's) for Websphere Application Server I wanted to show a real-life example. Not a good example necessarily but an example never the less... :-)
&lt;/p&gt;
&lt;p&gt;
The below example is a very simple TAI that simply does the following:
&lt;ol&gt;
&lt;li&gt;The initialize() method reads a cookie name from the configuration done in the Websphere Application Server ISC. It illustrates how you can configure a TAI externally without having to hard code it.&lt;/li&gt;
&lt;li&gt;The isTargetInterceptor() method looks at the request and sees if a cookie with the configured name is available. If yes it continues to process the request and if not it aborts processing (from the TAI point of view).&lt;/li&gt;
&lt;li&gt;The negotiateValidateandEstablishTrust() method does the actual work by simply telling WAS that the username of user is the value from the cookie.&lt;/li&gt;
&lt;/ol&gt;
As you see writing a TAI is very simple but extremely powerful. Imagine what could be done if you did SSO between Websphere Application Server and Lotus Domino.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
import java.util.Properties;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.websphere.security.WebTrustAssociationException;
import com.ibm.websphere.security.WebTrustAssociationFailedException;
import com.ibm.wsspi.security.tai.TAIResult;
import com.ibm.wsspi.security.tai.TrustAssociationInterceptor;

public class ExampleTAI implements TrustAssociationInterceptor {
   // declarations
   private String cookie = null;
   
   @Override
   public void cleanup() {
   }

   @Override
   public String getType() {
      return String.format("Example TAI %s", this.getVersion());
   }

   @Override
   public String getVersion() {
      return "1.0";
   }

   @Override
   public int initialize(Properties props) 
      throws WebTrustAssociationFailedException {
      System.out.println("ExampleTAI.initialize()");
      
      // read properties from configuration in WAS
      this.cookie = props.getProperty("cookieName");
      
      // return 0 to indicate success
      return 0;
   }

   @Override
   public boolean isTargetInterceptor(
      HttpServletRequest req) 
      throws WebTrustAssociationException {
      System.out.println("ExampleTAI.isTargetInterceptor()");
      for (Cookie c : req.getCookies()) {
         if (c.getName().equals(this.cookie)) return true;
      }
      return false;
   }

   @Override
   public TAIResult negotiateValidateandEstablishTrust(
      HttpServletRequest req, 
      HttpServletResponse res) 
      throws WebTrustAssociationFailedException {
      System.out.println("ExampleTAI.negotiate...()");
      for (Cookie c : req.getCookies()) {
         if (c.getName().equals(this.cookie)) {
            // send 200 to signal we're okay
            return TAIResult.create(HttpServletResponse.SC_OK, 
                c.getValue());
         }
      }
      
      // not authenticated
      return TAIResult.create(HttpServletResponse.SC_UNAUTHORIZED);
   }

}
&lt;/pre&gt;
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/categories/web/">Web</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/tai/">tai</category>
      <category domain="http://lekkimworld.com/tags/was/">was</category>
      <category domain="http://lekkimworld.com/tags/websphere/">websphere</category>
      <pubDate>Fri, 10 Jun 2011 12:06:58 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2011-06-10:default/1307707618593</guid>
      <dc:date>2011-06-10T12:06:58Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: New version of the demo application</title>
      <link>http://lekkimworld.com/2010/08/24/how_to_extend_notes_8_new_version_of_the_demo_application.html</link>
      <content:encoded>&lt;p&gt;
I just posted an update to the demo application for my &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;Extending Notes 8&lt;/a&gt; series of posts. The demo application is discussed in more detail in my previous post (&lt;a href="http://lekkimworld.com/2010/08/06/how_to_extend_notes_8_livetext_demo_application.html"&gt;How to extend Notes 8: LiveText demo application&lt;/a&gt;). The issue was that I had a button to create a demo e-mail in the UI which made the plugin depend on the Notes Java UI API which was added in Notes 8.5.1 and hence meant that the demo application wasn't installable on previous Notes versions... :-(
&lt;/p&gt;
&lt;p&gt;
To remedy that I built an new version where the button using the offending API is added from an Eclipse plugin fragment and using a custom extension point (if you're running Notes 8.5.1+). More on that approach at a later date. For now you may install the new version using the updated &lt;a href="http://lekkimworld.com/files/extending_notes8/dynlivetextdemoapplication/extension_1.0.1.xml"&gt;widget descriptor (extension.xml)&lt;/a&gt; (simply drag the link to your MyWidgets sidebar plugin).
&lt;/p&gt;
&lt;p&gt;
If you do an update - which there's absolutely no reason to if it already works for you - the only way to tell is by verifying that the version number at the bottom of the sidebar application is changed to 1.0.1.
&lt;/p&gt;
&lt;p&gt;
That's all for this post. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag.
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Tue, 24 Aug 2010 17:51:38 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-24:default/1282672298902</guid>
      <dc:date>2010-08-24T17:51:38Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: LiveText demo application</title>
      <link>http://lekkimworld.com/2010/08/06/how_to_extend_notes_8_livetext_demo_application.html</link>
      <content:encoded>&lt;p&gt;
The day before yesterday I posted the first summary post in my &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;Extending Notes 8&lt;/a&gt; series with a complete end-to-end approach to &lt;a href="http://lekkimworld.com/2010/08/04/how_to_extend_notes_8_dynamic_livetext_recognizers_using_java.html"&gt;dynamically adding LiveTex recognizers&lt;/a&gt;. As part of that post I uploaded a &lt;a href=".files/extending_notes8/dynamiclivetextrecognizersusingjava/com.lekkimworld.extnotes8.dynext.zip"&gt;demo application (plugin)&lt;/a&gt; but I didn't add a screenshot so I thought I'd remedy that. 
&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/dynlivetextdemoapplication/emoapp.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
As you can see the plugin has a small welcome text and two buttons. You'll also see a textbox to hold any exception (not that I'm expecting any) that might be raised as part of adding the recognizer and content type. You may use the two buttons to easily create a demo e-mail for use with the added LiveText stuff. The left button creates the e-mail in the UI (using the new handy Java UI classes) and the right one simply sends the e-mail to you in the backend. The latter is very handy for testing as the e-mail needs to be in read mode for the LiveText sub-system to kick in.
&lt;/p&gt;
&lt;p&gt;
I've put a compiled version of the plugin on my update site and tthe plugin may be installed by dragging this &lt;a href="http://lekkimworld.com/files/extending_notes8/dynlivetextdemoapplication/extension.xml"&gt;extension.xml&lt;/a&gt; file to your MyWidgets sidebar panel (policy permitting). 
&lt;/p&gt;
&lt;p&gt;
That's all for this post. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag.
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Fri, 06 Aug 2010 10:54:23 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-06:default/1281092063777</guid>
      <dc:date>2010-08-06T10:54:23Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: case insensitive LiveText patterns</title>
      <link>http://lekkimworld.com/2010/08/05/how_to_extend_notes_8_case_insensitive_livetext_patterns.html</link>
      <content:encoded>&lt;p&gt;
When you start to do a lot of LiveText recognizers you find yourself wanting to do more advanced stuff with your regular expressions. For instance you might want to do case insensitive patterns or use some of the others regular expression modifiers. This post will show you how to do this.
&lt;/p&gt;
&lt;p&gt;
By default the regular expressions you specify for your recognizers are case sensitive. This is normally fine unless you really want it to be case insensitive. Since the LiveText engine is in Java you may use the supported Java modifiers for your regular expressions. Normally the modifiers are specified when you "compile the pattern" in Java (java.util.regex.Pattern.compile(pattern, modifiers)) but as you don't have access to this process you can't do that. 
&lt;/p&gt;
&lt;p&gt;
There is however another way...
&lt;/p&gt;
&lt;p&gt;
You can embed some modifiers in the pattern such as Pattern.MULTILINE, Pattern.UNICODE_CASE, Pattern.DOTALL and most of all Pattern.CASE_INSENSITIVE! You embed the modifier in the start of the pattern. So instead of doing a case insensitive pattern like this (to recognizer "lotus" and "Lotus"):
&lt;pre&gt;
[Ll]otus
&lt;/pre&gt;
you do
&lt;pre&gt;
(?i)lotus
&lt;/pre&gt;
Cool isn't it?
&lt;/p&gt;
&lt;p&gt;
The following modifiers are supported in Java though not all makes sense for LiveText:
&lt;ul&gt;
&lt;li&gt;Pattern.CASE_INSENSITIVE = (?i)&lt;/li&gt;
&lt;li&gt;Pattern.MULTILINE = (?m)&lt;/li&gt;
&lt;li&gt;Pattern.DOTALL = (?s)&lt;/li&gt;
&lt;li&gt;Pattern.UNICODE_CASE = (?u)&lt;/li&gt;
&lt;/ul&gt;
Please bear in mind that it probably only makes sense to use DOTALL and CASE_INSENSITIVE.
&lt;/p&gt;
&lt;p&gt;
That's all for this post. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag.
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Thu, 05 Aug 2010 12:11:33 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-05:default/1281010293886</guid>
      <dc:date>2010-08-05T12:11:33Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: dynamic LiveText recognizers using Java</title>
      <link>http://lekkimworld.com/2010/08/04/how_to_extend_notes_8_dynamic_livetext_recognizers_using_java.html</link>
      <content:encoded>&lt;p&gt;
As I briefly described in my last post ("&lt;a href="http://lekkimworld.com/2010/08/03/how_to_extend_notes_8_dynamic_extensions_using_java.html"&gt;How to extend Notes 8: dynamic extensions using Java&lt;/a&gt;") 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. 
&lt;/p&gt;
&lt;p&gt;
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.
&lt;/p&gt;
&lt;p&gt;
All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag.
&lt;/p&gt;
&lt;p&gt;
We need three pieces of information:
&lt;ol&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;The Java action to act on the LiveText selection.&lt;/li&gt;
&lt;li&gt;The plugin.xml file to bind it all together.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
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.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
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();
  }
}
&lt;/pre&gt;
The above code injects the recognizer and content type with an id of DCCT.ExampleContentType.1234567890 into the client. 
&lt;/p&gt;
&lt;p&gt;
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.
&lt;pre&gt;
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");
}
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
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.
&lt;pre&gt;
&amp;lt;extension
  point="org.eclipse.ui.popupMenus"&amp;gt;
  &amp;lt;objectContribution
    id="com.lekkimworld.extnotes8.dynext.objCtr1"
    objectClass="com.ibm.rcp.content.IDocumentContent"&amp;gt;
    &amp;lt;visibility&amp;gt;
      &amp;lt;and&amp;gt;
        &amp;lt;objectState
          name="content.type"
          &lt;b&gt;value="DCCT.ExampleContentType.1234567890"&lt;/b&gt;&amp;gt;
        &amp;lt;/objectState&amp;gt;
        &amp;lt;objectState
          name="contents"
          value="*"&amp;gt;
        &amp;lt;/objectState&amp;gt;
      &amp;lt;/and&amp;gt;
    &amp;lt;/visibility&amp;gt;
    &amp;lt;action
      class="com.lekkimworld.extnotes8.dynext.MyAction"
      enablesFor="*"
      id="com.lekkimworld.extnotes8.dynext.action1"
      label="Do me!"&amp;gt;
    &amp;lt;/action&amp;gt;
  &amp;lt;/objectContribution&amp;gt;
&amp;lt;/extension&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
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.
&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/dynamiclivetextrecognizersusingjava/a.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
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 &lt;a href="http://lekkimworld.com/files/extending_notes8/dynamiclivetextrecognizersusingjava/com.lekkimworld.extnotes8.dynext.zip"&gt;here&lt;/a&gt;.
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Wed, 04 Aug 2010 11:10:51 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-04:default/1280920251589</guid>
      <dc:date>2010-08-04T11:10:51Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: dynamic extensions using Java</title>
      <link>http://lekkimworld.com/2010/08/03/how_to_extend_notes_8_dynamic_extensions_using_java.html</link>
      <content:encoded>&lt;p&gt;
I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag. In all of the examples I assume a working knowledge of Eclipse and Java programming and how to work with extension points.
&lt;/p&gt;
&lt;p&gt;
As I briefly mentioned in my last post ("&lt;a href=""&gt;How to extend Notes 8: capture group LiveText recognizers with a Java action&lt;/a&gt;") 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. I've used this a lot previously and also demoed it in my "&lt;a href="http://lekkimworld.com/2009/02/27/how_dynamic_are_your_notes_sidebar_plugins.html"&gt;How dynamic are your Notes sidebar plugins?&lt;/a&gt;" demo. Watch the Flash video and see how you can make sidebar panels come and go on demand.
&lt;/p&gt;
&lt;p&gt;
Now on to the code...
&lt;/p&gt;
&lt;p&gt;
The trick to dynamic extensions is to inject extensions into the Extension Registry at runtime. The Extension Registry is where Eclipse reads the plugin contributions from plugin.xml files into at startup. If we inject an extension, and the receiving plugins are set up to handle dynamically adding extensions you are golden. Let me show you have to use the Extension Registry.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
final String extensionXml = ...;
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);
&lt;/pre&gt;
The code does the following:
&lt;ol&gt;
&lt;li&gt;Defines the extension XML to add (more on this later).&lt;/li&gt;
&lt;li&gt;Gets the extension registry from the platform.&lt;/li&gt;
&lt;li&gt;Reads the extension XML into an input stream.&lt;/li&gt;
&lt;li&gt;Retrieves the bundle.&lt;/li&gt;
&lt;li&gt;Creates a new contributor that is the object that makes the contribution to the extension registry.&lt;/li&gt;
&lt;li&gt;Adds the contribution to the registry.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
So what is the extension XML mentioned above?
&lt;/p&gt;
&lt;p&gt;
The extension XML is the XML that defines the extension you're adding. It's actually any piece of XML you would stick in your plugin.xml file either manually or using the UI editor. An example could be a custom recognizer and content type as shown below as a snippet from Java.
&lt;pre&gt;
final String extensionXml = "&amp;lt;?xml version=\"1.0\" encoding=\"utf-8\" ?&amp;gt;" +
"&amp;lt;?eclipse version=\"3.2\"?&amp;gt;" +
"&amp;lt;plugin&amp;gt;" + 
"&amp;lt;extension id=\"DCR.ExampleRecognizer.%s\" 
   point=\"com.ibm.rcp.annotation.regex.regexTypes\"&amp;gt;" + 
"&amp;lt;regexTypes contentTypeId=\"DCCT.ExampleContentType.%s\" 
   id=\"DCR.ExampleRecognizer.%s\" match=\"([A-Z]{4})-(\\d{4})\" 
   name=\"Example Recognizer\"&amp;gt;" + 
"&amp;lt;group contentTypePropertyId=\"pn\" number=\"2\"/&amp;gt;" + 
"&amp;lt;group contentTypePropertyId=\"pf\" number=\"1\"/&amp;gt;" + 
"&amp;lt;group contentTypePropertyId=\"contents\" number=\"0\"/&amp;gt;" + 
"&amp;lt;/regexTypes&amp;gt;" + 
"&amp;lt;/extension&amp;gt;" +  
"&amp;lt;extension id=\"DCCT.ExampleContentType.%s\" 
   point=\"com.ibm.rcp.content.contentTypes\"&amp;gt;" + 
"&amp;lt;contentSet&amp;gt;" + 
"&amp;lt;type category=\"Recognized Content\" 
   id=\"DCCT.ExampleContentType.%s\" 
   name=\"Example Content Type\"&amp;gt;" + 
"&amp;lt;property description=\"Entire Contents\" id=\"contents\"/&amp;gt;" + 
"&amp;lt;property description=\"Product Family\" id=\"pf\"/&amp;gt;" + 
"&amp;lt;property description=\"Part Number\" id=\"pn\"/&amp;gt;" + 
"&amp;lt;/type&amp;gt;" + 
"&amp;lt;/contentSet&amp;gt;" + 
"&amp;lt;/extension&amp;gt;" + 
"&amp;lt;/plugin&amp;gt;";
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
That's how you do it. Tomorrow I'll show how to combine it with our custom recognizer and content type to inject it dynamically into the LiveText system in Lotus Notes. Stay tuned...
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/extension/">extension</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Tue, 03 Aug 2010 11:11:23 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-03:default/1280833883886</guid>
      <dc:date>2010-08-03T11:11:23Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: capture group LiveText recognizers with a Java action</title>
      <link>http://lekkimworld.com/2010/08/02/how_to_extend_notes_8_capture_group_livetext_recognizers_with_a_java_action.html</link>
      <content:encoded>&lt;p&gt;
I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag. In all of the examples I assume a working knowledge of Eclipse and Java programming and how to work with extension points.
&lt;/p&gt;
&lt;p&gt;
For this post I'll build on the "&lt;a href="http://lekkimworld.com/2010/07/27/how_to_extend_notes_8_coupling_livetext_to_a_java_action.html"&gt;How to extend Notes 8: coupling LiveText to a Java action&lt;/a&gt;" and "&lt;a href="http://lekkimworld.com/2010/07/30/how_to_extend_notes_8_using_livetext_with_capture_groups.html"&gt;How to extend Notes 8: using LiveText with capture groups&lt;/a&gt;" posts and show how to act on your own custom recognizer from a Java action when you have multiple capture groups. 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Please note:&lt;/b&gt; I'll assume that you read the "&lt;a href="http://lekkimworld.com/2010/07/30/how_to_extend_notes_8_using_livetext_with_capture_groups.html"&gt;How to extend Notes 8: using LiveText with capture groups&lt;/a&gt;" post and have it working as we'll build on that example in this post. Unfortunately as we act on the content type id you need to find the id of the content type on your system. I'll show you how.
&lt;/p&gt;
&lt;p&gt;
Enough with preparations - now on to the code!
&lt;/p&gt;
&lt;p&gt;
So far we have our custom recognizer and our custom content type but instead of a web widget we really want to use our Java action as the recipient of the LiveText selection. We couple the Java action to the content type using an extension point in plugin.xml based on the content type id. Let me show you how to find the content type id.
&lt;/p&gt;
&lt;p&gt;
&lt;ol&gt;
&lt;li&gt;Start by opening the management UI for widgets, content types and recognizers. You do this by choosing "Manage Widgets, Content and Recognizers" from the part menu in the My Widgets sidebar panel as show below.&lt;br/&gt;&lt;img src="http://lekkimworld.com/files/extending_notes8/capturegrouplivetextrecognizerswithjavaaction/1.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Now switch to the "Content Types" panel and make a note of the ID for the "Demo Product Number" content type. Here the id is "DemoProductNumber.1410710777" as highlighted below.&lt;br/&gt;&lt;img src="http://lekkimworld.com/files/extending_notes8/capturegrouplivetextrecognizerswithjavaaction/2.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Now comes the trick. Notes adds "DCCT." in front of the id shown so the &lt;b&gt;real id&lt;/b&gt; is "DCCT.DemoProductNumber.1410710777". Make a note of your own id and read on...&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
As previously the first piece of the puzzle is the extension point. Add an org.eclipse.ui.popupMenus extension as previous and specify the id you noted above as the content type id. Mine is shown below - notice how I use the id prefixed with "DCCT.".
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;?eclipse version="3.4"?&amp;gt;
&amp;lt;plugin&amp;gt;
   &amp;lt;extension  point="org.eclipse.ui.popupMenus"&amp;gt;
      &amp;lt;objectContribution id="com.lekkimworld.livetxt.objectContr1" 
         objectClass="com.ibm.rcp.content.IDocumentContent"&amp;gt;
         &amp;lt;visibility&amp;gt;
            &amp;lt;and&amp;gt;
               &amp;lt;objectState name="content.type" 
               &lt;b&gt;value="DCCT.DemoProductNumber.1410710777"&lt;/b&gt;/&amp;gt;
               &amp;lt;objectState name="contents" value="" /&amp;gt;
            &amp;lt;/and&amp;gt;
         &amp;lt;/visibility&amp;gt;
         &amp;lt;action class="com.lekkimworld.livetext.MyAction"
            enablesFor="*" 
            id="com.lekkimworld.livetxt.action1" 
            label="Do stuff!" /&amp;gt;
      &amp;lt;/objectContribution&amp;gt;   
   &amp;lt;/extension&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Now create your Java action class - again implemening org.eclipse.ui.IObjectActionDelegate - and specify the correct class name in the extension point. 
&lt;/p&gt;
&lt;p&gt;
Again when it comes to grabbing the contents of the recognized LiveText it comes down to you selectionChanged-method of your Java action. As our recognizer uses capture groups we have a few choices for the properties we can grasp from the document. As always the entire recognized product number will be in the "contents" property but we also have "pf" and a "pn" property available that holds the product family and the part number. The example code below shows how to get at these.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
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.selection = null;
      return;
   }
   
   // get all recognized content
   this.prodNumber = doc.getProperties().getProperty("contents");
   this.prodFamily = doc.getProperties().getProperty("pf");
   this.partNumber = doc.getProperties().getProperty("pn");
}
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Now when you install the extension and hence put the pieces together you should see two actions for the product number LiveText recognition as shown below. The top one is our Java action and the bottom one is our web widget from previously.
&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/capturegrouplivetextrecognizerswithjavaaction/3.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
That's what is required to act on custom recognizers. As you can probably gather from the above it doesn't work letting users do their own recognizers and then wanting to act on them from Java due to two reasons - 1) never trust a user to give it the right name as instructed :-) and 2) the id of the content type will change from machine as it is generated when the user creates the content type. It is possible however if you create the content type and the recognizer for users and install then using an extension.xml file as the extension.xml sets the id's. That's probably also the way you'd want it.
&lt;/p&gt;
&lt;p&gt;
There is however an even better solution... Dynamically add the content type and recognizer to the client from Java for a single, combined solution. Stay tuned...
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Mon, 02 Aug 2010 12:48:39 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-08-02:default/1280753319167</guid>
      <dc:date>2010-08-02T12:48:39Z</dc:date>
    </item>
    <item>
      <title>How to extend Notes 8: using LiveText with capture groups</title>
      <link>http://lekkimworld.com/2010/07/30/how_to_extend_notes_8_using_livetext_with_capture_groups.html</link>
      <content:encoded>&lt;p&gt;
I get so many question on how to extend Notes 8 that I finally decided to create a series of blog posts on how to do it. All the posts in the series may be found under the &lt;a href="http://lekkimworld.com/tags/extending_notes8/"&gt;extending_notes8&lt;/a&gt; tag. In this post you'll need familiarity with how MyWidgets and LiveText works. A basic understanding of &lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;regular expressions&lt;/a&gt; would be beneficial as well.
&lt;/p&gt;
&lt;p&gt;
This post will set the stage for the next post on how to add Java actions that use LiveText recognizers that contain capture groups. No Java code or Eclipse extension point stuff in this post.
&lt;/p&gt;
&lt;p&gt;
Let me start by explaining what capture groups are. As you probably know you use &lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;regular expressions&lt;/a&gt; to search for text occurrences when using LiveText. In short a regular expression is a text pattern to search for in a block of text. Regular expressions can be hard to grasp at first but once you "have it" they will become an invaluable tool in your arsenal.
&lt;/p&gt;
&lt;p&gt;
A regular expression can range from the simple to the extremely complex. A simple regular expression to find  a product number like OTGC-5431 could look like this one:
&lt;pre&gt;[A-Z]{4}-\d{4}&lt;/pre&gt;
This regular expression tells the regular expression engine to search for 4 consecutive, uppercase, letters ([A-Z]{4}) followed by a hyphen (-) followed by 4 digits (\d{4}).
&lt;/p&gt;
&lt;p&gt;
Now that's great but what if this isn't just a product number but it's actually a compound data format and that the product number is made up of a product family (OTGC) and a part number (5431) and I needed the two pieces of information separately? Well that's where capture groups become important.
&lt;/p&gt;
&lt;p&gt;
In regular expressions there is a syntax to signal that the text that you find actually consists of multiple, separate, discrete, pieces of information. As in the example with a product number such as OTGC-5431. This product number consists of two parts - 1) the product family (OTGC) and 2) the part number (5431). If you need access to the product family and part number separately you can use capture groups to split up the product number in the regular expression itself instead of relying on parsing after recognition.
&lt;/p&gt;
&lt;p&gt;
So instead of simply getting a match of "OTGC-5431" you also get information that the product family is "OTGC" and the part number is "5431". 
&lt;/p&gt;
&lt;p&gt;
So how does one use capture groups?
&lt;/p&gt;
&lt;p&gt;
Well you start with the regular expression above and then you add capture groups by simply changing it to be 
&lt;pre&gt;
([A-Z]{4})-(\d{4})
&lt;/pre&gt;
Notice how I only added two sets of parentheses. That all. That tells the regular expression engine that the result is made of of two parts. So instead of getting just one result (OTGC-5431) I get &lt;b&gt;three&lt;/b&gt;: OTGC-5431, OTGC, 5431 (the match in it's entirety and the two capture groups). 
&lt;/p&gt;
&lt;p&gt;
So how do I use these results in MyWidgets / LiveText? Well let me walk you through an example.
&lt;/p&gt;
&lt;p&gt;
Lets imagine that you have a web service that allows you to search for product numbers but need the product family and part number separately. The syntax is something like http://www.example.com/prodquery?pf=&amp;lt;product family&amp;gt;&amp;pn=&amp;lt;part number&amp;gt; (http://www.example.com/prodquery?pf=OTGC&amp;pn=5431). Let me show you, end to end, how to do this using MyWidgets and LiveText.
&lt;/p&gt;
&lt;p&gt;
&lt;ol&gt;
&lt;li&gt;Start by creating a new widget. Choose to create a web widget and click Next.&lt;br /&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/a.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Now specify the URL as being "http://www.example.com/prodquery?pf=OTGC&amp;pn=5431" (&lt;b&gt;Please note:&lt;/b&gt; The address doesn't point to anything but it proves the point we need). Now click Next.&lt;br /&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/b.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;A GET request is fine - just click Next.&lt;br /&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/c.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Now the web page is fetched. As we know the URL we specified doesn't work just click Next. &lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/d.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;In the "Configure a Widget" dialog name the widget "Demo Product Search" and choose "Wire as an action" at the bottom. Then click the "Advanced" tab at the top.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/e.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Put a checkmark in both boxes in the "Configure" column as we need to map both URL parameters to our recognized LiveText. Then click Next.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/f.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;We need a new recognizer to recognize our product number. To do this click the "New Recognizer..." button.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/g.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Name the recognizer "Demo Product Number" in the top text box. Now since our recognizer uses two capture groups we need to tell Notes how to map these to our widget (as widget properties) so we need a new Content Type. To do this click the "New Type..." button.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/h.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;In the "Configure a Content Type" dialog box you name the parts of the text you recognize. We have two parts so we click the "Add"-button &lt;b&gt;twice&lt;/b&gt; and fill the text fields like specified below. We do this to indicate we have two properties called "pf" and "pn". Then click OK.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/i.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Back in the "Configure a Recognizer" dialog our new Content Type ("Demo Product Number") has been chosen for us. Now we specify our regular expression with the two capture groups. Then we click the "Add"-button &lt;b&gt;twice&lt;/b&gt; and map capture group 1 (the "product family") to content property "pf" and capture group 2 (the "part number") to content property "pn" as shown below. Then click OK.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/j.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;Back in the "Wire an action to configure a widget" dialog our newly created recognizer has been chosen for us. Now we need to map the widget properties (the parts of the recognizer) to the URL parameters. We do this on the "Advanced" tab so click on that near the top.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/k.jpg" /&gt;&lt;/li&gt;
&lt;li&gt;On the "Advanced" tab add a second parameter box by clicking the "Add"-button and map the URL parameters to our widget properties as shown below. Then click Finish.&lt;br/&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/l.jpg" /&gt;&lt;/li&gt;
&lt;/ol&gt;
Now take a deeeeeeeeeeeeeeeeep breath... :-)
&lt;/p&gt;
&lt;p&gt;
That's what's required to create a new widget with a new recognizer and new content type. It may seem like much, and I think it is, but remember that you may now add a second web widget that uses the same recognizer by following the same steps but ignoring step 7-10. Also when you've done it a few times it becomes second nature and you use it all the time. I do.
&lt;/p&gt;
&lt;p&gt;
Now we need some text to test on. Create a new e-mail message, add a subject, some text to the body field including a couple of product numbers and e-mail the message to yourself. To make it easier you may copy/paste the below text:
&lt;pre&gt;
Ullamcorper veniam aliquip duis, vel vero dolore in dolor 
aliquam dolore lobortis delenit vel duis, magna. Eros 
iusto, consequat iriure eu enim nulla exerci minim nulla 
facilisis, ex te ut nulla volutpat qui: OTGC-5431, 
OTMM-6615. Odio nulla amet ea quis volutpat suscipit exerci 
eros et dolore feugiat, ea dolor ad, vulputate, delenit 
enim sed autem tation enim zzril blandit iusto. Dolor 
facilisi vero feugait iriure, et consequat ut, et euismod 
ipsum praesent quis duis zzril in hendrerit, at et, dolor 
hendrerit dignissim. Ut commodo odio consequat, onsectetuer 
augue dignissim nulla dolore velit. 
&lt;/pre&gt;
Now when you open the message from your inbox you should see something like this:
&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/y.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
As you can see the Notes client recognized two text strings as shown by the blue dotted lines. If you hover over the text and click the down arrow (will appear to the right of the text) you'll see a small menu as shown below. From that menu select "Display Demo Product Number Properties". That will show a dialog box explaining exactly what Notes found and what text goes into which capture groups and hence into which widget properties.
&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://lekkimworld.com/files/extending_notes8/usinglivetextwithcapturegroups/z.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
In the next post in the series I'll show how to use these widget properties from a Java action. Stay tuned...
&lt;/p&gt;</content:encoded>
      <category domain="http://lekkimworld.com/categories/java/">Java</category>
      <category domain="http://lekkimworld.com/categories/ibm_products/">IBM</category>
      <category domain="http://lekkimworld.com/tags/eclipse/">eclipse</category>
      <category domain="http://lekkimworld.com/tags/extending_notes8/">extending_notes8</category>
      <category domain="http://lekkimworld.com/tags/java/">java</category>
      <category domain="http://lekkimworld.com/tags/livetext/">livetext</category>
      <category domain="http://lekkimworld.com/tags/mywidgets/">mywidgets</category>
      <category domain="http://lekkimworld.com/tags/notes8/">notes8</category>
      <category domain="http://lekkimworld.com/tags/notes85/">notes85</category>
      <pubDate>Fri, 30 Jul 2010 12:42:29 GMT</pubDate>
      <guid isPermaLink="false">tag:lekkimworld.com,2010-07-30:default/1280493749292</guid>
      <dc:date>2010-07-30T12:42:29Z</dc:date>
    </item>
  </channel>
</rss>

