1 package com
.swabunga
.spell
.engine
;
6 /** A Generic implementation of a transformator takes an aspell
7 * phonetics file and constructs some sort of transformationtable using
8 * the inner class Rule.
10 * @author Robert Gustavsson (robert@lindesign.se)
12 public class GenericTransformator
implements Transformator
{
14 public static final char STARTMULTI
='(';
15 public static final char ENDMULTI
=')';
17 Object
[] ruleArray
=null
;
19 public GenericTransformator(File phonetic
)throws IOException
{
20 buildRules(new BufferedReader(new FileReader(phonetic
)));
24 * Returns the phonetic code of the word.
26 public String
transform(String word
) {
29 TransformationRule rule
;
30 StringBuffer str
=new StringBuffer(word
.toUpperCase());
31 int strLength
=str
.length();
32 int startPos
=0, add
=1;
34 while(startPos
<strLength
){
35 //System.out.println("StartPos:"+startPos);
37 for(int i
=0;i
<ruleArray
.length
;i
++){
38 //System.out.println("Testing rule#:"+i);
39 rule
=(TransformationRule
)ruleArray
[i
];
40 if(rule
.startsWithExp() && startPos
>0)
42 if(startPos
+rule
.lengthOfMatch()>=strLength
)
44 if(rule
.isMatching(str
,startPos
)){
45 str
.replace(startPos
,startPos
+rule
.getTakeOut(),rule
.getReplaceExp());
46 add
=rule
.getReplaceExp().length();
47 strLength
-=rule
.getTakeOut();
49 //System.out.println("Replacing with rule#:"+i+" add="+add);
55 return str
.toString();
58 // Used to build up the transformastion table.
59 private void buildRules(BufferedReader
in)throws IOException
{
61 LinkedList ruleList
=new LinkedList();
62 while((read
=in.readLine())!=null
){
63 buildRule(realTrimmer(read
),ruleList
);
65 ruleArray
=ruleList
.toArray();
68 // Here is where the real work of reading the phonetics file is done.
69 private void buildRule(String str
, LinkedList ruleList
){
72 if(str
.startsWith("version"))
75 TransformationRule rule
=null
;
76 StringBuffer matchExp
=new StringBuffer();
77 StringBuffer replaceExp
=new StringBuffer();
78 boolean start
=false
, end
=false
;
79 int takeOutPart
=0, matchLength
=0;
80 boolean match
=true
, inMulti
=false
;
81 for(int i
=0;i
<str
.length();i
++){
82 if(Character
.isWhitespace(str
.charAt(i
))){
86 if (!isReservedChar(str
.charAt(i
))){
87 matchExp
.append(str
.charAt(i
));
92 if(str
.charAt(i
)==STARTMULTI
|| str
.charAt(i
)==ENDMULTI
)
95 if (str
.charAt(i
)=='-')
97 if (str
.charAt(i
)=='^')
99 if (str
.charAt(i
)=='$')
102 replaceExp
.append(str
.charAt(i
));
106 rule
=new TransformationRule(matchExp
.toString(), replaceExp
.toString()
107 , takeOutPart
, matchLength
, start
, end
);
111 // Chars with special meaning to aspell. Not everyone is implemented here.
112 private boolean isReservedChar(char ch
){
113 if(ch
=='<' || ch
=='>' || ch
=='^' || ch
=='$' || ch
=='-' || Character
.isDigit(ch
))
118 // Trims off everything we don't care about.
119 private String
realTrimmer(String row
){
120 int pos
=row
.indexOf('#');
122 row
=row
.substring(0,pos
);
129 * Holds the match string and the replace string and all the rule attributes.
130 * Is responsible for indicating matches.
132 private class TransformationRule
{
134 private String replace
;
135 private char[] match
;
136 // takeOut=number of chars to replace;
137 // matchLength=length of matching string counting multies as one.
138 private int takeOut
, matchLength
;
139 private boolean start
, end
;
142 public TransformationRule(String match
, String replace
, int takeout
143 , int matchLength
, boolean start
, boolean end
){
144 this.match
=match
.toCharArray();
145 this.replace
=replace
;
146 this.takeOut
=takeout
;
147 this.matchLength
=matchLength
;
153 * Returns true if word from pos and forward matches the match string.
154 * Precondition: wordPos+matchLength<word.length()
156 public boolean isMatching(StringBuffer word
, int wordPos
){
157 boolean matching
=true
, inMulti
=false
, multiMatch
=false
;
160 for(int matchPos
=0;matchPos
<match
.length
;matchPos
++){
161 matchCh
=match
[matchPos
];
162 if(matchCh
==STARTMULTI
|| matchCh
==ENDMULTI
){
165 matching
=matching
& multiMatch
;
169 if(matchCh
!=word
.charAt(wordPos
)){
171 multiMatch
=multiMatch
| false
;
176 multiMatch
=multiMatch
| true
;
186 if(end
&& wordPos
!=word
.length()-1)
191 public String
getReplaceExp(){
195 public int getTakeOut(){
199 public boolean startsWithExp(){
203 public int lengthOfMatch(){
207 // Just for debugging purposes.
208 public String
toString(){
209 return "Match:"+String
.valueOf(match
)
212 +" MatchLength:"+matchLength