用 Java 字典和辞典 API 使 Java 用户可以使用您的单词参考
在本系列文章的 第 1 部分中,您学到了 JADT 的一些基础知识,JADT 提供了透明地以 Java 为中心的访问字典或非结构化单词以及它 们的有关信息的方法。JADT 的主要目标是为字典提供者提供一个可以依据的标准技术,以便他们支持 Java 平台。第 1 部分从开发人员的 角度介绍了 JADT。在本文中,我要给出实现的细节,重点从字典开发商的角度考虑。我会带您了解 JADT 以及 JADT 的体系结构的细节, 并提供 JADT 中包含的所有类和接口的信息。
在 JADT 示例驱动程序实现的帮助下,我将讨论驱动程序必需的接口实现。之后,您将对 JADT 驱动程序和提供驱动程序的方法有了一 个整体的印象。
JADT 体系结构
JADT 体系结构为任何类型的后端数据提供了基于驱动程序的访问。字典提供者实现驱动程序端接口,为字典提供一个访问点,任何使用 这个字典的程序,将使用字典服务的用户端接口。结果就是,您可以方便地把 JADT 体系结构与各种开发商和第三方驱动程序集成在一起。
Driver 实现与 JADT 保持分离:
JADT 开发商的角色
如果您想用 JADT 公开您的字典或辞典,那么只需提供 JADT 的实现即可。JADT 驱动程序位于开发商数据和 Java 程序员之间,允许开 发商在不完全公开他们的数据和数据格式的情况下,对外提供服务。反过来。Java 程序员也不必深入某个开发商专用的数据和数据格式, 就可以使用开发商的数据。
JADT 驱动程序开发商可以使用 JADT 接口,并根据它们自己的习惯实现这些接口。一旦驱动程序就绪,可以访问您的数据,那么就可以 在您的站点启用它了。到这个站点的链接,可以作为 JADT 访问页面中的一个线程来使用。
JADT 用一致的方式在所有数据辞典上工作,这一点很重要,所以实现所有符合 JADT 所设标准的 JADT 接口和方法,是开发商的责任。 JADT 的 JADT Javadocs 和接口定义文档非常清楚地公开了接口和方法的目标。
JADT 实现近观
JADT 定义了多组接口和类。有些接口是辅助性的,有些是可选的,这取决于您的驱动程序所要支持的功能。如果要完整地支持 JADT, 那么就必须按照 Javadocs 中所定义的规范,实现所有接口。在这一节里,我将给出所有这些接口和类实现的细节。
完整的 JADT 接口和类集,如图 2 中的类图所示:
图 2. 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. JADTDriverFacTorycom.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 WordListercom/ibm/jadtdrivers/SampleDriver JADTSampleDriver JADTSampleDriverFacTory SampleWordcom/ibm/jadtdrivers/SampleDriver/anagrammizer SampleAnagrammizercom/ibm/jadtdrivers/SampleDriver/dictionary SampleDictionarycom/ibm/jadtdrivers/SampleDriver/spellchecker SampleSpellCheckercom/ibm/jadtdrivers/SampleDriver/wordbook SampleWordBookcom/ibm/jadtdrivers/SampleDriver/wordlist SampleWordList SampleWordLister
把这些文件捆绑成一个 JAR 文件,您就可以部署它了。
结束语
通过本系列文章,您对于 JADT 技术有了全面的了解。这篇文件介绍了基本的 JADT 结构,以及如何使用不同的 JADT 服务和组件建立 使用字典和其他与单词有关的特性的 Java 应用程序。
海内存知已,天涯若比邻。