Skip to content

Commit cec801e

Browse files
committed
Fix failing test "gna": org.apache.commons.codec.language.bm.BeiderMorseEncoderTest.testEncodeGna()
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/codec/trunk@1151603 13f79535-47bb-0310-9956-ffa450edef68
1 parent 0a23747 commit cec801e

3 files changed

Lines changed: 90 additions & 33 deletions

File tree

src/java/org/apache/commons/codec/language/bm/PhoneticEngine.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,11 @@ public String encode(String input) {
145145
* @return a phonetic representation of the input; a String containing '-'-separated phonetic representations of the input
146146
*/
147147
public String phoneticUtf8(String input, final Set<String> languageSet) {
148-
List<Rule> rules = Rule.instance(this.nameType, RuleType.RULES, languageSet);
149-
List<Rule> finalRules1 = Rule.instance(this.nameType, this.ruleType, "common");
150-
List<Rule> finalRules2 = Rule.instance(this.nameType, this.ruleType, languageSet);
148+
final List<Rule> rules = Rule.instance(this.nameType, RuleType.RULES, languageSet);
149+
final List<Rule> finalRules1 = Rule.instance(this.nameType, this.ruleType, "common");
150+
final List<Rule> finalRules2 = Rule.instance(this.nameType, this.ruleType, languageSet);
151+
// System.err.println("Languages: " + languageSet);
152+
// System.err.println("Rules: " + rules);
151153

152154
// tidy the input
153155
// lower case is a locale-dependent operation
@@ -345,6 +347,11 @@ private String expand(String phonetic) {
345347
String prefix = phonetic.substring(0, altStart);
346348
altStart++;
347349
int altEnd = phonetic.indexOf(')');
350+
351+
if (altEnd < altStart) {
352+
throw new IllegalArgumentException("Phonetic string has a close-bracket before the first open-bracket");
353+
}
354+
348355
String altString = phonetic.substring(altStart, altEnd);
349356
altEnd++;
350357
String suffix = phonetic.substring(altEnd);

src/java/org/apache/commons/codec/language/bm/Rule.java

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Map;
2828
import java.util.Scanner;
2929
import java.util.Set;
30+
import java.util.Stack;
3031
import java.util.regex.Pattern;
3132

3233
/**
@@ -77,10 +78,10 @@
7778
* @since 2.0
7879
*/
7980
public class Rule {
80-
private static final String DOUBLE_QUOTE = "\"";
81-
8281
public static final String ALL = "ALL";
8382

83+
private static final String DOUBLE_QUOTE = "\"";
84+
8485
private static final String HASH_INCLUDE = "#include";
8586

8687
private static final Map<NameType, Map<RuleType, Map<String, List<Rule>>>> RULES = new EnumMap<NameType, Map<RuleType, Map<String, List<Rule>>>>(
@@ -95,10 +96,14 @@ public class Rule {
9596

9697
Languages ls = Languages.instance(s);
9798
for (String l : ls.getLanguages()) {
98-
rs.put(l, parseRules(mkScanner(s, rt, l)));
99+
try {
100+
rs.put(l, parseRules(createScanner(s, rt, l)));
101+
} catch (IllegalStateException e) {
102+
throw new IllegalStateException("Problem processing " + createResourceName(s, rt, l), e);
103+
}
99104
}
100105
if (!rt.equals(RuleType.RULES)) {
101-
rs.put("common", parseRules(mkScanner(s, rt, "common")));
106+
rs.put("common", parseRules(createScanner(s, rt, "common")));
102107
}
103108

104109
rts.put(rt, Collections.unmodifiableMap(rs));
@@ -108,6 +113,32 @@ public class Rule {
108113
}
109114
}
110115

116+
private static String createResourceName(NameType nameType, RuleType rt, String lang) {
117+
return String.format("org/apache/commons/codec/language/bm/%s_%s_%s.txt", nameType.getName(), rt.getName(), lang);
118+
}
119+
120+
private static Scanner createScanner(NameType nameType, RuleType rt, String lang) {
121+
String resName = createResourceName(nameType, rt, lang);
122+
InputStream rulesIS = Languages.class.getClassLoader().getResourceAsStream(resName);
123+
124+
if (rulesIS == null) {
125+
throw new IllegalArgumentException("Unable to load resource: " + resName);
126+
}
127+
128+
return new Scanner(rulesIS, ResourceConstants.ENCODING);
129+
}
130+
131+
private static Scanner createScanner(String lang) {
132+
String resName = String.format("org/apache/commons/codec/language/bm/%s.txt", lang);
133+
InputStream rulesIS = Languages.class.getClassLoader().getResourceAsStream(resName);
134+
135+
if (rulesIS == null) {
136+
throw new IllegalArgumentException("Unable to load resource: " + resName);
137+
}
138+
139+
return new Scanner(rulesIS, ResourceConstants.ENCODING);
140+
}
141+
111142
/**
112143
* Gets rules for a combination of name type, rule type and languages.
113144
*
@@ -148,33 +179,13 @@ public static List<Rule> instance(NameType nameType, RuleType rt, String lang) {
148179
return rules;
149180
}
150181

151-
private static Scanner mkScanner(NameType nameType, RuleType rt, String lang) {
152-
String resName = String.format("org/apache/commons/codec/language/bm/%s_%s_%s.txt", nameType.getName(), rt.getName(), lang);
153-
InputStream rulesIS = Languages.class.getClassLoader().getResourceAsStream(resName);
154-
155-
if (rulesIS == null) {
156-
throw new IllegalArgumentException("Unable to load resource: " + resName);
157-
}
158-
159-
return new Scanner(rulesIS, ResourceConstants.ENCODING);
160-
}
161-
162-
private static Scanner mkScanner(String lang) {
163-
String resName = String.format("org/apache/commons/codec/language/bm/%s.txt", lang);
164-
InputStream rulesIS = Languages.class.getClassLoader().getResourceAsStream(resName);
165-
166-
if (rulesIS == null) {
167-
throw new IllegalArgumentException("Unable to load resource: " + resName);
168-
}
169-
170-
return new Scanner(rulesIS, ResourceConstants.ENCODING);
171-
}
172-
173182
private static List<Rule> parseRules(Scanner scanner) {
174183
List<Rule> lines = new ArrayList<Rule>();
184+
int currentLine = 0;
175185

176186
boolean inMultilineComment = false;
177187
while (scanner.hasNextLine()) {
188+
currentLine++;
178189
String rawLine = scanner.nextLine();
179190
String line = rawLine;
180191

@@ -206,7 +217,7 @@ private static List<Rule> parseRules(Scanner scanner) {
206217
if (incl.contains(" ")) {
207218
System.err.println("Warining: malformed import statement: " + rawLine);
208219
} else {
209-
lines.addAll(parseRules(mkScanner(incl)));
220+
lines.addAll(parseRules(createScanner(incl)));
210221
}
211222
} else {
212223
// rule
@@ -218,6 +229,11 @@ private static List<Rule> parseRules(Scanner scanner) {
218229
String lCon = stripQuotes(parts[1]);
219230
String rCon = stripQuotes(parts[2]);
220231
String ph = stripQuotes(parts[3]);
232+
try {
233+
validatePhenome(ph);
234+
} catch (IllegalArgumentException e) {
235+
throw new IllegalStateException("Problem parsing line " + currentLine, e);
236+
}
221237
Rule r = new Rule(pat, lCon, rCon, ph, Collections.<String> emptySet(), ""); // guessing last 2 parameters
222238
lines.add(r);
223239
}
@@ -241,6 +257,40 @@ private static String stripQuotes(String str) {
241257
return str;
242258
}
243259

260+
private static void validatePhenome(CharSequence ph) {
261+
Stack<Character> stack = new Stack<Character>();
262+
for (int i = 0; i < ph.length(); i++) {
263+
switch (ph.charAt(i)) {
264+
case '(':
265+
stack.push('(');
266+
break;
267+
case '[':
268+
stack.push('[');
269+
break;
270+
case ')': {
271+
if (stack.isEmpty())
272+
throw new IllegalArgumentException("Closing ')' at " + i + " without an opening '('" + " in " + ph);
273+
char c = stack.pop();
274+
if (c != '(')
275+
throw new IllegalArgumentException("Closing ')' does not pair with opening '" + c + "' at " + i + " in " + ph);
276+
break;
277+
}
278+
case ']': {
279+
if (stack.isEmpty())
280+
throw new IllegalArgumentException("Closing ']' at " + i + " without an opening '['" + " in " + ph);
281+
char c = stack.pop();
282+
if (c != '[')
283+
throw new IllegalArgumentException("Closing ']' does not pair with opening '" + c + "' at " + i + " in " + ph);
284+
break;
285+
}
286+
default:
287+
break;
288+
}
289+
}
290+
if (!stack.isEmpty())
291+
throw new IllegalArgumentException("Bracket(s) opened without corresponding closes: " + stack + " in " + ph);
292+
}
293+
244294
private final Set<String> languages;
245295

246296
private final Pattern lContext;

src/test/org/apache/commons/codec/language/bm/BeiderMorseEncoderTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected StringEncoder createStringEncoder() {
4646
*
4747
* @throws EncoderException
4848
*/
49-
@Ignore
49+
// @Ignore
5050
@Test
5151
public void testEncodeGna() throws EncoderException {
5252
BeiderMorseEncoder bmpm = new BeiderMorseEncoder();
@@ -71,7 +71,7 @@ public void testInvalidLanguageIllegalArgumentException() {
7171
}
7272

7373
@Ignore
74-
@Test
74+
@Test(timeout = 10000L)
7575
public void testLongestEnglishSurname() throws EncoderException {
7676
BeiderMorseEncoder bmpm = new BeiderMorseEncoder();
7777
bmpm.setNameType(NameType.GENERIC);
@@ -113,7 +113,7 @@ public void testSetRuleTypeToRulesIllegalArgumentException() {
113113
}
114114

115115
@Ignore
116-
@Test
116+
@Test(timeout = 10000L)
117117
public void testSpeedCheck() throws EncoderException {
118118
char[] chars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'o', 'u' };
119119
BeiderMorseEncoder bmpm = new BeiderMorseEncoder();

0 commit comments

Comments
 (0)