JADT 入门,第 2 部分

用 Java 字典和辞典 API 使 Java 用户可以使用您的单词参考

级别: 中级

Rakesh Midhamrakesh@in.ibm.com
软件工程师, IBM 软件实验室,Bangalore
2004 年 10 月

在介绍 JADT 的第 1 篇文章中,介绍了来自 alphaWorks 的一套类库,用于在 Java 应用程序中访问语言特性。接下来,Rakesh Midha 在本文中给出了 JADT 体系结构和 API 的详细说明。他还通过剖析一个驱动程序的实现示例,向您展示了如何把这个 API 的实现作为驱动程序启动。

在本系列文章的 第 1 部分 中,您学到了 JADT 的一些基础知识,JADT 提供了透明地以 Java 为中心的访问字典或非结构化单词以及它们的有关信息的方法。JADT 的主要目标是为字典提供者提供一个可以依据的标准技术,以便他们支持 Java 平台。第 1 部分从开发人员的角度介绍了 JADT。在本文中,我要给出实现的细节,重点从字典开发商的角度考虑。我会带您了解 JADT 以及 JADT 的体系结构的细节,并提供 JADT 中包含的所有类和接口的信息。

在 JADT 示例驱动程序实现的帮助下,我将讨论驱动程序必需的接口实现。之后,您将对 JADT 驱动程序和提供驱动程序的方法有了一个整体的印象。

JADT 体系结构
JADT 体系结构为任何类型的后端数据提供了基于驱动程序的访问。字典提供者实现驱动程序端接口,为字典提供一个访问点,任何使用这个字典的程序,将使用字典服务的用户端接口。结果就是,您可以方便地把 JADT 体系结构与各种开发商和第三方驱动程序集成在一起。如图 1 所示,专用的语言数据总是通过 JADT Driver 实现与 JADT 保持分离:

图 1. JADT 体系结构
JADT 体系结构h

JADT 开发商的角色
如果您想用 JADT 公开您的字典或辞典,那么只需提供 JADT 的实现即可。JADT 驱动程序位于开发商数据和 Java 程序员之间,允许开发商在不完全公开他们的数据和数据格式的情况下,对外提供服务。反过来。Java 程序员也不必深入某个开发商专用的数据和数据格式,就可以使用开发商的数据。

JADT 驱动程序开发商可以使用 JADT 接口,并根据它们自己的习惯实现这些接口。一旦驱动程序就绪,可以访问您的数据,那么就可以在您的站点启用它了。到这个站点的链接,可以作为 JADT 访问页面中的一个线程来使用。

JADT 用一致的方式在所有数据辞典上工作,这一点很重要,所以实现所有符合 JADT 所设标准的 JADT 接口和方法,是开发商的责任。JADT 的 JADT Javadocs 和接口定义文档非常清楚地公开了接口和方法的目标。

JADT 实现近观
JADT 定义了多组接口和类。有些接口是辅助性的,有些是可选的,这取决于您的驱动程序所要支持的功能。如果要完整地支持 JADT,那么就必须按照 Javadocs 中所定义的规范,实现所有接口。在这一节里,我将给出所有这些接口和类实现的细节。

完整的 JADT 接口和类集,如图 2 中的类图所示:

图 2. JADT 类图
JADT 类图

下面我要介绍各种类和接口。

JADTDriverFactoryManager
JADTDriverFactory 对象的基本控制类是 com.ibm.jadt.JADTDriverFactoryManager,这个类就像用户和可用的驱动程序工厂之间的连接。可以用它取得 Driver 的实例,然后再用实例得到某个驱动程序实现的一个或多个 JADT 服务。

JADTDriverFactory 载入之后,由 JADTDriver 提供者负责注册 JADTDriverFactory,所以 JADT 用户还可以在任何时候,通过调用 Class.forName(Driver_factory_class);,显式地装入 JADTDriver

驱动程序工厂类的名称应当随 JADTDriverFactoryName 一起交给用户,用户使用这个类的静态方法 getJADTDriverFactory(String factoryName) ,就可以得到 getJADTDriverFactory。您可以调用静态 registerJADTDriverFactory (JADTDriverFactory factory) 方法来注册它。

JADT 带有下列接口,必须实现这些接口:

  • com.ibm.jadt. JADTDriverFactory
  • com.ibm.jadt.JADTDriver

JADTDriverFactory
com.ibm.jadt.JADTDriverFactory 工厂接口用于建立驱动程序实例,应当由驱动程序的实现者注册到工厂控制器。由于 JADT 是基于驱动程序的产品,所以 JADTDriver 的构造应当一直通过工厂。所有驱动程序实现者都应当实现这个接口。在 DriverFactory 类的静态块里,工厂应当用 FactoryManager 注册,如清单 1 所示:

清单 1. 注册工厂的静态方法

public class JADTSampleDriverFactory  implements JADTDriverFactory
{
 private static JADTSampleDriverFactory factory;
 private Properties props;
 private JADTSampleDriver driver;
  static {
  try{
   if(factory==null)
   factory=new JADTSampleDriverFactory();
   JADTDriverFactoryManager.registerJADTDriverFactory(factory);
   }
  catch(Exception ex){
   //handle exception
  }
 }
}

除了向管理器注册工厂之外, JADTSampleDriverFactory 类还必须实现 createJADTDriver() 方法。可以用 createJADTDriver() 方法把载入和数据访问策略(或者其他任何类型的访问属性)分开。例如,清单 2 显示了您如何才能设置要初始化的工厂数量,这由 loading_strategy 属性决定:

清单 2. 载入策略示例

public JADTDriver createJADTDriver() throws JADTException{	
 if(this.getProperty("loading_strategy")!=null&&
   this.getProperty("loading_strategy").equals("multiple")){
 if(this.getProperty("JADTSampleDriverDir")==null)
  return driver=new JADTSampleDriver();
 else return driver=new JADTSampleDriver
   (this.getProperty("JADTSampleDriverDir"));
 }
 return new JADTSampleDriver();
 else
 {
  if(this.getProperty("JADTSampleDriverDir")!=null)
  if(driver==null)
   driver=new JADTTextDriver(this.getProperty("JADTSampleDriverDir"));
  else
   if(driver==null)
   driver=new JADTSampleDriver();
   return driver;
  }
 }

驱动程序使用的所有属性,都必须编制文档,并提供驱动程序使用指南。这个接口方法的其余部分是自解释的,所以可以很容易地实现。

JADTDriver 接口
com.ibm.jadt.JADTDriver 接口是所有驱动程序都必须实现的主驱动程序接口。它是由 JADTDriverFactory 建立的,是向您提供驱动程序服务访问的类,服务包括字典、辞典、拼写检查器、单词表、翻译器、语法检测器,以及词变位器。

这个接口代表具体厂商的驱动程序。除此之外,相同的驱动程序厂商还可以为不同的语言提供服务。

JADTDriver 类必须实现基本的构造函数方法,构造函数方法可以用来指定属性,例如数据库、目录或者数据访问方法。还可以用构造函数初始化数据库的基本连接。类的结构如清单 3 所示:

清单 3. JADTSampleDriver 基本示例代码

public class JADTSampleDriver implements JADTDriver
{
 private Properties props;
 public JADTSampleDriver()
 {
  props=new Properties();
 }
 public JADTSampleDriver(String datapath)
 {
  props=new Properties();
  setProperty("JADTSampleDriverDir",filepath);
 }
 /*
  Rest all methods
 */
}

JADTDriver 类还提供了对各种服务的访问,所以这个类实现了所有类都使用的公共 get>Service< 方法。 例如,getDictionary() 方法看起来会像清单 4:

清单 4. 字典服务方法实现

public Dictionary getDictionary(String langFrom,String langTo) throws JADTException
{
 try{
  if(getProperty("JADTSampleDriverDir")!=null){
   return new SampleDictionary
     (langFrom,langTo,getProperty("JADTSampleDriverDir"));
  }
  else return new SampleDictionary(langFrom,langTo);
 }
 catch(JADTException exp){
  JADTException ex1=new JADTException
    ("DictionaryFailure","Could not create dictionary");
  ex1.setNextException(exp);
  throw ex1;
 }
}

此外,清单 5 中显示的方法也必须用类似的风格实现:

清单 5. 其他服务方法列表

public WordBook getWordBook
  (String lang)throws JADTException;
public SpellChecker getSpellChecker
  (String lang)throws JADTException;
public WordLister getWordlister
  (String lang)throws JADTException;
public Translator getTranslator
  (String langFrom,String langTo)throws JADTException;
public GrammarChecker getGrammarChecker
  (String lang)throws JADTException;
public Anagrammizer getAnagrammizer
  (String lang)throws JADTException;

使用数据结构
JADT 还提供了另外一组类和接口,用于提供组织数据的一般性方法。因为所有服务都使用数据库结构,所以 JADT 用户知道数据结构是非常重要的。在下一节中,我会回顾一下数据结构。

单词表接口
WordList 接口代表单词的列表。因为它就是单词的容器,所以它并不从后端资源提取数据。 WordList 一般用于传递、获取、设置单词,或者包含某些单词。

WordList 类的结构如清单 6 所示:

清单 6. SampleWordlist 实现

public class SampleWordList implements WordList
{
 private Vector words;
 private int currentPos=0;
 public TextWordList()   {/*default constructor*/}
 public int size(){return words.size();}
 public void addWord(Word word)
 {
  words.addElement(word);
 }
 public void addWords(Vector vec)
 {
  words.addAll(vec);
 }
 public Vector getAllWords()
 {
  return words;
 }
 public void Start()
 {
  currentPos=0;
 }
 public boolean hasMoreWords()
 {
  if(currentPos==words.size()) return false;
  else return true;
 }
 public WordList findWithPrefix(String find)
 {
 /* implementation */
 }
 public WordList findWithSuffix(String find)
 {
 /* implementation */
 }
 public WordList findWithSubstring(String find)
 {
 /* implementation */
 }
}

单词接口
Word 接口是字符的组合,代表母语使用者能够识别的语言单元。 Word 接口包装了单词的有关信息。保存在 Word 接口中的信息包括:拼写、类型、来源、发音和记录。

因为这个接口以真实格式表示单词,所以实现应当提供一个容器,容器带有必需的 get 和 set 方法。清单 7 显示的信息对于形成单词是必需的:

清单 7. 示例单词属性

private String word;
private String type;
private DictionaryRecord meaning;
private DictionaryRecord synonym;
private DictionaryRecord antonym;
		 		 		 
private String pronunciation;
		 
public static final int MEANINGS=1;
public static final int SYNONYMS=2;
public static final int ANTONYMS=3;
		 		 
private String source="";

这些字段可以通过它们的 get 和 set 方法来访问。

JADT 服务
JADT 为各种服务对象定义了接口。在下一节中,我将逐一介绍当前 JADT 版本中包含的服务对象。

字典接口
Dictionary 接口代表参考书,参考书里包含按字母顺序排列的单词表。每个条目都包含释义、类型、发音、来源和用法。

Dictionary 的实现应当包含字典接口中的所有方法,但不包含构造函数,同时要用恰当的载入机制。载入机制可以是消极(lazy),一次性(single shot),或者多重装入(multiple load) 策略,具体取决于属性,而且可以修正载入机制。

例如,构造函数应当从数据库或文件中一次性载入数据,然后把数据保存在字典实现存储库中,如清单 8 所示:

清单 8. SampleDictionary 类

public class SampleDictionary implements Dictionary
{
 private Hashtable words;
 private String langFrom;
 private String langTo;
		 		 		 		 
 public static final int LOADWHOLEONE=1;
 public static final int LOADWHOLEMULTIPLE=2;
 public static final int RUNTIME=3;
 public static final int INDEXING=4;
		 		 		 		 
 private int technique;
		 		 		 		 
 public SampleDictionary(String strLangFrom,String strLangTo,
   String dir,int method)  throws JADTException{
 /*
  Load the data from storage unit, according to strategy defined.
 */
 }
 /*
  Rest all methods
 */
}

余下的方法只是 getMeaning() 方法的变体,负责从载入的数据中提取单个或多个单词的含义。清单 9 显示了一个例子:

清单 9. 示例 getMeaning 方法

public com.ibm.jadt.DictionaryRecord getMeaning(Word word)
{
 if(words.containsKey(word.toString().toLowerCase()))
  return ((Word)words.get(word.toString().toLowerCase())).getRecord(TextWord.MEANINGS);
 else return null;
}

辞典组件
WordBook 是一个服务组件,它提供所有相关单词的信息。这些单词可以根据用法、来源、发音等进行关联。JADT 的当前版本提供了实现同义词、反义词、上位词、下位词、整体名词、部分名词的接口,我们在 第 1 部分中已经讨论过。

实现需要让方法可以访问所有这类数据,建立从数据源载入数据的必要机制,如清单 10 所示:

清单 10. 示例辞典实现

public class SampleWordBook implements WordBook
{
 private Hashtable wordsSyn;
 /* private hashtable for rest all services data, this act like a repository for data */
 public SampleWordBook(){
  /* loads required data into repository*/
 }
 public DictionaryRecord getSynonyms(Word word) throws JADTException {
  WordList syn=(WordList)wordsSyn.get(word.toString());
  if(syn==null||syn.size()==0)
  return null;
  DictionaryRecord first=null;
  DictionaryRecord curr=null;
  Enumeration enum=syn.getAllWords().elements();
  while (enum.hasMoreElements())
   {
   if(first==null)
   {
    curr=new DictionaryRecord();first=curr;
   }
   else
   {
    curr.setNextRecord(new DictionaryRecord());
    curr=curr.getNextRecord();
   }
   curr.setWordName(((Word)enum.nextElement()).toString());
  }
  return first;
 }
 /*
 Similarly implement rest all services methods
 */
}

其他服务
其余的服务我已经在第 1 部分详细介绍过。这里是一个快速回顾,包括附加的实现细节。

拼写检查器
SpellChecker 类用于捕获拼写错误的单词。这个类在执行方面没有什么新鲜东西。

它把数据保存在私有散列表中,并实现了其他方法。它还实现了检查拼写的算法。这个服务类与其他服务的实现方式一样。

单词表类
WordLister 可用于从后端资源取得单词。JADT WordLister 还提供了一个选项,可以查找符合某个规则(例如相似前缀、相似后缀和公共子字符串)的所有单词。

WordLister 类把数据保存在私有散列表中,并实现了其他方法。它还实现了检查拼写的算法。这个服务类与其他服务的实现方式一样。

词变位器类
Anagrammizer 可以给出单词或短语的所有变位形式,对于文字游戏应用程序来说会非常有用。这个类还实现了得到单词的变位词的算法。

语法检查器类
GrammarChecker 检查单词在句子中的排列,检查单词在特定上下文中的用法。它还实现了检查语法的算法。这个服务类与其他服务的实现方式一样。

翻译器类
Translator 类用于把单词或消息从一种语言转换成另一种语言。这个特性可以用在本地化和国际化实现上。利用这个特性,用一种语言编写的资源绑定文件可以被转换成另外一种语言。

Translator 实现了把单词和句子从一种语言翻译成另外一种语言的算法。这个服务类与其他服务的实现方式一样。

汇总
一旦您已经实现了所有的服务接口和驱动程序类,您就可以把所有类捆绑在一个包里。最后的包结构看起来类似于清单 11:

清单 11. JADTDriver 包结构

com/ibm/jadt
 Anagrammizer
 Dictionary
 DictionaryRecord
 GrammarChecker
 JADTDriver
 JADTDriverFactory
 JADTDriverFactoryManager
 JADTException
 SpellChecker
 Translator
 Word
 WordBook
 WordList
 WordLister
com/ibm/jadtdrivers/SampleDriver
 JADTSampleDriver
  JADTSampleDriverFactory
 SampleWord
com/ibm/jadtdrivers/SampleDriver/anagrammizer
 SampleAnagrammizer
com/ibm/jadtdrivers/SampleDriver/dictionary
 SampleDictionary
com/ibm/jadtdrivers/SampleDriver/spellchecker
 SampleSpellChecker
com/ibm/jadtdrivers/SampleDriver/wordbook
 SampleWordBook
com/ibm/jadtdrivers/SampleDriver/wordlist
 SampleWordList
 SampleWordLister

把这些文件捆绑成一个 JAR 文件,您就可以部署它了。

结束语
通过本系列文章,您对于 JADT 技术有了全面的了解。这篇文件介绍了基本的 JADT 结构,以及如何使用不同的 JADT 服务和组件建立使用字典和其他与单词有关的特性的 Java 应用程序。

参考资料

 

关于作者
Author photoRakesh Midha 是 Bangalore 的 IBM 软件试验室的软件工程师。他目前从事 IBM WebSphere 业务组件开发工作。他有 5 年在多平台和各种关系数据库系统(像 DB2 UDB、Oracle、MySQL 和 Microsoft SQL Server)上进行 Java 和 C++ 服务器端编程的经验。他的专长领域包括在银行、金融、编目行业以及订单和仓储管理系统等领域设计和开发独立的和 n 层分布式系统。他从 Chandigarh 的 Punjab 大学获得了电子工程学士学位,是 Java 字典和辞典方面的技术专家,这项技术是由 IBM alphaWorks 启动的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值