• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ljacqu / wordeval / 14626813804

23 Apr 2025 07:48PM UTC coverage: 60.853% (+0.7%) from 60.152%
14626813804

push

github

ljacqu
Flatten affix rules in model, consider crossproduct, check strip when applying rule

357 of 672 branches covered (53.13%)

38 of 40 new or added lines in 4 files covered. (95.0%)

956 of 1571 relevant lines covered (60.85%)

3.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.3
/src/main/java/ch/jalu/wordeval/dictionary/hunspell/HunspellUnmuncherService.java
1
package ch.jalu.wordeval.dictionary.hunspell;
2

3
import com.google.common.base.Preconditions;
4
import org.apache.commons.lang3.StringUtils;
5
import org.springframework.stereotype.Service;
6

7
import java.util.ArrayList;
8
import java.util.List;
9
import java.util.stream.Stream;
10

11
/**
12
 * Service to "unmunch" words (i.e. expand) based on Hunspell affix rules.
13
 */
14
@Service
15
public class HunspellUnmuncherService {
3✔
16

17
  /**
18
   * Processes the given dictionary lines and expands them based on the specified affix rules.
19
   *
20
   * @param lines the lines of the dictionary file (including affix information)
21
   * @param affixDefinition the dictionary's affix definitions
22
   * @return all words isolated and expanded
23
   */
24
  public Stream<String> unmunch(Stream<String> lines, HunspellAffixes affixDefinition) {
25
    return lines.flatMap(line -> unmunch(line, affixDefinition));
11✔
26
  }
27

28
  private Stream<String> unmunch(String line, HunspellAffixes affixDefinition) {
29
    int indexOfSlash = line.indexOf('/');
4✔
30
    if (indexOfSlash <= 0) {
2✔
31
      // We don't support empty strings as base
32
      return Stream.of(line);
3✔
33
    }
34

35
    String baseWord = line.substring(0, indexOfSlash);
5✔
36
    String affixFlagList = StringUtils.substringBefore(line.substring(indexOfSlash + 1), " ");
8✔
37
    List<String> affixFlags = affixDefinition.getFlagType().split(affixFlagList);
5✔
38

39
    List<String> results = new ArrayList<>();
4✔
40
    boolean includeBaseWord = affixDefinition.getNeedAffixFlag() == null
5✔
41
        || !affixFlags.contains(affixDefinition.getNeedAffixFlag());
7!
42
    if (includeBaseWord) {
2✔
43
      results.add(baseWord);
4✔
44
    }
45

46
    populateWithAffixes(baseWord, affixFlags, results, affixDefinition);
6✔
47
    return results.stream();
3✔
48
  }
49

50
  private void populateWithAffixes(String baseWord, List<String> affixFlags, List<String> results,
51
                                   HunspellAffixes affixDefinition) {
52
    affixFlags.stream()
5✔
53
        .flatMap(affixFlag -> affixDefinition.streamThroughMatchingRules(baseWord, affixFlag))
12✔
54
        .forEach(affixRule -> {
1✔
55
          String wordWithAffix = affixRule.applyRule(baseWord);
4✔
56
          if (wordWithAffix == null) {
2✔
57
            return;
1✔
58
          }
59
          results.add(wordWithAffix);
4✔
60

61

62
          if (!affixRule.getContinuationClasses().isEmpty()) {
4✔
63
            populateWithAffixes(wordWithAffix, affixRule.getContinuationClasses(), results, affixDefinition);
7✔
64
          }
65

66
          if (affixRule.getType() == AffixType.PFX && affixRule.isCrossProduct()) {
7!
67
            affixFlags.stream()
5✔
68
                .flatMap(affixFlag -> affixDefinition.streamThroughMatchingRules(wordWithAffix, affixFlag))
7✔
69
                .filter(rule -> rule.getType() == AffixType.SFX && rule.isCrossProduct())
15✔
70
                .forEach(suffixRule -> {
1✔
71
                  String suffixedResult = suffixRule.applyRule(wordWithAffix);
4✔
72
                  if (suffixedResult == null) {
2!
NEW
73
                    return;
×
74
                  }
75
                  Preconditions.checkArgument(suffixRule.getContinuationClasses().isEmpty(),
5✔
76
                      "Unexpected continuation classes on suffix rule");
77
                  results.add(suffixedResult);
4✔
78
                });
1✔
79

80
          }
81
        });
1✔
82
  }
1✔
83
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc