使用IBMLotusSametimeConnectV7.5的LocatePartner插件了解您的Sametime合作伙伴身处何处。该插件使用GoogleMaps技术定位Sametime合作伙伴,并提供合作伙伴所在位置的路线。
[编者注:IBMLotusSametimeV7.5尚未面世,但预计在今年稍后推出。本文介绍的是LotusSametimeConnectV7.5的测试版。]
在developerWorksLotus文章“
在这篇文章中,我们进一步研究通过插件扩展LotusSametime客户机的主题。我们还会阐明Eclipse首选项(preference)的概念。为提高学习的趣味性,本文将为您介绍如何构建一个与
GoogleMaps是Google提供的免费服务,它提供了基于Internet浏览器、逐门逐户的路线指南,以及特定位置的地图。交互式地图可放大,显示详细的信息。Google提供的地图是展示Ajax强大力量的绝妙示例,这是一种使用户更好地与Web站点交互的Web技术,方法是利用JavaScript和XML执行异步网络请求。
在本文中,您将在LotusSametime客户机插件——LocatePartner插件中利用GoogleMaps产品。该插件使您可获得从您所在位置到Sametime合作伙伴所在位置的详细路线指南。您还可获得一份Sametime合作伙伴所在位置的地图。图1展示了LocatePartner插件的屏幕快照。在您使用插件查找路线或Sametime合作伙伴所在位置的地图时,将打开一个浏览器窗口。浏览器指向恰当的GoogleMapsURL,可为Sametime用户展示他或她所感兴趣的路线或地图。
我们在插件测试中使用IBM的公共LotusSametime服务器:messaging.ngi.ibm.com。若想了解公共LotusSametime服务器的更多内容,请访问
Eclipse首选项表示一组名称值对。各名称均有两个值,一个默认值和一个用户指定值。若不存在用户指定值,则将使用默认值。
为实现LocatePartner插件逐门逐户的路线指南功能,Google必须了解您出发的起点地址。我们使用一个Eclipse首选项允许Sametime用户指定自己的起点地址,如图2所示。
LocatePartner插件允许一名Sametime用户指定其Web浏览器的位置。与起点地址相同,Web浏览器位置也是使用图2所示的Eclipse首选项存储的。
使用Internet浏览器显示Google路线指南和地图。
遗憾的是,没有任何方法可以获得其他Sametime合作伙伴的Eclipse首选项。相应地,您必须找到一种方法,发现各Eclipse合作伙伴所在的位置。这些信息可以通过我们在上一篇文章中介绍的LDAP目录获得。但为简单起见,我们使用属性文件将Sametime合作伙伴与实际地址关联在一起,每次想获得路线指南或特定Sametime合作伙伴所在位置的地图时,即可动态读取这个属性文件。参见图3。
我们假设您已经安装了EclipseSDK3.2。若尚未安装,可访问
更改目标平台的操作步骤如下:
要创建您的Sametime插件,您需要一个插件项目,在开发过程中容纳插件。创建插件项目的操作步骤如下:
为了使您的LotusSametime插件能够解析LotusSametime类,您需要编辑插件的依赖性。为此:
在一个Java程序中,设置通常是在程序外部的属性文件中完成的。除此之外,基于Eclipse的应用程序还提供了一些扩展点,允许Eclipse开发人员为基于Eclipse的应用程序(在我们的例子中是LotusSametime客户机)的首选项添加一个首选项页面。在您的首选项页面中有两个首选项。第一个首选项是Google路线中的起点地址。第二个首选项是Internet浏览器的位置。例如,编辑浏览器位置,Sametime用户可选择使用InternetExplorer或Firefox来显示路线和/或地图。
您将在一个名为GoogleMap的首选项页面中存储首选项,如图8所示。
要创建GoogleMap首选项页面,打开您的META-INF/MANIFEST.MF文件。选择Extensions选项卡并单击Add按钮打开NewExtension窗口。在NewExtension窗口中,选择ExtensionWizards选项卡。在ExtensionWizards选项卡的右窗格中选择PreferencePage扩展模板并单击Next。参见图9。
这将为您的首选项页面创建一个模板,您可按照自己的需求修改此模板。将首选项页面的类名设置为GMapPreferencePage。首选项页面的名称设置为GoogleMap。使用默认包名称com.devworks.example.map.preferences作为Java包名称,单击Finish(参见图10)。按Ctrl S保存Extensions视图中的更改。
在您创建模板时,Eclipse会为您生成一个名为PreferenceConstants的类。这是一个方便的类,可用于存储您的首选项页面所使用的常量值。可使用如下代码替换自动生成的代码:
ction">/***Constantdefinitionsforplug-inpreferences*/publicclassPreferenceConstants{publicstaticfinalStringMY_LOCATION="myLocation";publicstaticfinalStringBROWSER_LOCATION="browserLocation";} 从上述代码中可以看到,插件使用两个常量:MY_LOCATION和BROWSER_LOCATION,前者表示使用LotusSametime客户机的人的实际地址,后者表示他/她的Internet浏览器的可执行文件所在的磁盘位置。
为您自动生成的另外一个类就是PreferenceInitializer类。这个类的initializeDefaultPreference方法用于为首选项值填充默认值。在下面的代码中,请注意该类是如何使用您在PreferencesConstants类中定义的常量的。默认情况下,浏览器位置设置为MicrosoftInternetExplorer的默认安装位置(c:\ProgramFiles\InternetExplorer\iexplore.exe)。
ction">publicclassPreferenceInitializerextendsAbstractPreferenceInitializer{publicvoidinitializeDefaultPreferences(){IPreferenceStorestore=Activator.getDefault().getPreferenceStore();store.setDefault(PreferenceConstants.MY_LOCATION,"");store.setDefault(PreferenceConstants.BROWSER_LOCATION,"c:\\progra~1\\intern~1\\iexplore.exe");}} 模板生成创建了另外一个名为GMapPreferencePage的类。这个类定义首选项页面的布局。可用如下构造函数片段取代自动生成的构造函数:
ction">publicGMapPreferencePage(){super(GRID);setPreferenceStore(Activator.getDefault().getPreferenceStore());setDescription("PreferencesfortheGoogleMapfeature.");} 在上述代码中,父类的构造函数接受一个参数,一个表示布局的整型参数。我们选择了GRID布局,这种布局默认具有一列。您添加的各FieldEditor部件都将具有自己的一行。
您需要提供输入区域,使客户机可通过这个区域编辑其首选项的值(更具体地说,也就是浏览器位置和实际地址)。本文前面的图2已经展示了结合到您的首选项页面中的图形化输入工具。
为创建输入区域,使用您自己的代码替换所生成的createFieldEditors方法(您必须在父类FieldEditorPreferencePage中覆盖此方法)。在以下代码中,我们通过编程的方式使用StringFieldEditorEclipse部件添加了两个字段编辑器:一个字段编辑器用于捕获Sametime用户的实际地址,另外一个用于捕获其浏览器位置。
ction">publicvoidcreateFieldEditors(){addField(newStringFieldEditor(PreferenceConstants.MY_LOCATION,"MyLocation:",getFieldEditorParent()));addField(newStringFieldEditor(PreferenceConstants.BROWSER_LOCATION,"BrowserPath:",getFieldEditorParent()));}publicvoidinit(IWorkbenchworkbench){} 既然已经创建好了首选项页面,接下来就该着手处理LocatePartner插件的业务功能了。MapUtilities类是一个需要在com.devworks.example.map包下创建的类。MapUtilities类是插件的骨干,它负责生成显示路线和地图所必需的GoogleURL。这个类还负责在客户的机器上打开一个Web浏览器,查看所生成的URL。下面我们来详细剖析这个类及其各种方法,并给出各方法的角色和具体分析。showMap和getAddressURL这两个方法一前一后地发挥作用,显示Sametime合作伙伴的实际地址的地图。类似地,showDirections和getDirectionsURL方法也是一前一后地发挥作用,以显示前往Sametime合作伙伴的实际地址处时的行车路线。
MapUtilities类的showMap方法负责打开客户机Web浏览器的一个实例,并使用GoogleMaps显示Sametime合作伙伴所在地的地图。该类从Eclipse首选项存储中检索用户指定的浏览器位置。这个值与用户在之前所创建的GMapPreference页面中指定的值相同。该类随后调用JavaRuntime.getRuntime().exec()方法来启动浏览器。请特别注意我们是如何通过编程方式从org.eclipse.jface.preference.PreferenceStore对象中获取浏览器位置的。另外,还要注意如何通过对getMapURL方法的一个方法调用来沿用这个浏览器位置。
ction">publicstaticvoidshowMap(Stringaddress){StringbrowserLocation=Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.BROWSER_LOCATION);try{Runtime.getRuntime().exec(browserLocation "" getMapURL(address));}catch(IOExceptione){e.printStackTrace();}} 您可能会感到疑惑,showMap方法是从哪里获得其address字符串参数的?在本文稍后的“AddressStore”部分中将介绍相关内容。
以字符串形式给定一个Sametime合作伙伴的实际地址,getMapURL方法将构造一个GoogleURL地址字符串,在Internet浏览器访问它时,显示特定地理位置的地图。
ction">privatestaticStringgetMapURL(Stringaddress){StringstartURLFragment="http://maps.google.com/maps?f=q&hl=en&q=";StringendURLFragment="&om=1";returnstartURLFragment encodeAddress(address) endURLFragment;} getMapURL方法使用了一个名为encodeAddress的辅助方法。该方法将实际地址解码为Google可以接受的格式。不必担心,解码过程不是什么高端技术。方法只是用加号替换空格:
ction">privatestaticStringencodeAddress(StringunEncodedAddress){returnunEncodedAddress.replace('''','' '');} showDirections方法使用GoogleMaps显示路线,起点是之前创建的GMapPreference页面中指定的地址,终点是Sametime合作伙伴的实际地址。合作伙伴的实际地址是从AddressStore中收集来的。与之前介绍的showMap方法一样,showDirections方法使用Runtime.getRuntime.exec()方法来启动浏览器应用程序。showDirections方法依靠getDirectionsURL方法的返回字符串作为浏览器调用的参数。
ction">publicstaticvoidshowDirections(StringpartnerAddress){StringbrowserLocation=Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.BROWSER_LOCATION);try{Runtime.getRuntime().exec(browserLocation "" getDirectionsURL(partnerAddress));}catch(IOExceptione){e.printStackTrace();}catch(Exceptione){showErrorMessage(e.getMessage(),"PreferenceStoreError");}} 给定一位Sametime合作伙伴的实际地址(从AddressStore中收集而来),getDirectionsURL方法为显示行车路线的Web页面构造一个GoogleMapURL地址。getDirectionsURL方法收集PreferenceStore中的地址,将其作为起点地址:
ction">privatestaticStringgetDirectionsURL(StringtoAddress)throwsException{StringmyAddress=Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.MY_LOCATION);if((myAddress==null)||(myAddress.trim().equals(""))){thrownewException("Nooriginatingaddressspecifiedinthepreferencestore.");}StringsourceUrlFragment="http://maps.google.com/maps?f=d&hl=en&saddr=";StringdestinationURLFragment="&daddr=";StringendURLFragment="&om=1";returnsourceUrlFragment encodeAddress(myAddress) destinationURLFragment encodeAddress(toAddress) endURLFragment;} getDirectionsURL方法利用了encodeAddress方法(getMapURL方法也是如此),将实际地址转换成GoogleMap可以接受的格式。
在“AddressStore”部分中您将看到,定义Sametime合作伙伴实际地址的重担落在了LotusSametime客户机用户的身上。如果用户未指定过一个Sametime合作伙伴的地址,而又想获得其所在地地图或行车路线,showErrorMessage方法将以消息框的形式显示一条错误消息,如图11所示:
产生这样一个错误对话框的逻辑是在showErrorMessage方法中实现的:
ction">publicstaticvoidshowErrorMessage(Stringid,Stringtext){Shellshell=newShell();MessageBoxmessageBox=newMessageBox(shell);messageBox.setMessage(id);messageBox.setText(text);messageBox.open();} 您可能非常迷惑,LocationPartner插件是如何发现Sametime合作伙伴的实际地址的?为简单起见,如“收集您的Sametime合作伙伴所在位置”一节中所述,我们将发现过程设计得非常简单。一名Sametime用户负责填写属性文件,该文件又被读入ResourceBundle。只要LocatePartner插件需要了解Sametime合作伙伴的实际地址(以便显示地图或路线),AddressStore类就会引用ResourceBundle。
ction">publicclassAddressStore{privatestaticfinalStringBUNDLE_NAME="com.devworks.example.map.map";//$NON-NLS-1$,privateAddressStore(){}publicstaticStringgetStreetAddress(StringpartnerId){ResourceBundleRESOURCE_BUNDLE=ResourceBundle.getBundle(BUNDLE_NAME);try{returnRESOURCE_BUNDLE.getString(partnerId);}catch(MissingResourceExceptione){returnnull;}}} AddressStore对象由MapLookup和DirectionsLookup这两个类使用,稍后我们将介绍这两个类。
我们之前发表的developerWorksLotus文章“
例如,一个扩展点可以定义一种修改主插件菜单项的途径。LotusSametime7.5客户机有一个插件定义了ID为com.ibm.collaboration.realtime.people.personAction的扩展点。在这篇文章中,您创建一个扩展,扩展该扩展点的功能性。更具体地来说,您添加了图1所示的GoogleMap和GoogleMapDirections功能性。
在之前介绍的MapUtilities中创建好了地图查找功能性之后,您需要找到一种途径,使用户能够通过SametimeGUI访问此功能。LotusSametimeAPI提供了一个扩展点,可向右击Sametime合作伙伴时(调用上下文菜单)显示的项列表中添加菜单项。要添加您自己的菜单项,将以下代码添加到项目的plugin.xml文件中,从而扩展com.ibm.collaboration.realtime.people.personAction扩展点:
ction"><extensionpoint="com.ibm.collaboration.realtime.people.personAction"><personActionclass="com.devworks.example.map.MapLookup"id="com.devworks.example.map.MapLookup"label="GoogleMap"/></extension> 上述XML代码中,class属性的值是一个扩展RefreshPersonAction类的Java类的名称。也就是说,您确定出,在GoogleMap菜单项被选中时调用com.devworks.example.map.MapLookup类。id属性的值是扩展的惟一ID。我们使用完全限定类名(com.devworks.example.map.MapLookup)作为惟一ID。
MapLookup类如下。
ction">publicclassMapLookupextendsRefreshPersonAction{publicvoidrunWithEvent(Eventarg0){super.runWithEvent(arg0);IPersonperson=getPersons()[0];if(person!=null){Stringid=person.getContactId();System.out.println("PerformingLookupfor" id);//$NON-NLS-1$StringpartnerAddress=AddressStore.getStreetAddress(id);if(partnerAddress!=null)MapUtilities.showMap(partnerAddress);elseMapUtilities.showErrorMessage("Nostreetaddressfoundfor:" id,"PartnernotFound");}}} 当GoogleMap菜单项被选中时,runWithEvent方法即被触发。在这个方法中,您提取了为其选中GoogleMap菜单项的Sametime合作伙伴的联系人ID。然后在AddressStore对象中为该合作伙伴查找相关的实际地址。最终,调用showMap方法,在浏览器窗口中为Sametime用户显示Sametime合作伙伴的GoogleMap。参见图12。
与地图查找扩展相同,您再一次地使用com.ibm.collaboration.realtime.people.personAction扩展点来添加一个菜单项,但这一次您的菜单项名为GoogleMapDirections。与地图查找扩展类似,将以下扩展定义添加到plugin.xml文件中:
ction"><extensionpoint="com.ibm.collaboration.realtime.people.personAction"><personActionclass="com.devworks.example.map.DirectionsLookup"id="com.devworks.example.map.DirectionsLookup"label="GoogleMapDirections"/></extension> 上述扩展定义中,class属性的值是:com.devworks.example.map.DirectionsLookup,这是扩展RefreshPersonAction类的类名称。为Sametime合作伙伴选中了GoogleMapDirections上下文菜单项时,com.devworks.example.map.DirectionsLookup类即被调用。id属性的值是该扩展的惟一ID。我们使用完全限定类名(com.devworks.example.map.DirectionsLookup)作为惟一ID。
DirectionsLookup类如下所示:
ction">publicclassDirectionsLookupextendsRefreshPersonAction{publicvoidrunWithEvent(Eventarg0){super.runWithEvent(arg0);IPersonperson=getPersons()[0];if(person!=null){Stringid=person.getContactId();System.out.println("PerformingLookupfor" id);StringpartnerAddress=AddressStore.getStreetAddress(id);if(partnerAddress!=null)MapUtilities.showDirections(partnerAddress);elseMapUtilities.showErrorMessage("Nostreetaddressfoundfor:" id,"PartnernotFound");}}} 当GoogleMapDirections菜单项被选中时,DirectionsLookup类的runWithEvent方法被触发。在这个方法中,我们收集为其选中GoogleMapDirections上下文菜单项的Sametime合作伙伴的联系人ID。然后在AddressStore对象中查找与这个Sametime合作伙伴相关联的实际地址。最终,调用MapUtilities类的showDirections方法,使用GoogleMaps基于浏览器的路线指南产品来显示前往合作伙伴所在地址的路线。参见图13。
EclipseIDE提供了一种工具,可基于Eclipse平台测试应用程序,要在EclipseIDE内运行LotusSametime7.5,请按以下步骤操作:
要将此部署到LotusSametime,您需要创建一个Install/Update站点。要了解Install/Update站点的更多内容,请阅读Eclipse文章“
如果您跟我们一样,我们要与全国范围(以及全世界范围!)的Sametime合作伙伴打交道。有时,您需要了解您的Sametime合作伙伴身处何处,这样才能前去与他们会面。在这篇文章中,我们为您介绍了如何将GoogleMaps产品与LotusSametime的可扩展性配合使用。您看到了LotusSametime客户机基于Eclipse的基础设施是怎样带来了可为您所利用的可扩展性机遇。特别地,您还了解了Eclipse首选项,这允许用户自定义其基于Eclipse的体验。