深入讲解 Lotus Notes 插件编程

 

作者:李 伟, 软件工程师, IBM

原文链接:http://www.ibm.com/developerworks/cn/lotus/notes-plugindev/index.html?ca=drs-cn-0831#main

简介

众所周知,Lotus Notes V8 以后的各个版本都是基于强大的托管客户机软件平台 Lotus Expeditor 开发而成的,而 Lotus Expeditor 扩展了 Eclipse,是基于插件的架构,这也使得 Lotus Notes 具有良好的可扩展性。Lotus Notes 发展到今天已经成为一个非常强大的集成了 Web 2.0 功能特性的协作办公软件。

本文通过几个 Lotus Notes 插件的开发介绍,深入浅出的讲解如何基于 Lotus Notes 平台,开发最常用的 Notes 插件。从而增强 Lotus Notes 的协作能力,满足用户在工作中的实际需要。



Sender Analystics 插件开发

项目简介

该插件通过 Email 地址来分析发信人的信息。当用户收到一个陌生人的来信,准备进一步了解该发信人的信息时,这个插件特别有用。

扩展实现

如清单 1 所示,Sender Analystics 插件扩展了 Eclipse 平台的 org.eclipse.ui.popupMenus 扩展点。请注意 objectClass 的值是 com.ibm.rcp.realtime.livenames.LiveNameSelection,当您在 Lotus Notes 中选择一封 Email 或者一个对象中包含了 Sametime 的 Live Name 信息,其视图弹出菜单中将显示该扩展的菜单项。


清单 1. Plugin.xml
				 
<?xml version="1.0" encoding="UTF-8"?> 
<?eclipse version="3.2"?> 

当 ObjectClass 是 LiveNameSelection 对象的时候,在 Action 的 run 方法里面,我们能够拿到 com.ibm.rcp.realtime.livenames.LiveName 对象信息。在 Sametime Javadoc 文档中,我们知道 LiveName 有以下一些方法,可以获取发信人的相关信息。如表 1 所示,详情请下载 Lotus Sametime SDK 并参考有关文档。

java.lang.String getCommunityId()
Returns the ID of the community that this person belongs to.
java.lang.String getContactId()
Returns the person's contact ID.
java.lang.String getDisplayName()
Returns the person's display name.
java.lang.String getId()
Returns the person's unique ID.
java.lang.String getName()
Returns the persons username.
int getStatus()
Returns the person's status, one of the STATUS_xxx codes defined in this interface.
org.eclipse.swt.graphics.Image getStatusImage()
Returns the image displayed for the person's status.
java.lang.String getStatusMessage()
Returns the person's status message.

在 Sender Analystic 插件开发中,我们通过 LiveName 对象拿到了发信人的 Email 地址信息。如清单 2 所示:


清单 2. Action 的 run 方法
				 
public void run(IAction action) {
    ObjectPluginAction bjAction = (ObjectPluginAction) action;
    if (objAction == null)return;
    if (objAction.getSelection() instanceof IStructuredSelection) {
        if (((IStructuredSelection) objAction.getSelection()) 
            .getFirstElement() instanceof LiveNameSelection) {
            LiveNameSelection sel = (LiveNameSelection) ((IStructuredSelection) objAction
                .getSelection()).getFirstElement();
            LiveName name = sel.getLiveName();
            String contactId = name.getContactId(); 
            String url = SenderAnalyzerHelper.createURL(contactId);
            SenderAnalyzerHelper.launchURLasEmbed(url);
        }
    }
}

接下来,程序调用 SenderAnalyzerHelper 辅助类的 launchURLasEmbed 方法,并根据生成的 URL(本插件应用发信人的 Email 信息构造一个 myfreeemailsearch 网站的 URL 请求)启动 Lotus Notes 嵌入的浏览器打开 Email 查询页面。如清单 3 所示,关于该方法的实现逻辑,请参考 Lotus Expeditor 有关文档。


清单 3. launchURLasEmbed 方法
				 
public static boolean launchURLasEmbed(String url){ 	
    final String secondaryId = BROWSER_VIEW_ID + Integer.toString(++counter); 
    Map configMap = new HashMap(); 
    configMap.put(BrowserPreference.ID, secondaryId); 
    configMap.put(BrowserPreference.ENABLE_APPLET, "true"); 
    BrowserLauncher bLauncher = BrowserLauncher.getLauncher(); 	
    return bLauncher.launchURLasEmbedded(url,null, configMap); 
} 

因为 Sender Analystics 需要启动 Lotus 内部的浏览器,所以我们需要在 plugin.xml 加入如下的依赖插件。如图 1 所示:


图 1. 在 plugin.xml 中加入依赖插件
图 1. 在 plugin.xml 中加入依赖插件

图 2 显示了 Sender Analystics 插件的运行效果。


图 2. Sender Analystics 插件的运行效果
图 2. Sender Analystics 插件的运行效果

通过本插件的相关介绍,读者可以开发基于 Sametime 的 Notes 插件。

Driving Direction 插件开发

项目简介

本插件的主要目地是管理用户的旅行路线,启用 Google Maps 来显示旅行路线信息。

扩展实现

如图 3 所示,Driving Direction 插件扩展了如下的扩展点。读者可能对 org.eclipse.ui.views 并不陌生,插件扩展了 Lotus Expeditor 所提供的 com.ibm.rcp.ui.shelfViews 扩展点。该扩展点使得 view 能够和 Lotus Notes 的 Sametime 插件,Activity 插件一样显示在 shelfViews 区域,如图 4 所示。


图 3. Extension
图 3. Extension

图 4. shelfView
图 4. shelfView

对该扩展点的描述如下:(更多的信息,请参考 Lotus® Expeditor 信息中心的文档)。

id id 属性唯一标识该 shelf 视图,也就是说,如果该 id 被使用了多次,只会有一个视图被成功地注册。
view View 属性的值和所贡献视图的 id 是一致的(本插件中是 traffic view 的 id)
region region 属性是一种可选的方式用以描述视图显示在 sidebar 中的那个区域。其有三种可能的值 “TOP” ,“MIDDLE” 和“BOTTOM”。如果许多视图的该选项值相同的话,视图显示的顺序和其被加载的顺序是一致的。缺省值是“BOTTOM”
page page 属性描述该视图属于那个 sidebar, 对于 Lotus® Expeditor 而言,该值是"RIGHT"
showTitle showTitle 属性是 bool 类型,其值决定是否显示标题栏

在图 4 所示的 Driving Direction 插件中,点击 Open 按钮会打开 Lotus Notes 的 preference 页面(如图 5 所示),这个功能会被经常用到,请见清单 4。preference 页面主要是用来管理插件的一些配置选项信息。在本例中,用其管理旅行路线信息。


清单 4. 打开 Notes 的 preference 页面
				 
openBt.addSelectionListener(new SelectionAdapter() { 	        
    public void widgetSelected(SelectionEvent e) { 
        PreferenceDialog dlg = PreferencesUtil 
            .createPreferenceDialogOn( 
                TrafficView.this.getSite().getWorkbenchWindow().getShell(), 
                    "com.ibm.lotus.openntf.traffic.ui.trafficanalyzer", //$NON-NLS-1$ 
                    null, null); 
                int success = dlg.open(); 
                if(success == 0) refreshRoutes(); 
            } 
    }); 

清单 4 中,com.ibm.lotus.openntf.traffic.ui.trafficanalyzer 是您定义的 preference page 的 id 属性值。


图 5. Traffic Routes Preferences
图 5. Traffic Routes Preferences

通过本插件的介绍,读者就可以轻松的开发一个可以放在 shelfView 里面显示的 Eclipse 视图插件。


Date Recognizer 插件开发

项目简介

Date Recognizer 插件用来识别 Notes 文档里面的日期,并根据识别出来的日期触发动作显示当前的 Calendar 信息。

扩展实现

和本文第一个插件类似,Date Recognizer 扩展了 org.eclipse.ui.popupMenus 扩展点,不同的是,ObjectClass 的属性值是 org.eclipse.jface.text.ITextSelection (当我们在 Notes 文档中,选中一段文字才能激活插件的 action)如清单 5 所示。


清单 5. Plugin.xml
				 

Date Recognizer 插件中如何识别日期是一个非常重要的算法问题。通常我们都用正则表达式。但时间格式的复杂性,使得难以有一个完整的正则表达式处理所有可能的情况。在清单 6 中给出了本插件的算法,它结合正则表达式能够识别出 Notes 中常用的诸如:MM/DD/YYYY,March/Mar. Day, Year, 和 Year ? Month? Day 等日期格式。(其中‘?’是某一给定特殊的分隔符,比如 . / _- 等)如果字符串中没有合法的日期,本例中,将创建一个 Date 对象作为缺省值。


清单 6. 解析算法
				 
private boolean parse() { 
    // if destStr is empty, return false; 
    if (checkNull(destStr)) return false; 
    // append a space to destStr, it deals with situation like MM/DD/YYYY format, 
    // which lies at the end of destStr 
    StringBuffer sb = new StringBuffer(); 
    sb.append(destStr+" "); 	
    destStr = sb.toString(); 
    Pattern p = Pattern.compile(YEAR); 
    Matcher m = p.matcher(destStr); 
    // We just care about the first legal date and neglect other dates. 
    while (m.find()) { 
        // probably, year of Calendar exists 
        String lYear = m.group(); // for example 2008- 
        // two directions to analyze the string 
        int index = m.start(); 
        // Algorithm-forward: Obtain Month & Day information before the located year. 
        String previousP1 = destStr.substring(0, index + 4); // neglect yy format 
        // Match such format as January 01, 2009 
        Pattern pp1 = Pattern.compile(MonthDayYear); 
        previousP1 = previousP1.replaceAll("\\s", ""); // remove spaces 
        Matcher mp1 = pp1.matcher(previousP1); 
        if (mp1.find()) { 
            String destP1 = mp1.group(); 
            getDayAndMonth(destP1); 
            if (month != null && day != null) { 
                // remove the duplicated character 
                year = lYear.substring(0,lYear.length()-1); 
                createPrev1Date(); 
                return true; 
            } 
        } 
        //Match such format as MM/DD/YYYY 
        Pattern pp2 = Pattern.compile(MMDDYEAR); 
        Matcher mp2 = pp2.matcher(previousP1); 
        if (mp2.find()) { 
            createPrev2Date(mp2.group()); 
            return true; 
        } 
        // Algorithm: Obtain Month & Day information after the located year 
        // if Month & Day information is not in the same line as Year info, ignore it. 
        String afterText = destStr.substring(index + 4); 
        String[] dateText = afterText.split("\n|\t"); 
        String wantedText = afterText; 
        for (int i = 0; i < dateText.length; i++) { 
            if (!dateText[i].equals("")) { 
                wantedText = dateText[i]; 
                break; 
            } 
        } 
        afterText = wantedText.replaceAll("\\s", ""); // replace space 
        Pattern ap = Pattern.compile(MONTH); 
        Matcher map = ap.matcher(afterText); 
        int count = 0; 
        String tmpMonth = null; 
        String tmpDay = null; 
        if(checkNull(afterText)){ break; } 
        // separator of calendar must be consistent. 
        // can't support format like this 2008-09/02 
        char specialChar = afterText.charAt(0); // _ . / * - 
        while (map.find()) { 
            try { 
                if (count == 2) break; 
                if (count == 0) { 
                    tmpMonth = map.group(0); 
                } else if (count == 1) { 
                    String tmpday = map.group(0); 
                    int indexD = map.start(); 
                    if (afterText.charAt(indexD - 1) == specialChar) { 
                        tmpDay = tmpday; 
                    } 
                } 
                count++; 
            } catch (Exception e) {} 
        } 
        if (tmpMonth != null && tmpDay != null) { 
            year = lYear.substring(0,lYear.length()-1); 
            month = tmpMonth; 
            day = tmpDay; 
            createPrev1Date(); 
            return true; 
        } 
    } 
    return false; 
} 

图 6 显示了如何激活 Date Recognizer 插件。 图 7 给出了 Calendar 信息。日期被识别出来并赋值给了 Calendar 组件。


图 6. 启动插件
图 6. 启动插件

图 7. Date Recognizer
图 7. Date Recognizer

通过 Date Recognizer 插件的学习,开发者可以轻松的向 Notes 文档的右键菜单中贡献插件。

不仅如此,Eclipse 的诸多扩展点都可以在 Lotus Notes 中扩展应用。Lotus Expeditor 提供的 Launcher,Search Bar 等扩展点,请参考 Lotus Notes 8 的扩展与编程 一文。





如何安装 Lotus Notes 插件

有两种常见的方式用以安装 Notes 插件,一种就是我们常见的 update site 方式。在 Lotus Notes 中,缺省条件下 , 这个功能是不被支持的。

我们需要在 C:\Lotus\notes\framework\rcp (C:\Lotus\notes 是我的 Notes 的安装目录,开发者请注意,如果在安装目录中有空格,比如 notes 的缺省安装目录 C:\Program files\ 在 debug 环境下会导致类加载异常)目录下面的 plugin_customization.ini 文件内加入 com.ibm.notes.branding/enable.update.ui=true 一行语句,那么当您重新启动 Notes 的时候,Notes 就启动 update site 的功能了。如图 9 所示:


图 8. 启动 update site 功能
图 8. 启动 update site 功能

Notes 插件安装的另一种方式是 Lotus Notes 8.5.1 所提供的 widget 方式。最终插件会被包装成 widget 来安装。和第一种方式相比较,这种方式的好处之一就是不用去修改配置文件。然而这种安装方式最大的好处就是灵活,非常容易共享。开发者开发一个 Notes 插件并开发一个远程的更新站点(也可以自己下载一个 Apache http server, 把本地的更新站点简单的放到 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs 目录下面就成功了)然后通过 Notes widget 的向导逐步安装你的插件。如图 10 所示:


图 9. Start Configuring Widgets
图 9. Start Configuring Widgets

图 10. 从远程站点加载插件
图 10. 从远程站点加载插件

最终在 Notes 的 My Widget 里面生成类似于普通 widget 的插件。如图 11 所示:


图 11. Widget 插件
图 11. Widget 插件

开发者可以用 Email 方式分享此插件,收信人只要在 Notes 里进行简单的拖拽就能成功的安装此插件。开发者也可以点击 Remove 按钮卸载该插件。不过不管安装或卸载插件,都需要重新启动一次 Notes。





总结

本文通过对三个 Lotus Notes 插件项目的介绍,以及对其所涉及的扩展点,实现过程中的重要算法等的讲解会帮助开发者快速上手,开发 Lotus Notes 中最常见的插件。并介绍了两种常见的发布方式,如果用户安装了 Lotus Notes 8.5.1 ,Widget 方式的插件发布极具诱惑。

希望读者能够从本文中获益,快速的构建、发布您自己的基于 Lotus Notes 的插件项目。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14751907/viewspace-613811/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14751907/viewspace-613811/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值