class RuleDetails {
  private final List<Rule> rules;

  public RuleDetails(Language lang, @Nullable String ngramPath) throws IOException {
    JLanguageTool lt = new JLanguageTool(lang);
    if (ngramPath != null) {
      lt.activateLanguageModelRules(new File(ngramPath));
    }

    rules = lt.getAllRules();
  }

  @Nullable
  private Rule getRuleById(String ruleId) {
    return rules.stream()
      .filter(r -> r.getId().equals(ruleId))
      .findFirst().orElse(null);
  }

  public static void main(String[] args) throws ParseException, IOException {<FILL_FUNCTION_BODY>}
}

    Options options = new Options();
    options.addRequiredOption("l", "language", true, "Language for rules");
    options.addRequiredOption("f", "file", true, "Input file");
    options.addRequiredOption("o", "output", true, "Output file");
    options.addRequiredOption("c", "column", true, "Column in input file");
    options.addOption("n", "ngramPath", true, "Ngram path to activate ngram rules");

    CommandLine cmd = new DefaultParser().parse(options, args);

    String langCode = cmd.getOptionValue('l');
    String inputFile = cmd.getOptionValue('f');
    String outputFile = cmd.getOptionValue('o');
    String column = cmd.getOptionValue('c');
    String ngramPath = cmd.hasOption('n') ? cmd.getOptionValue('n') : null;

    RuleDetails details = new RuleDetails(Languages.getLanguageForShortCode(langCode), ngramPath);

    CSVFormat format = CSVFormat.RFC4180.withFirstRecordAsHeader();

    try (CSVParser parser = CSVParser.parse(new File(inputFile), Charset.defaultCharset(), format)) {
      try (CSVPrinter printer = new CSVPrinter(new BufferedWriter(new FileWriter(outputFile)), format)) {
        Map<String, Integer> oldHeader = parser.getHeaderMap();
        List<String> newHeader = new ArrayList<>(Collections.nCopies(oldHeader.size(), null));

        for (Map.Entry<String, Integer> entry : oldHeader.entrySet()) {
          newHeader.set(entry.getValue(), entry.getKey());
        }
        newHeader.add("description");
        newHeader.add("category");
        printer.printRecord(newHeader);

        if (!oldHeader.containsKey(column)) {
          throw new RuntimeException("Input file does not contain specified column " + column);
        }

        List<CSVRecord> records = parser.getRecords();


        records.stream().sequential().map(record -> {
          String ruleId = record.get(column);
          Rule rule = details.getRuleById(ruleId);
          List<String> transformedValues = new ArrayList<>();
          record.iterator().forEachRemaining(transformedValues::add);
          if (rule == null) {
            transformedValues.add("");
            transformedValues.add("");
          } else {
            transformedValues.add(rule.getDescription());
            transformedValues.add(rule.getCategory().getId().toString());
          }
          return transformedValues;
        }).forEachOrdered(values -> {
          try {
            printer.printRecord(values);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        });
      }
    }

  
<no_super_class>