class VagueSpellChecker {

  private final static Map<Language, Rule> langToRule = new HashMap<>();
  private final static Map<Language, Dictionary> langToDict = new HashMap<>();
  
  public boolean isValidWord(String word, Language lang) {
    Rule rule = langToRule.get(lang);
    if (rule == null) {
      Rule tempRule = getSpellingCheckRule(lang);
      if (tempRule instanceof HunspellRule) {
        rule = tempRule;
      } else if (tempRule instanceof MorfologikSpellerRule) {
        rule = new NonThreadSafeSpellRule(JLanguageTool.getMessageBundle(), lang, null);
      }
      langToRule.put(lang, rule);
    }
    if (rule instanceof NonThreadSafeSpellRule) {
      // indicates a Morfologik-based speller - it's not thread-safe, so re-create Speller in isMisspelled():
      return ((NonThreadSafeSpellRule) rule).isMisspelled(word);
    } else if (rule instanceof HunspellRule) {
      // it's okay to use a cached rule, as hunspell-based "isMisspelled()" is thread-safe
      return !((HunspellRule) rule).isMisspelled(word);
    } else {
      throw new RuntimeException("Unknown rule type for language " + lang.getShortCodeWithCountryAndVariant() + ": " + rule);
    }
  }

  private SpellingCheckRule getSpellingCheckRule(Language lang) {<FILL_FUNCTION_BODY>}

  private class NonThreadSafeSpellRule extends SpellingCheckRule {

    private NonThreadSafeSpellRule(ResourceBundle messages, Language language, UserConfig userConfig) {
      super(messages, language, userConfig);
    }

    @Override
    public String getId() {
      return "FAKE_FOR_VAGUE_SPELL_CHECKER";
    }

    @Override
    public String getDescription() {
      return "internal";
    }

    @Override
    public RuleMatch[] match(AnalyzedSentence sentence) throws IOException {
      throw new RuntimeException("not implemented");
    }

    @Override
    public boolean isMisspelled(String word) {
      try {
        Dictionary dict = langToDict.get(language);  // Dictionary itself is thread-safe, so it can be cached and re-used
        if (dict == null) {
          SpellingCheckRule spellingRule = getSpellingCheckRule(language);
          dict = Dictionary.read(JLanguageTool.getDataBroker().getFromResourceDirAsUrl(((MorfologikSpellerRule)spellingRule).getFileName()));
          langToDict.put(language, dict);
        }
        Speller speller = new Speller(dict, 1);
        return !speller.isMisspelled(word);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }
  
}

    JLanguageTool lt = new JLanguageTool(lang);
    SpellingCheckRule spellRule = null;
    for (Rule r : lt.getAllActiveRules()) {
      if (r instanceof HunspellRule || r instanceof MorfologikSpellerRule) {
        spellRule = (SpellingCheckRule) r;
        // TODO: what if there's more than one spell rule?
        break;
      }
    }
    if (spellRule == null) {
      throw new RuntimeException("No spelling rule found for language " + lang.getShortCodeWithCountryAndVariant() +
        " - make sure to set 'preferredVariants' so a variant with a spell checker can be selected");
    }
    return spellRule;
  
<no_super_class>