|
1 | 1 | package org.jabref.cli; |
2 | 2 |
|
| 3 | +import java.io.IOException; |
| 4 | +import java.io.OutputStreamWriter; |
| 5 | +import java.io.Writer; |
3 | 6 | import java.nio.file.Path; |
| 7 | +import java.util.List; |
| 8 | +import java.util.Locale; |
| 9 | +import java.util.Optional; |
| 10 | +import java.util.concurrent.Callable; |
| 11 | +import java.util.stream.Collectors; |
4 | 12 |
|
5 | 13 | import org.jabref.cli.converter.CygWinPathConverter; |
| 14 | +import org.jabref.logic.importer.ParserResult; |
| 15 | +import org.jabref.logic.integrity.IntegrityCheck; |
| 16 | +import org.jabref.logic.integrity.IntegrityCheckResultCsvWriter; |
| 17 | +import org.jabref.logic.integrity.IntegrityCheckResultErrorFormatWriter; |
| 18 | +import org.jabref.logic.integrity.IntegrityCheckResultTxtWriter; |
| 19 | +import org.jabref.logic.integrity.IntegrityCheckResultWriter; |
| 20 | +import org.jabref.logic.integrity.IntegrityMessage; |
| 21 | +import org.jabref.logic.journals.JournalAbbreviationLoader; |
6 | 22 | import org.jabref.logic.l10n.Localization; |
| 23 | +import org.jabref.model.database.BibDatabaseContext; |
| 24 | + |
| 25 | +import org.slf4j.Logger; |
| 26 | +import org.slf4j.LoggerFactory; |
| 27 | +import picocli.CommandLine; |
7 | 28 |
|
8 | 29 | import static picocli.CommandLine.Command; |
9 | 30 | import static picocli.CommandLine.Mixin; |
10 | 31 | import static picocli.CommandLine.Option; |
11 | | -import static picocli.CommandLine.Parameters; |
12 | 32 |
|
13 | 33 | @Command(name = "check-integrity", description = "Check integrity of the database.") |
14 | | -class CheckIntegrity implements Runnable { |
| 34 | +class CheckIntegrity implements Callable<Integer> { |
| 35 | + |
| 36 | + private static final Logger LOGGER = LoggerFactory.getLogger(CheckIntegrity.class); |
| 37 | + |
| 38 | + @CommandLine.ParentCommand |
| 39 | + private ArgumentProcessor argumentProcessor; |
15 | 40 |
|
16 | 41 | @Mixin |
17 | 42 | private ArgumentProcessor.SharedOptions sharedOptions = new ArgumentProcessor.SharedOptions(); |
18 | 43 |
|
19 | | - @Parameters(index = "0", converter = CygWinPathConverter.class, description = "BibTeX file to check", arity = "0..1") |
| 44 | + // [impl->req~jabkit.cli.input-flag~1] |
| 45 | + @Option(names = {"--input"}, converter = CygWinPathConverter.class, description = "Input BibTeX file", required = true) |
20 | 46 | private Path inputFile; |
21 | 47 |
|
22 | | - @Option(names = {"--input"}, converter = CygWinPathConverter.class, description = "Input BibTeX file") |
23 | | - private Path inputOption; |
| 48 | + @Option(names = {"--output-format"}, description = "Output format: errorformat, txt or csv", defaultValue = "errorformat") |
| 49 | + private String outputFormat; |
24 | 50 |
|
25 | | - @Option(names = {"--output-format"}, description = "Output format: txt or csv") |
26 | | - private String outputFormat = "txt"; // FixMe: Default value? |
| 51 | + // in BibTeX it could be preferences.getEntryEditorPreferences().shouldAllowIntegerEditionBibtex() |
| 52 | + @Option(names = {"--allow-integer-edition"}, description = "Allows Integer edition", negatable = true, defaultValue = "true", fallbackValue = "true") |
| 53 | + private boolean allowIntegerEdition; |
27 | 54 |
|
28 | 55 | @Override |
29 | | - public void run() { |
| 56 | + public Integer call() { |
| 57 | + Optional<ParserResult> parserResult = ArgumentProcessor.importFile( |
| 58 | + inputFile, |
| 59 | + "bibtex", |
| 60 | + argumentProcessor.cliPreferences, |
| 61 | + sharedOptions.porcelain); |
| 62 | + if (parserResult.isEmpty()) { |
| 63 | + System.out.println(Localization.lang("Unable to open file '%0'.", inputFile)); |
| 64 | + return 2; |
| 65 | + } |
| 66 | + |
| 67 | + if (parserResult.get().isInvalid()) { |
| 68 | + System.out.println(Localization.lang("Input file '%0' is invalid and could not be parsed.", inputFile)); |
| 69 | + return 2; |
| 70 | + } |
| 71 | + |
30 | 72 | if (!sharedOptions.porcelain) { |
31 | 73 | System.out.println(Localization.lang("Checking integrity of '%0'.", inputFile)); |
32 | 74 | System.out.flush(); |
33 | 75 | } |
34 | 76 |
|
35 | | - // TODO: Implement integrity checking |
| 77 | + BibDatabaseContext databaseContext = parserResult.get().getDatabaseContext(); |
| 78 | + |
| 79 | + IntegrityCheck integrityCheck = new IntegrityCheck( |
| 80 | + databaseContext, |
| 81 | + argumentProcessor.cliPreferences.getFilePreferences(), |
| 82 | + argumentProcessor.cliPreferences.getCitationKeyPatternPreferences(), |
| 83 | + JournalAbbreviationLoader.loadRepository(argumentProcessor.cliPreferences.getJournalAbbreviationPreferences()), |
| 84 | + allowIntegerEdition |
| 85 | + ); |
| 86 | + |
| 87 | + List<IntegrityMessage> messages = databaseContext.getEntries().stream() |
| 88 | + .flatMap(entry -> integrityCheck.checkEntry(entry).stream()) |
| 89 | + .collect(Collectors.toList()); |
| 90 | + |
| 91 | + messages.addAll(integrityCheck.checkDatabase(databaseContext.getDatabase())); |
| 92 | + |
| 93 | + Writer writer = new OutputStreamWriter(System.out); |
| 94 | + IntegrityCheckResultWriter checkResultWriter; |
| 95 | + switch (outputFormat.toLowerCase(Locale.ROOT)) { |
| 96 | + case "errorformat" -> |
| 97 | + checkResultWriter = new IntegrityCheckResultErrorFormatWriter(writer, messages, parserResult.get(), inputFile); |
| 98 | + case "txt" -> |
| 99 | + checkResultWriter = new IntegrityCheckResultTxtWriter(writer, messages); |
| 100 | + case "csv" -> |
| 101 | + checkResultWriter = new IntegrityCheckResultCsvWriter(writer, messages); |
| 102 | + default -> { |
| 103 | + System.out.println(Localization.lang("Unknown output format '%0'.", outputFormat)); |
| 104 | + return 3; |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + try { |
| 109 | + checkResultWriter.writeFindings(); |
| 110 | + writer.flush(); |
| 111 | + } catch (IOException e) { |
| 112 | + LOGGER.error("Error writing results", e); |
| 113 | + return 2; |
| 114 | + } |
| 115 | + return 0; |
36 | 116 | } |
37 | 117 | } |
0 commit comments