From 7e9f5798fc871ca4dc1e54c90df777602be442e5 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Thu, 12 Jun 2025 14:34:16 +0300 Subject: [PATCH 01/13] feat(importers): add importers for ODF files --- jablib/build.gradle.kts | 9 +++ jablib/src/main/java/module-info.java | 1 + .../jabref/logic/importer/ParserResult.java | 4 ++ .../importer/fileformat/docs/OdfImporter.java | 71 +++++++++++++++++++ .../importer/fileformat/docs/OdpImporter.java | 30 ++++++++ .../importer/fileformat/docs/OdsImporter.java | 30 ++++++++ .../importer/fileformat/docs/OdtImporter.java | 30 ++++++++ .../jabref/logic/importer/util/Constants.java | 30 ++++++++ .../jabref/logic/util/StandardFileType.java | 2 + .../java/org/jabref/model/entry/BibEntry.java | 8 +++ .../fileformat/docs/OdpImporterFilesTest.java | 57 +++++++++++++++ .../fileformat/docs/OdpImporterTest.java | 32 +++++++++ .../fileformat/docs/OdsImporterFilesTest.java | 57 +++++++++++++++ .../fileformat/docs/OdsImporterTest.java | 32 +++++++++ .../fileformat/docs/OdtImporterFilesTest.java | 57 +++++++++++++++ .../fileformat/docs/OdtImporterTest.java | 32 +++++++++ 16 files changed, 482 insertions(+) create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/util/Constants.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index ece09d14ad5..e1af1363c84 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -206,6 +206,15 @@ dependencies { exclude(group = "org.apache.xmlgraphics") } + // region for document importing + implementation("org.apache.tika:tika-core:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.tika:tika-parsers-standard-package:3.2.0") { + exclude(group = "commons-logging") + } + // endregion + // Even if("compileOnly") is used, IntelliJ always adds to module-info.java. To avoid issues during committing, we use("implementation") instead of("compileOnly") implementation("io.github.adr:e-adr:2.0.0-SNAPSHOT") diff --git a/jablib/src/main/java/module-info.java b/jablib/src/main/java/module-info.java index ba63449bb8a..4efb3fd0d07 100644 --- a/jablib/src/main/java/module-info.java +++ b/jablib/src/main/java/module-info.java @@ -252,5 +252,6 @@ requires mslinks; requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; + requires org.apache.tika.core; // endregion } diff --git a/jablib/src/main/java/org/jabref/logic/importer/ParserResult.java b/jablib/src/main/java/org/jabref/logic/importer/ParserResult.java index c0a75bc4903..fd4a573cff5 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/ParserResult.java +++ b/jablib/src/main/java/org/jabref/logic/importer/ParserResult.java @@ -50,6 +50,10 @@ public static ParserResult fromErrorMessage(String message) { return parserResult; } + public static ParserResult fromEntry(BibEntry entry) { + return new ParserResult(List.of(entry)); + } + private static String getErrorMessage(Exception exception) { String errorMessage = exception.getLocalizedMessage(); if (exception.getCause() != null) { diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java new file mode 100644 index 00000000000..359ee215bbd --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java @@ -0,0 +1,71 @@ +package org.jabref.logic.importer.fileformat.docs; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import org.jabref.logic.importer.Importer; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.Property; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.SAXException; + +/** + * General importer for Open Document Format files. + */ +public abstract class OdfImporter extends Importer { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isZip(input); + } + + @Override + public ParserResult importDatabase(BufferedReader input) throws IOException { + throw new UnsupportedOperationException("OdfImporter (and descendants) does not support importDatabase(BufferedReader reader)." + + "Instead use importDatabase(Path filePath)."); + } + + @Override + public ParserResult importDatabase(Path filePath) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath.toFile())) { + AutoDetectParser parser = new AutoDetectParser(); + Metadata metadata = new Metadata(); + BodyContentHandler handler = new BodyContentHandler(); + + parser.parse(inputStream, handler, metadata); + + BibEntry entry = extractMetadata(metadata); + + return ParserResult.fromEntry(entry); + } catch (SAXException | TikaException e) { + throw new IOException("Error parsing file: " + filePath, e); + } + } + + private BibEntry extractMetadata(Metadata metadata) { + Optional title = Optional.ofNullable(metadata.get("dc:title")); + Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); + + List authors = Arrays.asList(metadata.getValues("dc:contributor")); + + return new BibEntry() + .withField(StandardField.TITLE, title) + .withField(StandardField.AUTHOR, !authors.isEmpty() ? Optional.of(String.join(" and ", authors)) : Optional.empty()) + .withField(StandardField.YEAR, date.map(Date::getYear).map(Object::toString)); + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java new file mode 100644 index 00000000000..a715e594b85 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java @@ -0,0 +1,30 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Importer for OpenDocument Impress (ODP) files. + */ +public class OdpImporter extends OdfImporter { + @Override + public String getId() { + return "odp"; + } + + @Override + public String getName() { + return "OpenDocument Impress"; + } + + @Override + public String getDescription() { + return Localization.lang("Importer for OpenDocument Impress (ODP) files"); + } + + @Override + public FileType getFileType() { + return StandardFileType.ODP; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java new file mode 100644 index 00000000000..72df33e7f7f --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java @@ -0,0 +1,30 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Importer for OpenDocument Calc (ODS) files. + */ +public class OdsImporter extends OdfImporter { + @Override + public String getId() { + return "ods"; + } + + @Override + public String getName() { + return "OpenDocument Calc"; + } + + @Override + public String getDescription() { + return Localization.lang("Importer for OpenDocument Calc (ODS) files"); + } + + @Override + public FileType getFileType() { + return StandardFileType.ODS; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java new file mode 100644 index 00000000000..efe6fdb55f6 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java @@ -0,0 +1,30 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Importer for OpenDocument Text (ODT) files. + */ +public class OdtImporter extends OdfImporter { + @Override + public String getId() { + return "odt"; + } + + @Override + public String getName() { + return "OpenDocument Writer"; + } + + @Override + public String getDescription() { + return Localization.lang("Importer for OpenDocument Writer (ODT) files"); + } + + @Override + public FileType getFileType() { + return StandardFileType.ODT; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java new file mode 100644 index 00000000000..f80752e1e7a --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java @@ -0,0 +1,30 @@ +package org.jabref.logic.importer.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +public class Constants { + public static final char[] ZIP_HEADER_MAGIC_NUMBER = {0x50, 0x4b, 0x03, 0x04}; + + public static final List ZIP_FILES_EXTENSIONS = List.of( + ".ctv6bak", + ".zip", + ".epub", + ".odt", + ".docx", + ".xlsx", + ".pptx", + ".ods", + ".odp" + ); + + public static final String DC_NAMESPACE = "http://purl.org/dc/elements/1.1/"; + + public static boolean isZip(BufferedReader input) throws IOException { + char[] header = new char[ZIP_HEADER_MAGIC_NUMBER.length]; + int nRead = input.read(header); + return nRead == ZIP_HEADER_MAGIC_NUMBER.length && Arrays.equals(header, ZIP_HEADER_MAGIC_NUMBER); + } +} diff --git a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java index 4d0bf1c0412..9d077fc1a50 100644 --- a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java +++ b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java @@ -33,7 +33,9 @@ public enum StandardFileType implements FileType { MARKDOWN("Markdown", "md"), MEDLINE("Medline", "nbib", "xml"), MEDLINE_PLAIN("Medline Plain", "nbib", "txt"), + ODP("OpenOffice Impress", "odp"), ODS("OpenOffice Calc", "ods"), + ODT("OpenOffice Writer", "odt"), PDF("PDF", "pdf"), PUBMED("Pubmed", "fcgi"), RDF("RDF", "rdf"), diff --git a/jablib/src/main/java/org/jabref/model/entry/BibEntry.java b/jablib/src/main/java/org/jabref/model/entry/BibEntry.java index 221747e5565..5d8115a4442 100644 --- a/jablib/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/jablib/src/main/java/org/jabref/model/entry/BibEntry.java @@ -969,6 +969,14 @@ public BibEntry withField(Field field, String value) { return this; } + public BibEntry withField(Field field, Optional value) { + value.ifPresent(v -> { + setField(field, v); + this.setChanged(false); + }); + return this; + } + /** * A copy is made of the parameter */ diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java new file mode 100644 index 00000000000..b363242b6d1 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.docs; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class OdpImporterFilesTest { + private static final String FILE_ENDING = ".odp"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private OdpImporter importer; + + @BeforeEach + void setUp() { + importer = new OdpImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("OdpImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("OdpImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java new file mode 100644 index 00000000000..9ed53a322f2 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OdpImporterTest { + private OdpImporter importer; + + @BeforeEach + void setUp() { + importer = new OdpImporter(); + } + + @Test + void getFormatName() { + assertEquals("OpenDocument Impress", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("odp", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.ODP, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java new file mode 100644 index 00000000000..0fa5333a645 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.docs; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class OdsImporterFilesTest { + private static final String FILE_ENDING = ".ods"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private OdsImporter importer; + + @BeforeEach + void setUp() { + importer = new OdsImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("OdsImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("OdsImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java new file mode 100644 index 00000000000..0f06937b7a6 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OdsImporterTest { + private OdsImporter importer; + + @BeforeEach + void setUp() { + importer = new OdsImporter(); + } + + @Test + void getFormatName() { + assertEquals("OpenDocument Calc", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("odc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.ODS, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java new file mode 100644 index 00000000000..5b4edfc8503 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.docs; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class OdtImporterFilesTest { + private static final String FILE_ENDING = ".odt"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private OdtImporter importer; + + @BeforeEach + void setUp() { + importer = new OdtImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("OdtImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("OdtImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java new file mode 100644 index 00000000000..e1cb53b0b0a --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.docs; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OdtImporterTest { + private OdtImporter importer; + + @BeforeEach + void setUp() { + importer = new OdtImporter(); + } + + @Test + void getFormatName() { + assertEquals("OpenDocument Writer", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("odt", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.ODT, importer.getFileType()); + } +} From ed19d6b73f95eccaf98a18077ec1c5b6a0ed68d2 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 12 Jun 2025 20:06:11 +0200 Subject: [PATCH 02/13] try with bom --- jablib/build.gradle.kts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index e1af1363c84..95b8ec239a5 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -122,9 +122,12 @@ dependencies { implementation("jakarta.ws.rs:jakarta.ws.rs-api:4.0.0") // endregion - implementation("org.slf4j:slf4j-api:2.0.17") + implementation("org.slf4j:slf4j-bom:2.0.17") + implementation("org.slf4j:slf4j-api") + // route all jcl request to sfl4j + implementation("org.slf4j:jcl-over-slf4j") // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog in the CLI and GUI) - implementation("org.slf4j:jul-to-slf4j:2.0.17") + implementation("org.slf4j:jul-to-slf4j") // route all requests to log4j to SLF4J implementation("org.apache.logging.log4j:log4j-to-slf4j:2.24.3") @@ -207,11 +210,12 @@ dependencies { } // region for document importing - implementation("org.apache.tika:tika-core:3.2.0") { - exclude(group = "commons-logging") + implementation(platform("org.apache.tika:tika-bom:3.2.0")) + implementation("org.apache.tika:tika-core") { + exclude(group = "commons-logging", module = "commons-logging") } - implementation("org.apache.tika:tika-parsers-standard-package:3.2.0") { - exclude(group = "commons-logging") + implementation("org.apache.tika:tika-parsers-standard-package") { + exclude(group = "commons-logging", module = "commons-logging") } // endregion From a3eb9f3a9227a331ffd4d5f5b37980944097de11 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 12 Jun 2025 20:08:52 +0200 Subject: [PATCH 03/13] exclude jcl --- jablib/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index 95b8ec239a5..adfe6f5aef5 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -124,8 +124,6 @@ dependencies { implementation("org.slf4j:slf4j-bom:2.0.17") implementation("org.slf4j:slf4j-api") - // route all jcl request to sfl4j - implementation("org.slf4j:jcl-over-slf4j") // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog in the CLI and GUI) implementation("org.slf4j:jul-to-slf4j") // route all requests to log4j to SLF4J @@ -213,9 +211,11 @@ dependencies { implementation(platform("org.apache.tika:tika-bom:3.2.0")) implementation("org.apache.tika:tika-core") { exclude(group = "commons-logging", module = "commons-logging") + exclude(group = "org.slf4j", module = "jcl-over-slf4j") } implementation("org.apache.tika:tika-parsers-standard-package") { exclude(group = "commons-logging", module = "commons-logging") + exclude(group = "org.slf4j", module = "jcl-over-slf4j") } // endregion From 6679f1e5ff028c01ce6a066540d5498d6a8f649f Mon Sep 17 00:00:00 2001 From: InAnYan Date: Thu, 12 Jun 2025 23:55:19 +0300 Subject: [PATCH 04/13] Revert "exclude jcl" This reverts commit a3eb9f3a9227a331ffd4d5f5b37980944097de11. --- jablib/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index adfe6f5aef5..95b8ec239a5 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -124,6 +124,8 @@ dependencies { implementation("org.slf4j:slf4j-bom:2.0.17") implementation("org.slf4j:slf4j-api") + // route all jcl request to sfl4j + implementation("org.slf4j:jcl-over-slf4j") // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog in the CLI and GUI) implementation("org.slf4j:jul-to-slf4j") // route all requests to log4j to SLF4J @@ -211,11 +213,9 @@ dependencies { implementation(platform("org.apache.tika:tika-bom:3.2.0")) implementation("org.apache.tika:tika-core") { exclude(group = "commons-logging", module = "commons-logging") - exclude(group = "org.slf4j", module = "jcl-over-slf4j") } implementation("org.apache.tika:tika-parsers-standard-package") { exclude(group = "commons-logging", module = "commons-logging") - exclude(group = "org.slf4j", module = "jcl-over-slf4j") } // endregion From 5a3d35bc51eecc30d6891b3a5a7b5c280de219f6 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Thu, 12 Jun 2025 23:57:35 +0300 Subject: [PATCH 05/13] Revert "try with bom" This reverts commit ed19d6b73f95eccaf98a18077ec1c5b6a0ed68d2. --- jablib/build.gradle.kts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index 95b8ec239a5..e1af1363c84 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -122,12 +122,9 @@ dependencies { implementation("jakarta.ws.rs:jakarta.ws.rs-api:4.0.0") // endregion - implementation("org.slf4j:slf4j-bom:2.0.17") - implementation("org.slf4j:slf4j-api") - // route all jcl request to sfl4j - implementation("org.slf4j:jcl-over-slf4j") + implementation("org.slf4j:slf4j-api:2.0.17") // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog in the CLI and GUI) - implementation("org.slf4j:jul-to-slf4j") + implementation("org.slf4j:jul-to-slf4j:2.0.17") // route all requests to log4j to SLF4J implementation("org.apache.logging.log4j:log4j-to-slf4j:2.24.3") @@ -210,12 +207,11 @@ dependencies { } // region for document importing - implementation(platform("org.apache.tika:tika-bom:3.2.0")) - implementation("org.apache.tika:tika-core") { - exclude(group = "commons-logging", module = "commons-logging") + implementation("org.apache.tika:tika-core:3.2.0") { + exclude(group = "commons-logging") } - implementation("org.apache.tika:tika-parsers-standard-package") { - exclude(group = "commons-logging", module = "commons-logging") + implementation("org.apache.tika:tika-parsers-standard-package:3.2.0") { + exclude(group = "commons-logging") } // endregion From a27c7e7c8839d471ad28eebfd21f6dfb19784d71 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Thu, 12 Jun 2025 23:58:12 +0300 Subject: [PATCH 06/13] feat(importers): add document files --- .../logic/importer/fileformat/docs/Doc.bib | 5 +++++ .../logic/importer/fileformat/docs/Doc.doc | Bin 0 -> 9216 bytes .../logic/importer/fileformat/docs/Docx.bib | 5 +++++ .../logic/importer/fileformat/docs/Docx.docx | Bin 0 -> 5414 bytes .../logic/importer/fileformat/docs/Odp.bib | 5 +++++ .../logic/importer/fileformat/docs/Odp.odp | Bin 0 -> 21809 bytes .../logic/importer/fileformat/docs/Ods.bib | 5 +++++ .../logic/importer/fileformat/docs/Ods.ods | Bin 0 -> 10251 bytes .../logic/importer/fileformat/docs/Odt.bib | 5 +++++ .../logic/importer/fileformat/docs/Odt.odt | Bin 0 -> 10027 bytes .../logic/importer/fileformat/docs/Ppt.bib | 5 +++++ .../logic/importer/fileformat/docs/Ppt.ppt | Bin 0 -> 465920 bytes .../logic/importer/fileformat/docs/Pptx.bib | 5 +++++ .../logic/importer/fileformat/docs/Pptx.pptx | Bin 0 -> 16823 bytes .../logic/importer/fileformat/docs/Xls.xls | Bin 0 -> 5632 bytes .../logic/importer/fileformat/docs/Xlsx.xlsx | Bin 0 -> 5505 bytes .../logic/importer/fileformat/docs/Xsl.bib | 5 +++++ .../logic/importer/fileformat/docs/Xslx.bib | 5 +++++ 18 files changed, 45 insertions(+) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.doc create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.docx create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odp.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odp.odp create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.ods create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.odt create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.ppt create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.pptx create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xls.xls create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xlsx.xlsx create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xslx.bib diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib new file mode 100644 index 00000000000..135044d0f7f --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib @@ -0,0 +1,5 @@ +@article{, + author = {JabRef}, + year = {2025}, + title = {DOC Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.doc b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.doc new file mode 100644 index 0000000000000000000000000000000000000000..2c598fe5da84820d1dded9476853bbaefc9618a5 GIT binary patch literal 9216 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 LLXphcw0Xc4BKa|tAq=n3MqBJt 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.bib new file mode 100644 index 00000000000..6ce2ab4b8b3 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.bib @@ -0,0 +1,5 @@ +@article{, + author = {JabRef}, + year = {2025}, + title = {ODS Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.ods b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ods.ods new file mode 100644 index 0000000000000000000000000000000000000000..02e126ea634f6606147ee5983ea9fba1583390e3 GIT binary patch literal 10251 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib new file mode 100644 index 00000000000..0904e3ff377 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib @@ -0,0 +1,5 @@ +@article{, + author = {JabRef}, + year = {2025}, + title = {ODT Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.odt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.odt new file mode 100644 index 0000000000000000000000000000000000000000..93b42672c8089dd0149161dd16d0cf0fc4224a72 GIT binary patch literal 10027 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%0Ayqtw$2DfsC+${Du>v_Y) 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 w^7r|4uznvn|AX?6p?mrw*0 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 Ie6&ywleDL7CS(VFjrY{ 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 DD0E27 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib new file mode 100644 index 00000000000..1df78a101a1 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib @@ -0,0 +1,5 @@ +@article{, + author = {JabRef}, + year = {2025}, + title = {XLS Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xslx.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xslx.bib new file mode 100644 index 00000000000..c3a4e80e381 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xslx.bib @@ -0,0 +1,5 @@ +@article{, + author = {JabRef}, + year = {2025}, + title = {XLSX Document} +} From 06fbb3585ee64475b75eb4c097219d955570d6d4 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Fri, 13 Jun 2025 00:00:26 +0300 Subject: [PATCH 07/13] fix(build): change package name to just `tika-parsers` --- jablib/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index e1af1363c84..8c0c0579a65 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -210,7 +210,7 @@ dependencies { implementation("org.apache.tika:tika-core:3.2.0") { exclude(group = "commons-logging") } - implementation("org.apache.tika:tika-parsers-standard-package:3.2.0") { + implementation("org.apache.tika:tika-parsers:3.2.0") { exclude(group = "commons-logging") } // endregion From 8769276a0f2dddfafa7d08af7f8f3682a52cbfb5 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Sun, 15 Jun 2025 00:53:48 +0300 Subject: [PATCH 08/13] feat(importers/docs): refactor ODF imports + add MsOffice importers and tests --- .../jabref/logic/importer/TikaImporter.java | 4 + .../importer/fileformat/docs/OdfImporter.java | 71 ------------------ .../fileformat/microsoft/DocImporter.java | 40 ++++++++++ .../fileformat/microsoft/DocxImporter.java | 40 ++++++++++ .../fileformat/microsoft/PptImporter.java | 40 ++++++++++ .../fileformat/microsoft/PptxImporter.java | 40 ++++++++++ .../fileformat/microsoft/XlsImporter.java | 40 ++++++++++ .../fileformat/microsoft/XlsxImporter.java | 40 ++++++++++ .../importer/fileformat/odf/OdfImporter.java | 37 +++++++++ .../fileformat/{docs => odf}/OdpImporter.java | 0 .../fileformat/{docs => odf}/OdsImporter.java | 0 .../fileformat/{docs => odf}/OdtImporter.java | 0 .../microsoft/DocImporterFilesTest.java | 58 ++++++++++++++ .../fileformat/microsoft/DocImporterTest.java | 32 ++++++++ .../microsoft/DocxImporterFilesTest.java | 57 ++++++++++++++ .../microsoft/DocxImporterTest.java | 33 ++++++++ .../microsoft/PptImporterFilesTest.java | 57 ++++++++++++++ .../fileformat/microsoft/PptImporterTest.java | 32 ++++++++ .../microsoft/PptxImporterFilesTest.java | 57 ++++++++++++++ .../microsoft/PptxImporterTest.java | 32 ++++++++ .../microsoft/XlsImporterFilesTest.java | 57 ++++++++++++++ .../fileformat/microsoft/XlsImporterTest.java | 32 ++++++++ .../microsoft/XlsxImporterFilesTest.java | 57 ++++++++++++++ .../microsoft/XlsxImporterTest.java | 32 ++++++++ .../{docs => odf}/OdpImporterFilesTest.java | 0 .../{docs => odf}/OdpImporterTest.java | 0 .../{docs => odf}/OdsImporterFilesTest.java | 0 .../{docs => odf}/OdsImporterTest.java | 0 .../{docs => odf}/OdtImporterFilesTest.java | 0 .../{docs => odf}/OdtImporterTest.java | 0 .../{docs/Ppt.bib => DocImporterTest1.bib} | 3 +- .../{docs/Doc.doc => DocImporterTest1.doc} | Bin .../importer/fileformat/DocImporterTest2.bib | 5 ++ .../importer/fileformat/DocImporterTest2.doc | Bin 0 -> 26624 bytes .../{docs/Docx.bib => DocxImporterTest1.bib} | 3 +- .../Docx.docx => DocxImporterTest1.docx} | Bin 5414 -> 5418 bytes .../importer/fileformat/DocxImporterTest2.bib | 5 ++ .../fileformat/DocxImporterTest2.docx | Bin 0 -> 12101 bytes .../{docs/Odp.bib => OdpImporterTest1.bib} | 2 +- .../{docs/Odp.odp => OdpImporterTest1.odp} | Bin .../importer/fileformat/OdpImporterTest2.bib | 5 ++ .../importer/fileformat/OdpImporterTest2.odp | Bin 0 -> 23854 bytes .../{docs/Ods.bib => OdsImporterTest1.bib} | 2 +- .../{docs/Ods.ods => OdsImporterTest1.ods} | Bin .../importer/fileformat/OdsImporterTest2.bib | 5 ++ .../importer/fileformat/OdsImporterTest2.ods | Bin 0 -> 2687 bytes .../{docs/Odt.bib => OdtImporterTest1.bib} | 2 +- .../{docs/Odt.odt => OdtImporterTest1.odt} | Bin .../importer/fileformat/OdtImporterTest2.bib | 5 ++ .../importer/fileformat/OdtImporterTest2.odt | Bin 0 -> 4478 bytes .../importer/fileformat/PptImporterTest1.bib | 4 + .../{docs/Ppt.ppt => PptImporterTest1.ppt} | Bin .../importer/fileformat/PptImporterTest2.bib | 5 ++ .../importer/fileformat/PptImporterTest2.ppt | Bin 0 -> 84992 bytes .../importer/fileformat/PptxImporterTest1.bib | 4 + .../Pptx.pptx => PptxImporterTest1.pptx} | Bin .../importer/fileformat/PptxImporterTest2.bib | 5 ++ .../fileformat/PptxImporterTest2.pptx | Bin 0 -> 32087 bytes .../{docs/Xsl.bib => XlsImporterTest1.bib} | 3 +- .../{docs/Xls.xls => XlsImporterTest1.xls} | Bin .../importer/fileformat/XlsImporterTest2.bib | 5 ++ .../importer/fileformat/XlsImporterTest2.xls | Bin 0 -> 17408 bytes .../{docs/Xslx.bib => XlsxImporterTest1.bib} | 3 +- .../Xlsx.xlsx => XlsxImporterTest1.xlsx} | Bin .../importer/fileformat/XlsxImporterTest2.bib | 5 ++ .../fileformat/XlsxImporterTest2.xlsx | Bin 0 -> 8327 bytes .../logic/importer/fileformat/docs/Doc.bib | 5 -- .../logic/importer/fileformat/docs/Pptx.bib | 5 -- 68 files changed, 877 insertions(+), 92 deletions(-) create mode 100644 jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java delete mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java rename jablib/src/main/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdpImporter.java (100%) rename jablib/src/main/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdsImporter.java (100%) rename jablib/src/main/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdtImporter.java (100%) create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdpImporterFilesTest.java (100%) rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdpImporterTest.java (100%) rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdsImporterFilesTest.java (100%) rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdsImporterTest.java (100%) rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdtImporterFilesTest.java (100%) rename jablib/src/test/java/org/jabref/logic/importer/fileformat/{docs => odf}/OdtImporterTest.java (100%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Ppt.bib => DocImporterTest1.bib} (57%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Doc.doc => DocImporterTest1.doc} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.doc rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Docx.bib => DocxImporterTest1.bib} (58%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Docx.docx => DocxImporterTest1.docx} (63%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.docx rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Odp.bib => OdpImporterTest1.bib} (85%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Odp.odp => OdpImporterTest1.odp} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdpImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdpImporterTest2.odp rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Ods.bib => OdsImporterTest1.bib} (85%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Ods.ods => OdsImporterTest1.ods} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdsImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdsImporterTest2.ods rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Odt.bib => OdtImporterTest1.bib} (85%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Odt.odt => OdtImporterTest1.odt} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.odt create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.bib rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Ppt.ppt => PptImporterTest1.ppt} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.ppt create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.bib rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Pptx.pptx => PptxImporterTest1.pptx} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.pptx rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Xsl.bib => XlsImporterTest1.bib} (57%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Xls.xls => XlsImporterTest1.xls} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.xls rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Xslx.bib => XlsxImporterTest1.bib} (58%) rename jablib/src/test/resources/org/jabref/logic/importer/fileformat/{docs/Xlsx.xlsx => XlsxImporterTest1.xlsx} (100%) create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsxImporterTest2.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsxImporterTest2.xlsx delete mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib delete mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.bib diff --git a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java new file mode 100644 index 00000000000..317091dda3e --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java @@ -0,0 +1,4 @@ +package org.jabref.logic.importer; + +public class TikaImporter { +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java deleted file mode 100644 index 359ee215bbd..00000000000 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdfImporter.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jabref.logic.importer.fileformat.docs; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Optional; - -import org.jabref.logic.importer.Importer; -import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.importer.util.Constants; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.FileType; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; - -import org.apache.tika.exception.TikaException; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.metadata.Property; -import org.apache.tika.parser.AutoDetectParser; -import org.apache.tika.sax.BodyContentHandler; -import org.xml.sax.SAXException; - -/** - * General importer for Open Document Format files. - */ -public abstract class OdfImporter extends Importer { - @Override - public boolean isRecognizedFormat(BufferedReader input) throws IOException { - return Constants.isZip(input); - } - - @Override - public ParserResult importDatabase(BufferedReader input) throws IOException { - throw new UnsupportedOperationException("OdfImporter (and descendants) does not support importDatabase(BufferedReader reader)." - + "Instead use importDatabase(Path filePath)."); - } - - @Override - public ParserResult importDatabase(Path filePath) throws IOException { - try (InputStream inputStream = new FileInputStream(filePath.toFile())) { - AutoDetectParser parser = new AutoDetectParser(); - Metadata metadata = new Metadata(); - BodyContentHandler handler = new BodyContentHandler(); - - parser.parse(inputStream, handler, metadata); - - BibEntry entry = extractMetadata(metadata); - - return ParserResult.fromEntry(entry); - } catch (SAXException | TikaException e) { - throw new IOException("Error parsing file: " + filePath, e); - } - } - - private BibEntry extractMetadata(Metadata metadata) { - Optional title = Optional.ofNullable(metadata.get("dc:title")); - Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); - - List authors = Arrays.asList(metadata.getValues("dc:contributor")); - - return new BibEntry() - .withField(StandardField.TITLE, title) - .withField(StandardField.AUTHOR, !authors.isEmpty() ? Optional.of(String.join(" and ", authors)) : Optional.empty()) - .withField(StandardField.YEAR, date.map(Date::getYear).map(Object::toString)); - } -} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java new file mode 100644 index 00000000000..00f3a0a6224 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports old Microsoft Word 97-2003 files (`.doc`). + */ +public class WordOldImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isOleCompound(input); + } + + @Override + public String getId() { + return "doc"; + } + + @Override + public String getName() { + return "Microsoft Word 97-2003"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft Word 97-2003 files (doc)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.DOC; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java new file mode 100644 index 00000000000..40e9b553310 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports Microsoft Word 2007-365 files (`.docx`). + */ +public class WordImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isZip(input); + } + + @Override + public String getId() { + return "docx"; + } + + @Override + public String getName() { + return "Microsoft Word 2007-365"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft Word 2007-365 files (docx)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.DOCX; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java new file mode 100644 index 00000000000..74dc93cd242 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports old Microsoft PowerPoint 97-2003 files (`.ppt`). + */ +public class PowerpointOldImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isOleCompound(input); + } + + @Override + public String getId() { + return "ppt"; + } + + @Override + public String getName() { + return "Microsoft PowerPoint 97-2003"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft PowerPoint 97-2003 files (ppt)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.PPT; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java new file mode 100644 index 00000000000..e5c6c7864b1 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports Microsoft PowerPoint 2007-365 files (`.pptx`). + */ +public class PowerpointImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isZip(input); + } + + @Override + public String getId() { + return "pptx"; + } + + @Override + public String getName() { + return "Microsoft PowerPoint 2007-365"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft PowerPoint 2007-365 files (pptx)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.PPTX; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java new file mode 100644 index 00000000000..89e793ce6b1 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports old Microsoft Excel 97-2003 files (`.xls`). + */ +public class ExcelOldImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isOleCompound(input); + } + + @Override + public String getId() { + return "xls"; + } + + @Override + public String getName() { + return "Microsoft Excel 97-2003"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft Excel 97-2003 files (xls)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.DOC; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java new file mode 100644 index 00000000000..421090c59e5 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +/** + * Imports Microsoft Excel 2007-365 files (`.xlsx`). + */ +public class ExcelImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isZip(input); + } + + @Override + public String getId() { + return "xlsx"; + } + + @Override + public String getName() { + return "Microsoft Excel 2007-365"; + } + + @Override + public String getDescription() { + return Localization.lang("Import Microsoft Excel 2007-365 files (xlsx)"); + } + + @Override + public FileType getFileType() { + return StandardFileType.XLSX; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java new file mode 100644 index 00000000000..9818df8e107 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java @@ -0,0 +1,37 @@ +package org.jabref.logic.importer.fileformat.docs; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import org.jabref.logic.importer.Importer; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.Property; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.SAXException; + +/** + * General importer for Open Document Format files. + */ +public abstract class OdfImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.isZip(input); + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java similarity index 100% rename from jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdpImporter.java rename to jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java similarity index 100% rename from jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdsImporter.java rename to jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java similarity index 100% rename from jablib/src/main/java/org/jabref/logic/importer/fileformat/docs/OdtImporter.java rename to jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java new file mode 100644 index 00000000000..53a873ffd7b --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java @@ -0,0 +1,58 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.fileformat.odf.OdpImporter; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class WordOldImporterFilesTest { + private static final String FILE_ENDING = ".doc"; + private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private WordOldImporter importer; + + @BeforeEach + void setUp() { + importer = new WordOldImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java new file mode 100644 index 00000000000..7488d1c4f88 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class WordOldImporterTest { + private WordOldImporter importer; + + @BeforeEach + void setUp() { + importer = new WordOldImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("doc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOC, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java new file mode 100644 index 00000000000..39e81478156 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class DocxImporterFilesTest { + private static final String FILE_ENDING = ".doc"; + private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java new file mode 100644 index 00000000000..2dcda2cd42b --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java @@ -0,0 +1,33 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.importer.fileformat.odf.OdpImporter; +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class WordImporterTest { + private OdpImporter importer; + + @BeforeEach + void setUp() { + importer = new OdpImporter(); + } + + @Test + void getFormatName() { + assertEquals("OpenDocument Impress", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("odp", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.ODP, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java new file mode 100644 index 00000000000..a6cf1dc9ddc --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class PptImporterFilesTest { + private static final String FILE_ENDING = ".doc"; + private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java new file mode 100644 index 00000000000..0ea71d8d392 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PptImporterTest { + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("doc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOC, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java new file mode 100644 index 00000000000..dc81f892048 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class PptxImporterFilesTest { + private static final String FILE_ENDING = ".docx"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocxImporter importer; + + @BeforeEach + void setUp() { + importer = new DocxImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocxImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java new file mode 100644 index 00000000000..dede8157169 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PptxImporterTest { + private XlsxImporter importer; + + @BeforeEach + void setUp() { + importer = new XlsxImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Excel 2007-365", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("xlsx", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.XLSX, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java new file mode 100644 index 00000000000..56c42d294f7 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class DocImporterFilesTest { + private static final String FILE_ENDING = ".doc"; + private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java new file mode 100644 index 00000000000..776b716c6ec --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class XlsImporterTest { + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("doc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOC, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java new file mode 100644 index 00000000000..3aa182f0482 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class XlsxImporterFilesTest { + private static final String FILE_ENDING = ".docx"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocxImporter importer; + + @BeforeEach + void setUp() { + importer = new DocxImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocxImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java new file mode 100644 index 00000000000..8b8997eea23 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class XlsxImporterTest { + private DocxImporter importer; + + @BeforeEach + void setUp() { + importer = new DocxImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 2007-365", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("docx", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOCX, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterFilesTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdpImporterTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterFilesTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdsImporterTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterFilesTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java similarity index 100% rename from jablib/src/test/java/org/jabref/logic/importer/fileformat/docs/OdtImporterTest.java rename to jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest1.bib similarity index 57% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.bib rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest1.bib index 135044d0f7f..07e67e9c1fd 100644 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.bib +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest1.bib @@ -1,5 +1,4 @@ -@article{, - author = {JabRef}, +@misc{, year = {2025}, title = {DOC Document} } diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.doc b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest1.doc similarity index 100% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.doc rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest1.doc diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.bib new file mode 100644 index 00000000000..cea00174be1 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef}, + year = {2025}, + title = {DOC Document from MIcrosoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.doc b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocImporterTest2.doc new file mode 100644 index 0000000000000000000000000000000000000000..0c2d3a7240bf6775b248780a3cacdaac8587b3e1 GIT binary patch literal 26624 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 NOs8fWt^aKd{0|Hh3Vi?o literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest1.bib similarity index 58% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.bib rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest1.bib index 954661289f0..b352c379580 100644 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.bib +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest1.bib @@ -1,5 +1,4 @@ -@article{, - author = {JabRef}, +@misc{, year = {2025}, title = {DOCX Document} } diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.docx b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest1.docx similarity index 63% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Docx.docx rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest1.docx index 8b50db6c994e9b2374b08adfd10fadb54d9d12f2..356956ccb4b7dbc008d9bc36d716ed3376717a43 100644 GIT binary patch delta 783 zcmZ3cwMvUOz?+#xgn@&DgTZzAxsAMXjLblKvL2&K{pq|z1_FD&Yb)IsR)44{GI4>} zk(Dc^a%sIfTRQE*B#UWpKm7Q8i;rc6#g}c?#`EreeOFPm#w(vcXydHq8eC3K7?+ox ztC+axYSFv?3Cm3$T54wVX<9WpO@5Q<n`F@j_f+_P;N#%7yT0vW`MyW_>?`rK@ zaX@2-qWRV}9cC-*bv7uJxN{vSl;A65o%O^;IET0PqUEB^seabp7f)Q0d?Mn^DO#|$ zK*Z(8s;dgxUq3V^=S>m4tj@^4RD4sgyy)we_QQ%6U*=r-BLDE~qpyd1Um54^?_xT2 z?75qeR%6Bq+vEvbp6Z=R&$o&`7bw>L@c@5&orwNoi_Yqk3;vrPtFONoeb{VWYTC{0 zq(?F$Q++ZvAD*^{*(XjY&g9wQ&1uiq&zrlX`HhzMqA!PZY7Z;aTT1q`-&nf%RnOn_ zCI2p+Gxl2aB5g@`<7%D6^Kag!GKX*R&b_|s=Rd|(w13Vc;J-o)yFdeArBM=KC zYi4kqY$&Xx0J5PhWmWDKpxktzc`_(!Bv~gLvdZzJ89I4^ur#CjgQz?+#xgn@&DgJGrjnT@=1jLblKvL2&K{lUCL20VM;Yp=TFealE-wbwM1*RLL%9>e1h=Z z&0L8meHRub<*cgT79q4tJ^DbP08b%bn?VxCI^NowmWwv4E}pwoC-fPQ#L)?ke1|e* zzB$!glnU6n@Am=2@KbYUPj1*e!8=6C;Et+Bww z(p)H*^$5e~HI8?tWY0YRuVmYt#U@;f8s&NZ8bq}P%6xr%@Nsz4|2_5Vd1vnk$UGY- zByD^lq%iXhpY$iT4V7+3wr!E0H?6w<>l+o>ko88&w{+fIGMBk=`efCegSYxV8Grjf zao(eX64RjU2U^+|AAWtiv`_oi($ed@{`_Oinl*9Pkz;MMc`n_&UGnxUSJbui2PVAl zdh+^>|FQ;nvvUZguCpv)WMFu~#K6aZ5;dD2GG#&H#*gJHD2_I(u}XslHoLGTGJ!=_ zaGZxQs<@*dQrCGZA&g+YIEd61fi)0gl7-ATfyP9Et(?3_$P66uw}qq`FHHU}BoF3E z3QIHEPBs-*0`sDPJkiNz!rJm6eH%iAoK=|^7;dpLFbFar1LMgDgcZPQxVm_RrUKPW z;$&dpM^?fxee!={Ik2e;BGQbRlWjy4!Mp?@@7UxT5d|=BK9J`$dAEoP*tED=f3M{L X1ILezfk7C>w8fMEiKwv!2!R9v)tVbY diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.bib new file mode 100644 index 00000000000..002e76e343f --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef}, + year = {2025}, + title = {DOCX Document from MIcrosoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.docx b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/DocxImporterTest2.docx new file mode 100644 index 0000000000000000000000000000000000000000..9b10ae2592e5f77cd4a3724e9c3e45aa3ebc2f2d GIT binary patch literal 12101 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

L2a>@k86{`o`bm!58@I8O3@L76}%th+41`4 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest1.bib similarity index 85% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest1.bib index 0904e3ff377..afb4c91d8c6 100644 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.bib +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest1.bib @@ -1,4 +1,4 @@ -@article{, +@misc{, author = {JabRef}, year = {2025}, title = {ODT Document} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.odt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest1.odt similarity index 100% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Odt.odt rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest1.odt diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.bib new file mode 100644 index 00000000000..22fc748866b --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef and ruslan}, + year = {2025}, + title = {ODT Document from MIcrosoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.odt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/OdtImporterTest2.odt new file mode 100644 index 0000000000000000000000000000000000000000..15c1c20b93b20db64b36aa1fb551d99f554aef25 GIT binary patch literal 4478 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.bib new file mode 100644 index 00000000000..85eb4724bed --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.bib @@ -0,0 +1,4 @@ +@misc{, + year = {2025}, + title = {PPT Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.ppt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.ppt similarity index 100% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Ppt.ppt rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest1.ppt diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.bib new file mode 100644 index 00000000000..67c2871da10 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef}, + year = {2025}, + title = {PPT Document from Microsoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.ppt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptImporterTest2.ppt new file mode 100644 index 0000000000000000000000000000000000000000..12f8474f7d5f8eb6ec3d9b7308eafdac44a1a446 GIT binary patch literal 84992 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 Y`50?`R|Gx$P3(uPsr2qf` literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.bib new file mode 100644 index 00000000000..978b1e0cc11 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.bib @@ -0,0 +1,4 @@ +@misc{, + year = {2025}, + title = {PPTX Document} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.pptx b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.pptx similarity index 100% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.pptx rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest1.pptx diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.bib new file mode 100644 index 00000000000..98f7f950942 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef}, + year = {2025}, + title = {PPTX Document from Microsoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.pptx b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PptxImporterTest2.pptx new file mode 100644 index 0000000000000000000000000000000000000000..f9b0190d5445adeaa749bb0ea07926ab611402b6 GIT binary patch literal 32087 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 c`ClI?RpjA8>Io<)TF^rgl=5od{^Fk literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest1.bib similarity index 57% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest1.bib index 1df78a101a1..3a3a953f7d6 100644 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xsl.bib +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest1.bib @@ -1,5 +1,4 @@ -@article{, - author = {JabRef}, +@misc{, year = {2025}, title = {XLS Document} } diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xls.xls b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest1.xls similarity index 100% rename from jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Xls.xls rename to jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest1.xls diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.bib new file mode 100644 index 00000000000..dffa8b8129e --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.bib @@ -0,0 +1,5 @@ +@misc{, + author = {JabRef}, + year = {2025}, + title = {XLS Document from Microsoft Office} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.xls b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/XlsImporterTest2.xls new file mode 100644 index 0000000000000000000000000000000000000000..ce8d26b1e80e617d7ce7713a402ce263b8235c18 GIT binary patch literal 17408 zcmeHOeQXrR6@PcW^PRuIUzl&$7!0;Cj(ulb5<(6z6ljkRfh$ts$U5vhe6{hRdw>FKyI>R)j=?fM}(NMn$QbRB5)qH+y@x zyEk`%wn~(0_cXIRZ)V=_&6_uGXJ+SK`+e25XJ43ioh;YGR74-EB~)ynJMgUN=}JPr zs&Z1lFUB)S_Vqc^K#A8&+3i_+^A?gm(~n=pYrxM-B~zhLun2+5jnT zx~33U(Oe->wTNp(yq2m-9phia#?_FJ$U%=d*NMC*MO-i98HgQp!NDzhQ&8Hej^0Ab zOW$Q<~*Dy$3X$9)GS*^o*Y7sye}M7lDAH2o;psNohQeEK9^~fwNsK) zXOU|jxoLL&()uMWOO~|tHm&Jt)Dt~Ti(HH07Z>OR({_KbvfQbPNIg!V%T zO@@0yQtmkkO~y}F?gdHR|26K<3>dT0dj6$^_7e&1f`s;>gl24qj$yz*vpHV=EkUm-G5*lM{c-=Tw05S)|^AD(J)NovNSE9 z(Kb99?Tu+=-4Q$ro5XyB`7!OQI;|u_OYXDKOc)hfx#Q0p+RL6ptnjEN^;uEvtVGDWU19?Xh-shkAJj+Q+@yXq=Uhz8tPaY6bbIjT$hbS0b#ZKK#NoObKd7sUmVvIeA>+$d&7N zR5w3sLtJe@&pH{T$_(Pm1*tCp;>&`#!;z0}{!tE6Z3gk@f-EZl;?IHEVqHrMfEcaI=YRjlkIP%K z$P6N}uEqi&M(gtVFI~DM2U%dBLNC$6`=6BnwUyzfDxjqzV=Ea4=1vnBl=ETttn zOIVSW<$V^GM#~|(eWYE^a;eS|He+SkU}0&r6Qa|nPs>?0=qzC&R+dc`mPV^UW2Z^Z za+%H&_F!eX(!$bc14MgIUY4_5uCqk%TUoYSSQ>kr=-}DSGM2^ENJSe${o~#T%)RZH zuNKh;3Q>RNrRT=ZqWYWP2{!yZMa6nA&%ngB44Wo>BSWD?G&Vf$J!)p>tW(RV3+#q4 zjT%85!bB=cF-)ikt8$)9G0Qu5w8<1d|MLiG?2BoJ$Q&CRQynO5OnFVI5>slzS%Ecr zY1crwZ&2w94-Jib$1GCKR!bq(048>QG>Bg(PvncK&=(P(9Ie=dX0uXW8mSi!?Hd@LSV;4AER-wJ{_K#-jtW3I4 zXPKprOZB482*vT^d2AmY&eUj4dQhX)Qp2N`=hQG`)zJM^xoPwu_8~)wSp2Zk9Ue`L zdpDaIIajHbw24NsY03RQEc!kMF%CoH-4JFJw!r&pJdNg_=Z;Rh4-Z=A+8m3)K-ZYL zI_9Y^+6;xoEGByKy{w4>O6OFLd3(v0aHu~zykEhL-y&pDC3Lz4!m!0hA>@7tr_J=m z?7j#duKQ~mGd4kwOLut_&T=djGOXd{tgNdftTj)UhqW5`{!g#N9+dM?jJFCl(QBs*$Ryw zg!OSpXNS9*(xz+N>4Cu4|J&g{1JjWoQz}vx=TN#HPu^Z9WiQGQ*-KnhS+> z)f9MZPW0Tla|V~HrF8eDrF8eDr6!yu^Z*s_7)gkp{)Po|78vgk?a%FNqibhhC>o&4 z!Gx@9*HXG1T1uBgOR;NwFzJTgmYPLyyU__d(c*Y!xz6fh16@Pz?r35Nnrb)KDVm9n z>4sG#&}FQvTnl$FgNMK%mf)VZ>=qQw6%1I_TCcl=DVcTzxTU(!&|0de*sx~OS}NZY ziVw4M(wu0(ETppx-gpoA$1#$0|0HvsY-&QcpheTuof zlSr$Rs0+R~ZrmV$L?wSJ1v*M|m_&$xePohOoH#)!K>kS(;MM#HlOllTpG5G}6I4MP z<}+aN?tySP(aw8b;tN`FrTBtY1|O@tnQ*pf>(C;dJ1-u~*d{Xw3e}#J(WnSX#GI1?LtKqx( z(p(9Vk%g9H$Dg4FKE|ji6_#Tbg1hV56Q}NcxMQI5x$k*t#qt-gw1M^p0^23$Z$V&d z-ig5WiA_+EcMSJxgee3b59bkh=XM&Q1_2{a)VqmFi}1V@;gR5OWn-*wpU15w;J*|D5*3!HioUOTOv@bkF>p-K?*UN)% zUv-G*Q^z{_Ic=GoYhShoYz^2Nur*+7z}A4R0b2vM25b%38n88BYvBJ{1BKTA&daY} zo@$+6Iq@{s|1BT>h}Zwe5qNut*Z;iX$0yL%A@J$6AOf$yyAgQ3--E#G{}=-A6X@%G z-YejX>+q%D7ojrq+O)(SK`w4Woy9JfUN;r1GWZi z4cHp6HDGJN)_|=6TLZQRYz=&p26zR{3vB)t&g*ji#~`ooc@56r+WDVZd}M*9^f%E6!J{Msg0-u_}ff!ndz>9g#{}%$^?d!AC zz%K00@L4hihi3WzW_(cgUamTFJ9O#Ujw-zzYiB)h`=Ur#BJOjYv_aqx>dAY)Wv1=t2KF@J_H}lm%|}LLg#r-a|NnRW51&B!%K^16UVQm8rEA$WuGobdY4iuX zVSR+}S!v8ylr1ND{N~4QC5g_erSnJ}gsUxw=RG9_ay|)tCU%T2ZY`TmPt-@KJOws4 zSmwqx9wm{a7ix|9qLIuY*32BA+SE*=eh90f)-6|IlfVdlf~HGmq_f@HY)LyivLy|B@G)iv$%>`QsJ zGi0?4QB-m2gXd1Xd`g?@x2WH~OBD-haIk*mf9+%cF>;#xaCh}+;EL%X7yt5@a6+Zb zg+I6ikxCZ1qzXyt^FfOTN4@yDRL5`!>k)rjP10?U!Fhb5+zo0{dzul9-!>$@0rg-O zJe>aqHu2W)7{T6y;W{^nd{C+xn-Q7MUIcdo^fFN{^D^!&)=je}6m^=ueRT^DZb5f< zNC41ZXjreq%Ww?;MHS96EI19#Jitz#JlsF-|I+V&m~(%6^>WB#^)6oQ$bF^jDA?KL z!VCOIDn2qw&2-v9A6%GZcY-tlq7O>}BtY^He@AF(`~5%2neJbL&xH z5EW5Hl1gTT8umUmShPH^M3{V}wObKc)hGs zK$sKV$pwXumYt}5m1T~H7`>mFwbO_1aEz% zY`<<{jIJ`+!N;&Tn&L%xMEW~P_-v-gz(@dqDLi!jppmZ=kB_T|qou2>E8(B|Gc_6FR1W4y~AYUMe)+CP&e`h8(5cJt~)cN(B0cM z)wi)2;55|k^!~FivoYxN8)h+2)$n7IGW)ya%%!hIBpHz}-o14n@P}mb$fcWc-(If< z4xVo(Ri_{TT9pPB`su2jH69dpt;FLLq76U}aaG8VSd6f=#h1L`WpP%66uAK>ctyhotDZ?Cc*hx#C)63CtF z-+O3^i^*w^X9 z@?S$HN<>5Hj9%gq1ya={HJCqnI_&xQYK3-#(q+OrrcZZB1{UBea?gUiIrIqGLe)sw zH<2l$+B6K;$Ni@AtKez51=MXd^;%L>ZP`4ujaJvrJ!M(ZJsfNm-|~3Spyr&J_8Nso zKJH3hts7Wlp-~IuTr44?p^3PIsvDO;oumB+oUU#iQA23ePbpfG=0nZ~t}(aWqH^=t zK>^Sryj`Y3$;;c!=DmrSnv!)JcZ&;mVuNwOV7bAXVpA^3C?{U9G_iy#d!*vbH}(o% zt?{Uu`x%voHm)*i{9~8ScY3yGwc2+owT(BRq*C$S97w(I_%jNMS7@_SPT85H9(0*$ ziCy(VQX_^!C0p`&c-(VM?dVS(LaO7A#YWmJQ#0S@&;)3Zs+I#HLe~q5tLT%XQpqBV z9-d_7$0ylXw-*$;szYA~6imgoYYDT5IU1g@Hy;cU)uXkSCsi&68AQxs5?6}tk~8!r zq@c~fIOv|>t>jDNT?~1xbhoV&-yeyyoQe$`uD1!=Bkd@J#c_g8G#Z1Cg6BgGS3lm? z=IaZk4~X_nVoE7AT4z`w0B2E=1D9S7hOv4|KsVEhpBeW)PXXt-qWEp05G4=CLIWAf zI?aNPP-C51GtEUix3tl;5{V{Ln`gS#JjAQZ#-n7@=D)J%G${#4Q%vnUxhll-Wm=LSHRNYkDA%m(r~*z8N# zg0zy*40$>Q(Cp%OdVSBA3l zQ^U|wHpZh}mnFg0A|Ka82GOPv=~R0qGEhnkS4?Dk7L($Kf%8GhLr6}9?j@DGX`CZ& zk0f>5QwcXk#p*V^sz=-sPnr!I_7t^N2-V!1XBt9zOXV$@D7Ww=fiZ+LtA>;VdN`-8iG}0C?hHo0W0{oB`N+Lui(GyM9!lJZCu9C@P z(nvV1$B7t>bz3x}EQ8Yw73++zoPdVjIB|-%t#96(obpm>ltt&*Nqf*E zliq!>5eZ#lj_*_IWXL7$qoNL9Oef_i(ySn7fSj9#S%Lzd^3ySV!$|=K2b8p^f8k4d zgcHxYq*q$alvlmlRr4r1VpDUEnr`;UB8N}>{z|~u87m=Sklh8-%?4Q`59z2bv)nqW zfvgMkj=xFOJWzks^JuHXVT=|%+%TZX45`?-?_}r3u)SgI4T7CuSjy{$X|bIYmlqZ| zpv%d;X1#r#0n)`0Gn3jT>e9rBDX4aERU{4e`(=5ow=!%}#$8d_Hg9Zqrl7=TMqN`X zyQZMVV@Hsjvd6nf?udE^pQc$7>(0&RM2pzrGOZA{VT~6!W#2TlRQ2hF*A3(M_@w|L zh?$sE_cr{jiVE~MiMfcztd*J0qUH;l?uIm%@Etb%U_scVjiPU zsd?&a+5J(q;hF86{rX}ct^Mv$?4)XCo`k3E>Cw^FOR}Y>CmZUC)U$I`)aeIwG1Ui^ zU##|-<19jPuMQC&W_R;G>V`-YYK}d;lB-!9%qvEFlW-_u9LNl9_R$qKASxnTy%ch zRqQw^8EDO50e=qOpy-nI-T^yqjc=Nwa(oY{+v2R(_&tI<6qze|80Gw9*}h*|aXwS| zDi(D@A=8eDy^4Ev-=tdzqT;bR))YrBkR<6nodA;XoK=Oux`UW;>Ex4q!j;Ja6KBNb zBxR{UHGK1p7!92_HuUdM)*LdES)wn&L)6tR@foc&WL{xaao|~rhUxmj7y)sy?A&xT;E9ToXmog$EcS{Oydf7_i*ZK7>F95lGylO2QttWL zPsh`A^8D_q)MngN>MeN4G2^>o@5$+jj6+6CU}!({{?TTRdQ0`X0A2Fl07_5uBcG?p zEu-;hyv1`G?^&805QgZ_GasaL&L=Z)t-3QmWZ|Dp9Kkk}1uuNaid8+)_7z};S`|h; z;ULK!skl=6?wgn}u4da*{ywt=3k7oF%VwM)n+ANnX(+kBSTV5^w5jc5kcP@SGfr-y zYD1~w1*TtW2a0Rq}=v z$(y>2miS7{p$rB8mjWdj2p~%y0op__t(o`kehyFUOIzg&xftTTY7=C^3G4U&gpy*Q~7CBor8v4eI~Ob zZ--kVy%g!RReeF2X0qQC)&8sP>mK&)39px1QQ~VjWk<3THS9$$H)>oSm5$s^xP+5_ zz?Lr)Pvej}c)4;v@jo_bQR|AWt<{*T6W~P0R-X_$cYdNEB6(QJ@(`B&$?%CZ=MFIY z{IY+(Wzq)CCse}UEm-7@<|gQoYZ?RVlB~$BY6Te9=PO70@IF%Aw_KsvM zP)KfGvtugqswxx6eHt!)`rLF^HfwDpV4pFk&!XBb8q3|1Bmi+4ruAZ&uK;rz8h%sf zO4}NyOlf}kE?CYLdqL5iUrhS)ncw@*ufsk{ovm*6YjrrF$>A(H-E4aywL9)o73aPo zc|%!Id{Bf<%YxL;mVuubblE;hHf@ri&4IPGSBBjsdGuH$69ns^I*3f@qbb0dc8!!b zc^ZQk%`i(=sJ@jnCEk^L^Mr&~6b-%3rOD0sCY0A)ccBR-Pw&G;*_7}`GK!c+b!J1S zWVV#exl^zui7PlT_OjDw_5}Z))Eu5^iQTqm)sUn|UZ}dHmFe)|tsb0CZ6f$~o$N1_NkqieS0UcV@MJv&t*p+ZeHpcZE)BDe z-1p4w8$YljjF54sR_L$>+IBekXCuoK_LOZ|`=t?oj1D;Jx20#)5R?$f39NB5=I@x) zC@Xkm#S@J@*G??+9QfjUuFNgvKV_2yRE!U7;f9_9H)#TRU25%W1@drp^W?E|^#K1i z)A+X>h4VZf(xKkTOWw23e2e#Zzkre!0_KPz#6`^~i0?LXZkJh|<#r~x*xwaO$CvbV zTDl5)`qo+KLX+tdd8cqxRL!4H0op{M>FRM^lPPZ%pJi)UHD(7pM4-wU*(rN|{PJy7KxR>Fxd zeIA{t)FEzNUkgUU&yvQ#tn*>qVp{9l>0m$GkS@p)O*xKY_Y&)sw8dJC&AuA=IP`95 zKj2D+h+$0~=Fev)q{C3M)4UR5&+NNh#1mS%G4LRhqOGhezmp<@6k@ch`eoEgLkaiZ z*8B-o(PWX}iwz42Hu5-ND5&KA&G}sH2q6;AG&~i&9z2hni z1W1GJv!lozPP%#L4-_JCs6^NCTADILj9Q+%fv zOoB*IAQ<(Be9}zMLsk^b0ySSz5m|eLpeQ1j%c&&mYUVrV3A{5Gts3i|zqcZ^4|bxk z{US7*hKu;ItfnQ^jTZgEMA{ZH>+5bEbsC(C0_yVvcOO;k^2x^JmfFbk)XO)uqLxm@ z=RsA=DOqu`TMg!BH3bFSDOrsUjtNl@&~|!#k(riIx9@+ds!MRcSHEpP8D5l*NaBU*f+ za^HX<-8u*{kBfH?h#tat57k8GLS4l?hlEWt)Gt{AsGF@jlOnWEx*}`?m70AW(M_lP zq_pQgTNhuTsO?DMOh~%&U(s1FWL8C8PJVCamAG9!?m9X0*9hXiFtHV2TDq;d#roZR z5fHfm|7~deySjeg|6zm-Qu(WZzmB_p2maWj;GFo=@atFLuOomzpylw)<(GlLui(FS zEB}B308*Gg!T+Uq`Kz2?yIOxpGR6MSL;S7B^{bR$J05>XiN^gY<=6hluL6F}+5QlK zM*3609~s=Q(7(pVKY#$hXLy_LZ_)Bs_+K5^pW$BcaQq+mZ|)4Ff&$kK0Du9%q~HNr J;Qo(K{|5}cj6(nb literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib deleted file mode 100644 index 135044d0f7f..00000000000 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Doc.bib +++ /dev/null @@ -1,5 +0,0 @@ -@article{, - author = {JabRef}, - year = {2025}, - title = {DOC Document} -} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.bib deleted file mode 100644 index 135044d0f7f..00000000000 --- a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/docs/Pptx.bib +++ /dev/null @@ -1,5 +0,0 @@ -@article{, - author = {JabRef}, - year = {2025}, - title = {DOC Document} -} From 34039bde951826e33bef821ca187a6ca0987d493 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Sun, 15 Jun 2025 00:54:11 +0300 Subject: [PATCH 09/13] feat(importers/docs): refactor ODF imports + add MsOffice importers and tests --- jablib/build.gradle.kts | 22 +++++ .../org/jabref/logic/importer/Importer.java | 4 + .../jabref/logic/importer/TikaImporter.java | 90 ++++++++++++++++++- .../fileformat/microsoft/DocImporter.java | 2 +- .../fileformat/microsoft/DocxImporter.java | 2 +- .../fileformat/microsoft/PptImporter.java | 2 +- .../fileformat/microsoft/PptxImporter.java | 2 +- .../fileformat/microsoft/XlsImporter.java | 4 +- .../fileformat/microsoft/XlsxImporter.java | 2 +- .../importer/fileformat/odf/OdfImporter.java | 22 +---- .../importer/fileformat/odf/OdpImporter.java | 2 +- .../importer/fileformat/odf/OdsImporter.java | 4 +- .../importer/fileformat/odf/OdtImporter.java | 2 +- .../jabref/logic/importer/util/Constants.java | 20 ++++- .../jabref/logic/util/StandardFileType.java | 6 ++ .../microsoft/DocImporterFilesTest.java | 7 +- .../fileformat/microsoft/DocImporterTest.java | 6 +- .../microsoft/DocxImporterFilesTest.java | 12 +-- .../microsoft/DocxImporterTest.java | 13 ++- .../microsoft/PptImporterFilesTest.java | 10 +-- .../fileformat/microsoft/PptImporterTest.java | 10 +-- .../microsoft/PptxImporterFilesTest.java | 10 +-- .../microsoft/PptxImporterTest.java | 10 +-- .../microsoft/XlsImporterFilesTest.java | 12 +-- .../fileformat/microsoft/XlsImporterTest.java | 10 +-- .../microsoft/XlsxImporterFilesTest.java | 10 +-- .../microsoft/XlsxImporterTest.java | 10 +-- .../fileformat/odf/OdpImporterFilesTest.java | 2 +- .../fileformat/odf/OdpImporterTest.java | 2 +- .../fileformat/odf/OdsImporterFilesTest.java | 2 +- .../fileformat/odf/OdsImporterTest.java | 4 +- .../fileformat/odf/OdtImporterFilesTest.java | 2 +- .../fileformat/odf/OdtImporterTest.java | 2 +- 33 files changed, 217 insertions(+), 103 deletions(-) diff --git a/jablib/build.gradle.kts b/jablib/build.gradle.kts index 8c0c0579a65..70e43a5250b 100644 --- a/jablib/build.gradle.kts +++ b/jablib/build.gradle.kts @@ -213,6 +213,24 @@ dependencies { implementation("org.apache.tika:tika-parsers:3.2.0") { exclude(group = "commons-logging") } + implementation("org.apache.tika:tika-parser-xml-module:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.tika:tika-parser-image-module:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.tika:tika-parser-microsoft-module:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.tika:tika-parser-text-module:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.tika:tika-parser-miscoffice-module:3.2.0") { + exclude(group = "commons-logging") + } + implementation("org.apache.poi:poi:5.4.1") + // TODO: Remove this mail dependency. + implementation("com.sun.mail:jakarta.mail:2.0.1") // endregion // Even if("compileOnly") is used, IntelliJ always adds to module-info.java. To avoid issues during committing, we use("implementation") instead of("compileOnly") @@ -483,6 +501,10 @@ tasks.test { useJUnitPlatform { excludeTags("DatabaseTest", "FetcherTest") } + + jvmArgs( + "--add-exports=org.apache.poi.ooxml/org.apache.poi.xslf.extractor=org.apache.tika.parser.microsoft" + ) } jmh { diff --git a/jablib/src/main/java/org/jabref/logic/importer/Importer.java b/jablib/src/main/java/org/jabref/logic/importer/Importer.java index ca54f38da9e..2bb98734ed3 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/Importer.java +++ b/jablib/src/main/java/org/jabref/logic/importer/Importer.java @@ -49,6 +49,10 @@ public abstract class Importer implements Comparable { * @throws IOException Signals that an I/O exception has occurred. */ public boolean isRecognizedFormat(Path filePath) throws IOException { + if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) { + return false; + } + try (BufferedReader bufferedReader = getReader(filePath)) { return isRecognizedFormat(bufferedReader); } diff --git a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java index 317091dda3e..59655c0e919 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java @@ -1,4 +1,92 @@ package org.jabref.logic.importer; -public class TikaImporter { +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.model.strings.StringUtil; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.Property; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.SAXException; + +/** + * Common class for all file importers that use Apache Tika to extract metadata from files. + *

+ * Child classes should implement the rest of {@link Importer}. + */ +public abstract class TikaImporter extends Importer { + @Override + public ParserResult importDatabase(BufferedReader input) throws IOException { + throw new UnsupportedOperationException("TikaImporter (and descendants) do not support importDatabase(BufferedReader reader)." + + "Instead use importDatabase(Path filePath)."); + } + + @Override + public ParserResult importDatabase(Path filePath) throws IOException { + try (InputStream inputStream = new FileInputStream(filePath.toFile())) { + Parser parser = getTikaParser(); + Metadata metadata = new Metadata(); + BodyContentHandler handler = new BodyContentHandler(); + + ParseContext parseContext = new ParseContext(); + parseContext.set(Parser.class, parser); + + parser.parse(inputStream, handler, metadata, parseContext); + + BibEntry entry = extractMetadata(metadata); + + return ParserResult.fromEntry(entry); + } catch (SAXException | TikaException e) { + throw new IOException("Error parsing file: " + filePath, e); + } + } + + protected Parser getTikaParser() { + return new AutoDetectParser(); + } + + private BibEntry extractMetadata(Metadata metadata) { + System.out.println(metadata); + Optional title = Optional.ofNullable(metadata.get("dc:title")); + Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); + + Optional dateString = date.map(d -> { + Calendar cal = Calendar.getInstance(); + cal.setTime(d); + return Integer.toString(cal.get(Calendar.YEAR)); + }); + + List creators = Arrays.stream(metadata.getValues("dc:creator")) + .filter(StringUtil::isNotBlank) + .toList(); + List contributors = Arrays.stream(metadata.getValues("dc:contributor")) + .filter(StringUtil::isNotBlank) + .toList(); + + List authors = Stream.concat(creators.stream(), contributors.stream()).toList(); + + return new BibEntry(StandardEntryType.Misc) + .withField(StandardField.TITLE, title) + .withField(StandardField.AUTHOR, !authors.isEmpty() + ? Optional.of(String.join(" and ", authors)) + : Optional.empty()) + .withField(StandardField.YEAR, dateString); + } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java index 00f3a0a6224..a3baff9f9e0 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocImporter.java @@ -12,7 +12,7 @@ /** * Imports old Microsoft Word 97-2003 files (`.doc`). */ -public class WordOldImporter extends TikaImporter { +public class DocImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isOleCompound(input); diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java index 40e9b553310..6f8054a1a0c 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporter.java @@ -12,7 +12,7 @@ /** * Imports Microsoft Word 2007-365 files (`.docx`). */ -public class WordImporter extends TikaImporter { +public class DocxImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isZip(input); diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java index 74dc93cd242..8bc3cc3b428 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptImporter.java @@ -12,7 +12,7 @@ /** * Imports old Microsoft PowerPoint 97-2003 files (`.ppt`). */ -public class PowerpointOldImporter extends TikaImporter { +public class PptImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isOleCompound(input); diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java index e5c6c7864b1..245e6aeef9b 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporter.java @@ -12,7 +12,7 @@ /** * Imports Microsoft PowerPoint 2007-365 files (`.pptx`). */ -public class PowerpointImporter extends TikaImporter { +public class PptxImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isZip(input); diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java index 89e793ce6b1..3204fc87ecc 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporter.java @@ -12,7 +12,7 @@ /** * Imports old Microsoft Excel 97-2003 files (`.xls`). */ -public class ExcelOldImporter extends TikaImporter { +public class XlsImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isOleCompound(input); @@ -35,6 +35,6 @@ public String getDescription() { @Override public FileType getFileType() { - return StandardFileType.DOC; + return StandardFileType.XLS; } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java index 421090c59e5..eed034d6650 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporter.java @@ -12,7 +12,7 @@ /** * Imports Microsoft Excel 2007-365 files (`.xlsx`). */ -public class ExcelImporter extends TikaImporter { +public class XlsxImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isZip(input); diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java index 9818df8e107..3cf4963d888 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java @@ -1,30 +1,10 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import java.io.BufferedReader; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Optional; -import org.jabref.logic.importer.Importer; -import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.TikaImporter; import org.jabref.logic.importer.util.Constants; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.FileType; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; - -import org.apache.tika.exception.TikaException; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.metadata.Property; -import org.apache.tika.parser.AutoDetectParser; -import org.apache.tika.sax.BodyContentHandler; -import org.xml.sax.SAXException; /** * General importer for Open Document Format files. diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java index a715e594b85..7a5e068d4ce 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdpImporter.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java index 72df33e7f7f..8363107b748 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdsImporter.java @@ -1,9 +1,11 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; import org.jabref.logic.util.StandardFileType; +import org.apache.tika.parser.Parser; + /** * Importer for OpenDocument Calc (ODS) files. */ diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java index efe6fdb55f6..1b7b2aff3c6 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdtImporter.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java index f80752e1e7a..a1ceb8315b1 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java @@ -7,6 +7,8 @@ public class Constants { public static final char[] ZIP_HEADER_MAGIC_NUMBER = {0x50, 0x4b, 0x03, 0x04}; + // public static final char[] OLE_COMPOUND_MAGIC_NUMBER = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}; + public static final char[] OLE_COMPOUND_MAGIC_NUMBER = {65533, 65533, 17, 2161, 0x1A, 65533, 0x00, 0x00}; public static final List ZIP_FILES_EXTENSIONS = List.of( ".ctv6bak", @@ -20,11 +22,23 @@ public class Constants { ".odp" ); - public static final String DC_NAMESPACE = "http://purl.org/dc/elements/1.1/"; + public static final List OLE_COMPOUND_FILES_EXTENSIONS = List.of( + ".doc", + ".xls", + ".ppt" + ); public static boolean isZip(BufferedReader input) throws IOException { - char[] header = new char[ZIP_HEADER_MAGIC_NUMBER.length]; + return hasMagicNumber(input, ZIP_HEADER_MAGIC_NUMBER); + } + + public static boolean isOleCompound(BufferedReader input) throws IOException { + return hasMagicNumber(input, OLE_COMPOUND_MAGIC_NUMBER); + } + + private static boolean hasMagicNumber(BufferedReader input, char[] magicNumber) throws IOException { + char[] header = new char[magicNumber.length]; int nRead = input.read(header); - return nRead == ZIP_HEADER_MAGIC_NUMBER.length && Arrays.equals(header, ZIP_HEADER_MAGIC_NUMBER); + return nRead == magicNumber.length && Arrays.equals(header, magicNumber); } } diff --git a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java index 9d077fc1a50..3b9d5f61cd8 100644 --- a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java +++ b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java @@ -22,6 +22,8 @@ public enum StandardFileType implements FileType { CLASS("Class file", "class"), CSS("CSS Styleshet", "css"), CSV("CSV", "csv"), + DOC("Microsoft Word 97-2003", "doc"), + DOCX("Microsoft Word 2007-365", "docx"), ENDNOTE("Endnote", "ref", "enw"), HTML("HTML", "html", "htm"), ISI("Isi", "isi", "txt"), @@ -36,6 +38,8 @@ public enum StandardFileType implements FileType { ODP("OpenOffice Impress", "odp"), ODS("OpenOffice Calc", "ods"), ODT("OpenOffice Writer", "odt"), + PPT("Microsoft PowerPoint 97-2003", "ppt"), + PPTX("Microsoft PowerPoint 2007-365", "pptx"), PDF("PDF", "pdf"), PUBMED("Pubmed", "fcgi"), RDF("RDF", "rdf"), @@ -47,6 +51,8 @@ public enum StandardFileType implements FileType { TXT("Plain Text", "txt"), XML("XML", "xml"), XMP("XMP", "xmp"), + XLS("Microsoft Excel 97-2003", "xsl"), + XLSX("Microsoft Excel 2007-365", "xlsx"), YAML("YAML Markup", "yml", "yaml"), ZIP("Zip Archive", "zip"); diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java index 53a873ffd7b..56c42d294f7 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterFilesTest.java @@ -7,25 +7,24 @@ import org.jabref.logic.importer.ImportException; import org.jabref.logic.importer.fileformat.ImporterTestEngine; -import org.jabref.logic.importer.fileformat.odf.OdpImporter; import org.jabref.logic.importer.util.Constants; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -public class WordOldImporterFilesTest { +public class DocImporterFilesTest { private static final String FILE_ENDING = ".doc"; private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private WordOldImporter importer; + private DocImporter importer; @BeforeEach void setUp() { - importer = new WordOldImporter(); + importer = new DocImporter(); } private static Stream fileNames() throws IOException { diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java index 7488d1c4f88..e1d80064c35 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocImporterTest.java @@ -7,12 +7,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class WordOldImporterTest { - private WordOldImporter importer; +class DocImporterTest { + private DocImporter importer; @BeforeEach void setUp() { - importer = new WordOldImporter(); + importer = new DocImporter(); } @Test diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java index 39e81478156..85e426abe46 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterFilesTest.java @@ -14,26 +14,26 @@ import org.junit.jupiter.params.provider.MethodSource; public class DocxImporterFilesTest { - private static final String FILE_ENDING = ".doc"; - private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + private static final String FILE_ENDING = ".docx"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private DocImporter importer; + private DocxImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new DocxImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("DocxImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("DocxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java index 2dcda2cd42b..b6bd526c565 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/DocxImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat.microsoft; -import org.jabref.logic.importer.fileformat.odf.OdpImporter; import org.jabref.logic.util.StandardFileType; import org.junit.jupiter.api.BeforeEach; @@ -8,26 +7,26 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class WordImporterTest { - private OdpImporter importer; +class DocxImporterTest { + private DocxImporter importer; @BeforeEach void setUp() { - importer = new OdpImporter(); + importer = new DocxImporter(); } @Test void getFormatName() { - assertEquals("OpenDocument Impress", importer.getName()); + assertEquals("Microsoft Word 2007-365", importer.getName()); } @Test void getCLIId() { - assertEquals("odp", importer.getId()); + assertEquals("docx", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.ODP, importer.getFileType()); + assertEquals(StandardFileType.DOCX, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java index a6cf1dc9ddc..af18f450345 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterFilesTest.java @@ -14,26 +14,26 @@ import org.junit.jupiter.params.provider.MethodSource; public class PptImporterFilesTest { - private static final String FILE_ENDING = ".doc"; + private static final String FILE_ENDING = ".ppt"; private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private DocImporter importer; + private PptImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new PptImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("PptImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("PptImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java index 0ea71d8d392..d75ad18ecbc 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class PptImporterTest { - private DocImporter importer; + private PptImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new PptImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Word 97-2003", importer.getName()); + assertEquals("Microsoft PowerPoint 97-2003", importer.getName()); } @Test void getCLIId() { - assertEquals("doc", importer.getId()); + assertEquals("ppt", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.DOC, importer.getFileType()); + assertEquals(StandardFileType.PPT, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java index dc81f892048..bfa0b0daa41 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterFilesTest.java @@ -14,26 +14,26 @@ import org.junit.jupiter.params.provider.MethodSource; public class PptxImporterFilesTest { - private static final String FILE_ENDING = ".docx"; + private static final String FILE_ENDING = ".pptx"; private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private DocxImporter importer; + private PptxImporter importer; @BeforeEach void setUp() { - importer = new DocxImporter(); + importer = new PptxImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocxImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("PptxImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("PptxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java index dede8157169..8be5537030a 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/PptxImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class PptxImporterTest { - private XlsxImporter importer; + private PptxImporter importer; @BeforeEach void setUp() { - importer = new XlsxImporter(); + importer = new PptxImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Excel 2007-365", importer.getName()); + assertEquals("Microsoft PowerPoint 2007-365", importer.getName()); } @Test void getCLIId() { - assertEquals("xlsx", importer.getId()); + assertEquals("pptx", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.XLSX, importer.getFileType()); + assertEquals(StandardFileType.PPTX, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java index 56c42d294f7..e0ff00dabdb 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterFilesTest.java @@ -13,27 +13,27 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -public class DocImporterFilesTest { - private static final String FILE_ENDING = ".doc"; +public class XlsImporterFilesTest { + private static final String FILE_ENDING = ".xls"; private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private DocImporter importer; + private XlsImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new XlsImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("XlsImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("XlsImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java index 776b716c6ec..4d2c5682f4c 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class XlsImporterTest { - private DocImporter importer; + private XlsImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new XlsImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Word 97-2003", importer.getName()); + assertEquals("Microsoft Excel 97-2003", importer.getName()); } @Test void getCLIId() { - assertEquals("doc", importer.getId()); + assertEquals("xls", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.DOC, importer.getFileType()); + assertEquals(StandardFileType.XLS, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java index 3aa182f0482..24e37bc6010 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterFilesTest.java @@ -14,26 +14,26 @@ import org.junit.jupiter.params.provider.MethodSource; public class XlsxImporterFilesTest { - private static final String FILE_ENDING = ".docx"; + private static final String FILE_ENDING = ".xlsx"; private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS .stream() .filter(ext -> !ext.equals(FILE_ENDING)) .toList(); - private DocxImporter importer; + private XlsxImporter importer; @BeforeEach void setUp() { - importer = new DocxImporter(); + importer = new XlsxImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocxImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("XlsxImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("XlsxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java index 8b8997eea23..c736920de35 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/XlsxImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class XlsxImporterTest { - private DocxImporter importer; + private XlsxImporter importer; @BeforeEach void setUp() { - importer = new DocxImporter(); + importer = new XlsxImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Word 2007-365", importer.getName()); + assertEquals("Microsoft Excel 2007-365", importer.getName()); } @Test void getCLIId() { - assertEquals("docx", importer.getId()); + assertEquals("xlsx", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.DOCX, importer.getFileType()); + assertEquals(StandardFileType.XLSX, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java index b363242b6d1..23329c74f40 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterFilesTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import java.io.IOException; import java.util.List; diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java index 9ed53a322f2..2f1071b1910 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdpImporterTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.util.StandardFileType; diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java index 0fa5333a645..9e218d9a74f 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterFilesTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import java.io.IOException; import java.util.List; diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java index 0f06937b7a6..6badb81a1bc 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdsImporterTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.util.StandardFileType; @@ -22,7 +22,7 @@ void getFormatName() { @Test void getCLIId() { - assertEquals("odc", importer.getId()); + assertEquals("ods", importer.getId()); } @Test diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java index 5b4edfc8503..61b091ab0c1 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterFilesTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import java.io.IOException; import java.util.List; diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java index e1cb53b0b0a..1ca6425b3c7 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/odf/OdtImporterTest.java @@ -1,4 +1,4 @@ -package org.jabref.logic.importer.fileformat.docs; +package org.jabref.logic.importer.fileformat.odf; import org.jabref.logic.util.StandardFileType; From 511e3c090f1c1234f758f14471e78ae071a5f79b Mon Sep 17 00:00:00 2001 From: InAnYan Date: Sun, 15 Jun 2025 03:11:45 +0300 Subject: [PATCH 10/13] feat(importers/docs): add images importers --- .../importer/fileformat/TxtImporter.java | 4 ++ .../importer/fileformat/img/JpgImporter.java | 37 +++++++++++ .../importer/fileformat/img/PngImporter.java | 4 ++ .../fileformat/microsoft/RtfImporter.java | 4 ++ .../entry/types/BiblatexNonStandardTypes.java | 4 ++ .../importer/fileformat/TxtImporterTest.java | 33 ++++++++++ .../fileformat/img/JpgImporterFilesTest.java | 58 ++++++++++++++++++ .../fileformat/img/JpgImporterTest.java | 33 ++++++++++ .../fileformat/img/PngImporterFilesTest.java | 51 +++++++++++++++ .../fileformat/img/PngImporterTest.java | 32 ++++++++++ .../microsoft/RtfImporterFilesTest.java | 57 +++++++++++++++++ .../fileformat/microsoft/RtfImporterTest.java | 32 ++++++++++ .../importer/fileformat/JpgImporterTest1.bib | 6 ++ .../importer/fileformat/JpgImporterTest1.jpg | Bin 0 -> 135594 bytes .../importer/fileformat/PngImporterTest1.bib | 6 ++ .../importer/fileformat/PngImporterTest1.png | Bin 0 -> 3904 bytes .../importer/fileformat/RtfImporterTest1.bib | 4 ++ .../importer/fileformat/RtfImporterTest1.rtf | 14 +++++ .../logic/importer/fileformat/Test.java | 45 ++++++++++++++ .../importer/fileformat/TxtImporterTest1.txt | 1 + 20 files changed, 425 insertions(+) create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java create mode 100644 jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java create mode 100644 jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.jpg create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.png create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.bib create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.rtf create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/Test.java create mode 100644 jablib/src/test/resources/org/jabref/logic/importer/fileformat/TxtImporterTest1.txt diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java new file mode 100644 index 00000000000..957e9610e63 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java @@ -0,0 +1,4 @@ +package org.jabref.logic.importer.fileformat; + +public class TxtImporter { +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java new file mode 100644 index 00000000000..8ac89788902 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java @@ -0,0 +1,37 @@ +package org.jabref.logic.importer.fileformat.img; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class JpegImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.hasMagicNumber(input, new char[]{(char) 0xFF, (char) 0xD8, (char) 0xFF}); + } + + @Override + public String getId() { + return "jpg"; + } + + @Override + public String getName() { + return "JPG"; + } + + @Override + public String getDescription() { + return Localization.lang("JPG image importer"); + } + + @Override + public FileType getFileType() { + return StandardFileType.JPG; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java new file mode 100644 index 00000000000..d61e3e3bd11 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java @@ -0,0 +1,4 @@ +package org.jabref.logic.importer.fileformat.img; + +public class PngImporter { +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java new file mode 100644 index 00000000000..ae4c4fc34c1 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java @@ -0,0 +1,4 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +public class RtfImporter { +} diff --git a/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java b/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java new file mode 100644 index 00000000000..99a2e4729d4 --- /dev/null +++ b/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java @@ -0,0 +1,4 @@ +package org.jabref.model.entry.types; + +public enum BiblatexNonStandardTypes { +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java new file mode 100644 index 00000000000..71e80edc307 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java @@ -0,0 +1,33 @@ +package org.jabref.logic.importer.fileformat; + +import org.jabref.logic.importer.fileformat.microsoft.XlsImporter; +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TxtImporterTest { + private XlsImporter importer; + + @BeforeEach + void setUp() { + importer = new XlsImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Excel 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("xls", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.XLS, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java new file mode 100644 index 00000000000..e5b036048cb --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java @@ -0,0 +1,58 @@ +package org.jabref.logic.importer.fileformat.img; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.fileformat.microsoft.DocImporter; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class DocImporterFilesTest { + private static final String FILE_ENDING = ".doc"; + private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java new file mode 100644 index 00000000000..eacc38d2f5d --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java @@ -0,0 +1,33 @@ +package org.jabref.logic.importer.fileformat.img; + +import org.jabref.logic.importer.fileformat.microsoft.DocImporter; +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DocImporterTest { + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("doc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOC, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java new file mode 100644 index 00000000000..0d9049bd71a --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java @@ -0,0 +1,51 @@ +package org.jabref.logic.importer.fileformat.img; + +import java.io.IOException; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class PngImporterFilesTest { + private static final String FILE_ENDING = ".jpg"; + + private JpgImporter importer; + + @BeforeEach + void setUp() { + importer = new JpgImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("JpgImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("JpgImporterTest") && !name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java new file mode 100644 index 00000000000..8bcba20744d --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.img; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PngImporterTest { + private JpgImporter importer; + + @BeforeEach + void setUp() { + importer = new JpgImporter(); + } + + @Test + void getFormatName() { + assertEquals("JPG", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("jpg", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.JPG, importer.getFileType()); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java new file mode 100644 index 00000000000..a762277615f --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java @@ -0,0 +1,57 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.jabref.logic.importer.ImportException; +import org.jabref.logic.importer.fileformat.ImporterTestEngine; +import org.jabref.logic.importer.util.Constants; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class RtfImporterFilesTest { + private static final String FILE_ENDING = ".pptx"; + private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS + .stream() + .filter(ext -> !ext.equals(FILE_ENDING)) + .toList(); + + private PptxImporter importer; + + @BeforeEach + void setUp() { + importer = new PptxImporter(); + } + + private static Stream fileNames() throws IOException { + Predicate fileName = name -> name.startsWith("PptxImporterTest") && name.endsWith(FILE_ENDING); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + private static Stream invalidFileNames() throws IOException { + Predicate fileName = name -> !name.startsWith("PptxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + return ImporterTestEngine.getTestFiles(fileName).stream(); + } + + @ParameterizedTest + @MethodSource("fileNames") + void isRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("invalidFileNames") + void isNotRecognizedFormat(String fileName) throws IOException { + ImporterTestEngine.testIsNotRecognizedFormat(importer, fileName); + } + + @ParameterizedTest + @MethodSource("fileNames") + void importEntries(String fileName) throws ImportException, IOException { + ImporterTestEngine.testImportEntries(importer, fileName, FILE_ENDING); + } +} diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java new file mode 100644 index 00000000000..1b7efb6ce02 --- /dev/null +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java @@ -0,0 +1,32 @@ +package org.jabref.logic.importer.fileformat.microsoft; + +import org.jabref.logic.util.StandardFileType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RtfImporterTest { + private DocImporter importer; + + @BeforeEach + void setUp() { + importer = new DocImporter(); + } + + @Test + void getFormatName() { + assertEquals("Microsoft Word 97-2003", importer.getName()); + } + + @Test + void getCLIId() { + assertEquals("doc", importer.getId()); + } + + @Test + void sGetExtensions() { + assertEquals(StandardFileType.DOC, importer.getFileType()); + } +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.bib new file mode 100644 index 00000000000..a52bc6207dd --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.bib @@ -0,0 +1,6 @@ +@image{, + title = {JpgImporterTest1}, + author = {Falkenpost}, + year = {2025}, + date = {2020-01-01} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.jpg b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/JpgImporterTest1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..89514fe5bf9b8ea9b3ef8ebee7918d10b92fc0ca GIT binary patch literal 135594 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

vjR?J+p~~c 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.bib new file mode 100644 index 00000000000..8ea30241704 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.bib @@ -0,0 +1,6 @@ +@image{, + title = {PngImporterTest1}, + year = {2025}, + month = {feb}, + date = {2025-02-21}, +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.png b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/PngImporterTest1.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f416b2060cb5db61a3012bcb95538bca8cb6fc GIT binary patch literal 3904 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 literal 0 HcmV?d00001 diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.bib b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.bib new file mode 100644 index 00000000000..45ba322eb8b --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.bib @@ -0,0 +1,4 @@ +@misc(, + title = {RTF Document}, + year = {2025} +} diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.rtf b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.rtf new file mode 100644 index 00000000000..8a0952e7474 --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/RtfImporterTest1.rtf @@ -0,0 +1,14 @@ +{\rtf1\ansi\deff3\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\fnil\fprq2\fcharset0 0;}{\f6\fnil\fprq2\fcharset0 Noto Sans CJK SC;}{\f7\fnil\fprq2\fcharset0 FreeSans;}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;} +{\stylesheet{\s0\snext0\rtlch\af7\afs24\alang1081 \ltrch\lang1058\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1058\kerning1\dbch\af5\langfe2052 Normal;} +{\s15\sbasedon0\snext16\rtlch\af7\afs28 \ltrch\hich\af4\loch\sb240\sa120\keepn\f4\fs28\dbch\af6 Heading;} +{\s16\sbasedon0\snext16\loch\sl276\slmult1\sb0\sa140 Body Text;} +{\s17\sbasedon16\snext17\rtlch\af7 \ltrch\loch\sl240\slmult1\sb0\sa0 List;} +{\s18\sbasedon0\snext18\rtlch\af7\afs24\ai \ltrch\loch\sb120\sa120\fs24\i caption;} +{\s19\sbasedon0\snext19\rtlch\af7 \ltrch Index;} +}{\*\generator LibreOffice/25.2.3.2$Linux_X86_64 LibreOffice_project/520$Build-2}{\info{\title RTF Document}{\creatim\yr2025\mo6\dy15\hr1\min1}{\revtim\yr2025\mo6\dy15\hr1\min10}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709 +\hyphauto1\viewscale160\formshade\nobrkwrptbl\paperh16838\paperw11906\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\fet\aftnrstcont\aftnstart1\aftnnrlc +{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\rtlch\af7\afs24\alang1081 \ltrch\lang1058\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang1058\kerning1\dbch\af5\langfe2052\ql{\loch +Hello, World!} +\par } \ No newline at end of file diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/Test.java b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/Test.java new file mode 100644 index 00000000000..eafe708416a --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/Test.java @@ -0,0 +1,45 @@ +//DEPS org.apache.tika:tika-core:3.2.0 +//DEPS org.apache.tika:tika-parsers-standard-package:3.2.0 + +import org.apache.tika.Tika; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.parser.Parser; +import org.apache.tika.parser.image.JpegParser; +import org.apache.tika.sax.BodyContentHandler; +import org.apache.tika.parser.ParseContext; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.File; + +public class Test { + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.err.println("Usage: jbang PrintMetadata.java "); + System.exit(1); + } + + String filePath = args[0]; + File file = new File(filePath); + if (!file.exists() || !file.isFile()) { + System.err.println("File not found: " + filePath); + System.exit(1); + } + + try (InputStream stream = new FileInputStream(file)) { + JpegParser parser = new JpegParser(); + Metadata metadata = new Metadata(); + BodyContentHandler handler = new BodyContentHandler(); + ParseContext context = new ParseContext(); + context.set(Parser.class, parser); + parser.parse(stream, handler, metadata, context); + + System.out.println("Metadata" + metadata.get(Metadata.ORIGINAL_DATE) + ":"); + for (String name : metadata.names()) { + System.out.printf(" %s: %s%n", name, metadata.get(name)); + } + } + } +} + diff --git a/jablib/src/test/resources/org/jabref/logic/importer/fileformat/TxtImporterTest1.txt b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/TxtImporterTest1.txt new file mode 100644 index 00000000000..8ab686eafeb --- /dev/null +++ b/jablib/src/test/resources/org/jabref/logic/importer/fileformat/TxtImporterTest1.txt @@ -0,0 +1 @@ +Hello, World! From 03cbaa3de7afd6cd795d834898a744e8d46463bc Mon Sep 17 00:00:00 2001 From: InAnYan Date: Sun, 15 Jun 2025 03:17:23 +0300 Subject: [PATCH 11/13] feat(importers/docs): add images importers --- .../StandardExternalFileType.java | 2 +- jablib/src/main/java/module-info.java | 5 +- .../jabref/logic/importer/TikaImporter.java | 109 +++++++++++++++--- .../importer/fileformat/TxtImporter.java | 4 - .../fileformat/books/EpubImporter.java | 39 +++++++ .../importer/fileformat/img/JpgImporter.java | 9 +- .../importer/fileformat/img/PngImporter.java | 42 ++++++- .../fileformat/microsoft/RtfImporter.java | 37 +++++- .../importer/fileformat/misc/TxtImporter.java | 36 ++++++ .../jabref/logic/importer/util/Constants.java | 2 +- .../jabref/logic/util/StandardFileType.java | 2 + .../entry/types/BiblatexNonStandardTypes.java | 43 ++++++- .../importer/fileformat/TxtImporterTest.java | 12 +- .../fileformat/img/JpgImporterFilesTest.java | 19 +-- .../fileformat/img/JpgImporterTest.java | 13 +-- .../fileformat/img/PngImporterFilesTest.java | 10 +- .../fileformat/img/PngImporterTest.java | 10 +- .../microsoft/RtfImporterFilesTest.java | 14 +-- .../fileformat/microsoft/RtfImporterTest.java | 10 +- 19 files changed, 342 insertions(+), 76 deletions(-) delete mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/books/EpubImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/misc/TxtImporter.java diff --git a/jabgui/src/main/java/org/jabref/gui/externalfiletype/StandardExternalFileType.java b/jabgui/src/main/java/org/jabref/gui/externalfiletype/StandardExternalFileType.java index fc12e9670e8..145c2b266b9 100644 --- a/jabgui/src/main/java/org/jabref/gui/externalfiletype/StandardExternalFileType.java +++ b/jabgui/src/main/java/org/jabref/gui/externalfiletype/StandardExternalFileType.java @@ -28,7 +28,7 @@ public enum StandardExternalFileType implements ExternalFileType { TIFF(Localization.lang("%0 image", "TIFF"), "tiff", "image/tiff", "gimp", "picture", IconTheme.JabRefIcons.PICTURE), URL("URL", "html", "text/html", "firefox", "www", IconTheme.JabRefIcons.WWW), MHT("MHT", "mht", "multipart/related", "firefox", "www", IconTheme.JabRefIcons.WWW), - ePUB("ePUB", "epub", "application/epub+zip", "firefox", "www", IconTheme.JabRefIcons.WWW), + ePUB("ePUB", "epub", "application/epub+zip", "firefox", "www", IconTheme.JabRefIcons.BOOK), MARKDOWN("Markdown", "md", "text/markdown", "emacs", "emacs", IconTheme.JabRefIcons.FILE_TEXT); private final String name; private final String extension; diff --git a/jablib/src/main/java/module-info.java b/jablib/src/main/java/module-info.java index 4efb3fd0d07..c92ae905263 100644 --- a/jablib/src/main/java/module-info.java +++ b/jablib/src/main/java/module-info.java @@ -106,8 +106,7 @@ exports org.jabref.logic.git; exports org.jabref.logic.pseudonymization; exports org.jabref.logic.citation.repository; - - requires java.base; + exports org.jabref.logic.importer.fileformat.misc; requires javafx.base; requires javafx.graphics; // because of javafx.scene.paint.Color @@ -115,7 +114,6 @@ requires com.tobiasdiez.easybind; // for java.awt.geom.Rectangle2D required by org.jabref.logic.pdf.TextExtractor - requires java.desktop; // SQL requires java.sql; @@ -253,5 +251,6 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires org.apache.tika.core; + requires org.jetbrains.annotations; // endregion } diff --git a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java index 59655c0e919..f899ab35dca 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java @@ -5,15 +5,23 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Stream; +import org.jabref.logic.util.io.FileUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.StandardEntryType; import org.jabref.model.strings.StringUtil; @@ -24,6 +32,7 @@ import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.sax.BodyContentHandler; +import org.jetbrains.annotations.NotNull; import org.xml.sax.SAXException; /** @@ -32,6 +41,8 @@ * Child classes should implement the rest of {@link Importer}. */ public abstract class TikaImporter extends Importer { + private final static Pattern imageDatePattern = Pattern.compile("(year|month|day|hour|minute|second)=(\\d+)"); + @Override public ParserResult importDatabase(BufferedReader input) throws IOException { throw new UnsupportedOperationException("TikaImporter (and descendants) do not support importDatabase(BufferedReader reader)." @@ -50,7 +61,8 @@ public ParserResult importDatabase(Path filePath) throws IOException { parser.parse(inputStream, handler, metadata, parseContext); - BibEntry entry = extractMetadata(metadata); + String fileName = FileUtil.getBaseName(filePath); + BibEntry entry = extractMetadata(metadata, fileName); return ParserResult.fromEntry(entry); } catch (SAXException | TikaException e) { @@ -59,20 +71,58 @@ public ParserResult importDatabase(Path filePath) throws IOException { } protected Parser getTikaParser() { + // Use {@link AutoDetectParser} by default, subclasses can override this method to provide a different parser return new AutoDetectParser(); } - private BibEntry extractMetadata(Metadata metadata) { - System.out.println(metadata); - Optional title = Optional.ofNullable(metadata.get("dc:title")); - Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); + protected EntryType getEntryType() { + // Default to `Misc`, subclasses should override this method if they have a specific entry type + return StandardEntryType.Misc; + } - Optional dateString = date.map(d -> { + private BibEntry extractMetadata(Metadata metadata, String titleReplacement) { + String title = Optional.ofNullable(metadata.get("dc:title")).orElse(titleReplacement); + Optional date = extractDate(metadata); + List authors = extractAuthors(metadata); + + Optional year = date.map(d -> { Calendar cal = Calendar.getInstance(); cal.setTime(d); return Integer.toString(cal.get(Calendar.YEAR)); }); + Optional dateIso = date.map(d -> { + LocalDate localDate = d.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + return localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); + }); + + Optional month = date.map(d -> { + LocalDate localDate = d.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + String[] bibtexMonths = { + "jan", "feb", "mar", "apr", "may", "jun", + "jul", "aug", "sep", "oct", "nov", "dec" + }; + + return bibtexMonths[localDate.getMonthValue() - 1]; + }); + + return new BibEntry(getEntryType()) + .withField(StandardField.TITLE, title) + .withField(StandardField.AUTHOR, !authors.isEmpty() + ? Optional.of(String.join(" and ", authors)) + : Optional.empty()) + .withField(StandardField.YEAR, year) + .withField(StandardField.DATE, dateIso) + .withField(StandardField.MONTH, month); + } + + private static List extractAuthors(Metadata metadata) { List creators = Arrays.stream(metadata.getValues("dc:creator")) .filter(StringUtil::isNotBlank) .toList(); @@ -80,13 +130,46 @@ private BibEntry extractMetadata(Metadata metadata) { .filter(StringUtil::isNotBlank) .toList(); - List authors = Stream.concat(creators.stream(), contributors.stream()).toList(); + return Stream.concat(creators.stream(), contributors.stream()).toList(); + } - return new BibEntry(StandardEntryType.Misc) - .withField(StandardField.TITLE, title) - .withField(StandardField.AUTHOR, !authors.isEmpty() - ? Optional.of(String.join(" and ", authors)) - : Optional.empty()) - .withField(StandardField.YEAR, dateString); + private static Optional extractDate(Metadata metadata) { + Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); + + if (date.isEmpty()) { + Optional dateEntry = Optional.ofNullable(metadata.get("tIME")) + .or(() -> Optional.ofNullable(metadata.get("Document ImageModificationTime"))); + + if (dateEntry.isPresent()) { + date = Optional.of(parseDateForImages(dateEntry.get())); + } + } + + return date; + } + + private static Date parseDateForImages(String dateString) { + Matcher matcher = imageDatePattern.matcher(dateString); + + int year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0; + + while (matcher.find()) { + String key = matcher.group(1); + int value = Integer.parseInt(matcher.group(2)); + + switch (key) { + case "year" -> year = value; + case "month" -> month = value; + case "day" -> day = value; + case "hour" -> hour = value; + case "minute" -> minute = value; + case "second" -> second = value; + } + } + + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month, day, hour, minute, second); + + return calendar.getTime(); } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java deleted file mode 100644 index 957e9610e63..00000000000 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/TxtImporter.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.jabref.logic.importer.fileformat; - -public class TxtImporter { -} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/EpubImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/EpubImporter.java new file mode 100644 index 00000000000..5dbb48e8b55 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/EpubImporter.java @@ -0,0 +1,39 @@ +package org.jabref.logic.importer.fileformat.books; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class EpubImporter extends TikaImporter { + private static final char[] EPUB_HEADER_MAGIC_NUMBER = {0x50, 0x4b, 0x03, 0x04}; + + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.hasMagicNumber(input, EPUB_HEADER_MAGIC_NUMBER); + } + + @Override + public String getId() { + return "epub"; + } + + @Override + public String getName() { + return "ePUB"; + } + + @Override + public String getDescription() { + return Localization.lang("Import the popular e-book file format ePUB"); + } + + @Override + public FileType getFileType() { + return StandardFileType.EPUB; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java index 8ac89788902..fbe10c69a57 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java @@ -8,8 +8,10 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.entry.types.BiblatexNonStandardTypes; +import org.jabref.model.entry.types.EntryType; -public class JpegImporter extends TikaImporter { +public class JpgImporter extends TikaImporter { @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.hasMagicNumber(input, new char[]{(char) 0xFF, (char) 0xD8, (char) 0xFF}); @@ -34,4 +36,9 @@ public String getDescription() { public FileType getFileType() { return StandardFileType.JPG; } + + @Override + protected EntryType getEntryType() { + return BiblatexNonStandardTypes.Image; + } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java index d61e3e3bd11..29b685db5d7 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java @@ -1,4 +1,44 @@ package org.jabref.logic.importer.fileformat.img; -public class PngImporter { +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; +import org.jabref.model.entry.types.BiblatexNonStandardTypes; +import org.jabref.model.entry.types.EntryType; + +public class PngImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.hasMagicNumber(input, new char[]{0xFFFD, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}); + } + + @Override + public String getId() { + return "png"; + } + + @Override + public String getName() { + return "PNG"; + } + + @Override + public String getDescription() { + return Localization.lang("PNG image importer"); + } + + @Override + public FileType getFileType() { + return StandardFileType.PNG; + } + + @Override + protected EntryType getEntryType() { + return BiblatexNonStandardTypes.Image; + } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java index ae4c4fc34c1..9e8f640e5a1 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporter.java @@ -1,4 +1,39 @@ package org.jabref.logic.importer.fileformat.microsoft; -public class RtfImporter { +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class RtfImporter extends TikaImporter { + private static final char[] RTF_MAGIC_NUMBER = new char[]{'{', '\\', 'r', 't', 'f', '1'}; + + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return Constants.hasMagicNumber(input, RTF_MAGIC_NUMBER); + } + + @Override + public String getId() { + return "rtf"; + } + + @Override + public String getName() { + return "RTF"; + } + + @Override + public String getDescription() { + return Localization.lang("Rich Text File importer"); + } + + @Override + public FileType getFileType() { + return StandardFileType.RTF; + } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/misc/TxtImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/misc/TxtImporter.java new file mode 100644 index 00000000000..cd157b34db9 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/misc/TxtImporter.java @@ -0,0 +1,36 @@ +package org.jabref.logic.importer.fileformat.misc; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class TxtImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return true; + } + + @Override + public String getId() { + return "txt"; + } + + @Override + public String getName() { + return "TXT"; + } + + @Override + public String getDescription() { + return Localization.lang("Importer for plain text files"); + } + + @Override + public FileType getFileType() { + return StandardFileType.TXT; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java index a1ceb8315b1..032bf096a4a 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/Constants.java @@ -36,7 +36,7 @@ public static boolean isOleCompound(BufferedReader input) throws IOException { return hasMagicNumber(input, OLE_COMPOUND_MAGIC_NUMBER); } - private static boolean hasMagicNumber(BufferedReader input, char[] magicNumber) throws IOException { + public static boolean hasMagicNumber(BufferedReader input, char[] magicNumber) throws IOException { char[] header = new char[magicNumber.length]; int nRead = input.read(header); return nRead == magicNumber.length && Arrays.equals(header, magicNumber); diff --git a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java index 3b9d5f61cd8..1f1c83b6adb 100644 --- a/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java +++ b/jablib/src/main/java/org/jabref/logic/util/StandardFileType.java @@ -26,6 +26,7 @@ public enum StandardFileType implements FileType { DOCX("Microsoft Word 2007-365", "docx"), ENDNOTE("Endnote", "ref", "enw"), HTML("HTML", "html", "htm"), + JPG("JPG", "jpg", "jpg"), ISI("Isi", "isi", "txt"), JAR("JAR", "jar"), JAVA_KEYSTORE("Java Keystore", "jks"), @@ -38,6 +39,7 @@ public enum StandardFileType implements FileType { ODP("OpenOffice Impress", "odp"), ODS("OpenOffice Calc", "ods"), ODT("OpenOffice Writer", "odt"), + PNG("PNG", "png"), PPT("Microsoft PowerPoint 97-2003", "ppt"), PPTX("Microsoft PowerPoint 2007-365", "pptx"), PDF("PDF", "pdf"), diff --git a/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java b/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java index 99a2e4729d4..881ccb075f0 100644 --- a/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java +++ b/jablib/src/main/java/org/jabref/model/entry/types/BiblatexNonStandardTypes.java @@ -1,4 +1,45 @@ package org.jabref.model.entry.types; -public enum BiblatexNonStandardTypes { +import java.util.Arrays; +import java.util.Locale; +import java.util.Optional; + +public enum BiblatexNonStandardTypes implements EntryType { + Artwork("artwork"), + Audio("audio"), + Bibnote("bibnote"), + Commentary("commentary"), + Image("image"), + Jurisdiction("jurisdiction"), + Legislation("legislation"), + Legal("legal"), + Letter("letter"), + Movie("movie"), + Music("music"), + Performance("performance"), + Review("review"), + Standard("standard"), + Video("video"); + + private final String displayName; + + BiblatexNonStandardTypes(String displayName) { + this.displayName = displayName; + } + + public static Optional fromName(String name) { + return Arrays.stream(BiblatexNonStandardTypes.values()) + .filter(field -> field.getName().equalsIgnoreCase(name)) + .findAny(); + } + + @Override + public String getName() { + return displayName.toLowerCase(Locale.ENGLISH); + } + + @Override + public String getDisplayName() { + return displayName; + } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java index 71e80edc307..eeda335061f 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/TxtImporterTest.java @@ -1,6 +1,6 @@ package org.jabref.logic.importer.fileformat; -import org.jabref.logic.importer.fileformat.microsoft.XlsImporter; +import org.jabref.logic.importer.fileformat.misc.TxtImporter; import org.jabref.logic.util.StandardFileType; import org.junit.jupiter.api.BeforeEach; @@ -9,25 +9,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class TxtImporterTest { - private XlsImporter importer; + private TxtImporter importer; @BeforeEach void setUp() { - importer = new XlsImporter(); + importer = new TxtImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Excel 97-2003", importer.getName()); + assertEquals("TXT", importer.getName()); } @Test void getCLIId() { - assertEquals("xls", importer.getId()); + assertEquals("txt", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.XLS, importer.getFileType()); + assertEquals(StandardFileType.TXT, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java index e5b036048cb..12aa336ccbe 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterFilesTest.java @@ -1,40 +1,33 @@ package org.jabref.logic.importer.fileformat.img; import java.io.IOException; -import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; import org.jabref.logic.importer.ImportException; import org.jabref.logic.importer.fileformat.ImporterTestEngine; -import org.jabref.logic.importer.fileformat.microsoft.DocImporter; -import org.jabref.logic.importer.util.Constants; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -public class DocImporterFilesTest { - private static final String FILE_ENDING = ".doc"; - private static final List EXCLUDE_EXTENSIONS = Constants.OLE_COMPOUND_FILES_EXTENSIONS - .stream() - .filter(ext -> !ext.equals(FILE_ENDING)) - .toList(); +public class JpgImporterFilesTest { + private static final String FILE_ENDING = ".jpg"; - private DocImporter importer; + private JpgImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new JpgImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("DocImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("JpgImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("DocImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("JpgImporterTest") && !name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java index eacc38d2f5d..78839d27bd9 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/JpgImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat.img; -import org.jabref.logic.importer.fileformat.microsoft.DocImporter; import org.jabref.logic.util.StandardFileType; import org.junit.jupiter.api.BeforeEach; @@ -8,26 +7,26 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class DocImporterTest { - private DocImporter importer; +class JpgImporterTest { + private JpgImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new JpgImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Word 97-2003", importer.getName()); + assertEquals("JPG", importer.getName()); } @Test void getCLIId() { - assertEquals("doc", importer.getId()); + assertEquals("jpg", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.DOC, importer.getFileType()); + assertEquals(StandardFileType.JPG, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java index 0d9049bd71a..091cd70c4c1 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterFilesTest.java @@ -12,22 +12,22 @@ import org.junit.jupiter.params.provider.MethodSource; public class PngImporterFilesTest { - private static final String FILE_ENDING = ".jpg"; + private static final String FILE_ENDING = ".png"; - private JpgImporter importer; + private PngImporter importer; @BeforeEach void setUp() { - importer = new JpgImporter(); + importer = new PngImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("JpgImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("PngImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("JpgImporterTest") && !name.endsWith(FILE_ENDING); + Predicate fileName = name -> !name.startsWith("PngImporterTest") && !name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java index 8bcba20744d..afb00dbe214 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/img/PngImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class PngImporterTest { - private JpgImporter importer; + private PngImporter importer; @BeforeEach void setUp() { - importer = new JpgImporter(); + importer = new PngImporter(); } @Test void getFormatName() { - assertEquals("JPG", importer.getName()); + assertEquals("PNG", importer.getName()); } @Test void getCLIId() { - assertEquals("jpg", importer.getId()); + assertEquals("png", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.JPG, importer.getFileType()); + assertEquals(StandardFileType.PNG, importer.getFileType()); } } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java index a762277615f..372c9353435 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterFilesTest.java @@ -14,26 +14,22 @@ import org.junit.jupiter.params.provider.MethodSource; public class RtfImporterFilesTest { - private static final String FILE_ENDING = ".pptx"; - private static final List EXCLUDE_EXTENSIONS = Constants.ZIP_FILES_EXTENSIONS - .stream() - .filter(ext -> !ext.equals(FILE_ENDING)) - .toList(); + private static final String FILE_ENDING = ".rtf"; - private PptxImporter importer; + private RtfImporter importer; @BeforeEach void setUp() { - importer = new PptxImporter(); + importer = new RtfImporter(); } private static Stream fileNames() throws IOException { - Predicate fileName = name -> name.startsWith("PptxImporterTest") && name.endsWith(FILE_ENDING); + Predicate fileName = name -> name.startsWith("RtfImporterTest") && name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } private static Stream invalidFileNames() throws IOException { - Predicate fileName = name -> !name.startsWith("PptxImporterTest") && EXCLUDE_EXTENSIONS.stream().noneMatch(name::endsWith); + Predicate fileName = name -> !name.startsWith("RtfImporterTest") && !name.endsWith(FILE_ENDING); return ImporterTestEngine.getTestFiles(fileName).stream(); } diff --git a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java index 1b7efb6ce02..cb4b540511b 100644 --- a/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java +++ b/jablib/src/test/java/org/jabref/logic/importer/fileformat/microsoft/RtfImporterTest.java @@ -8,25 +8,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class RtfImporterTest { - private DocImporter importer; + private RtfImporter importer; @BeforeEach void setUp() { - importer = new DocImporter(); + importer = new RtfImporter(); } @Test void getFormatName() { - assertEquals("Microsoft Word 97-2003", importer.getName()); + assertEquals("RTF", importer.getName()); } @Test void getCLIId() { - assertEquals("doc", importer.getId()); + assertEquals("rtf", importer.getId()); } @Test void sGetExtensions() { - assertEquals(StandardFileType.DOC, importer.getFileType()); + assertEquals(StandardFileType.RTF, importer.getFileType()); } } From a5c006b21cff24e31d2e38898cd8f41e265842c6 Mon Sep 17 00:00:00 2001 From: InAnYan Date: Sun, 15 Jun 2025 03:26:44 +0300 Subject: [PATCH 12/13] feat(importers/docs): scaffold book importers --- .../fileformat/books/DjvuImporter.java | 42 +++++++++++++++++++ .../fileformat/books/Fb2Importer.java | 40 ++++++++++++++++++ .../jabref/logic/util/StandardFileType.java | 5 ++- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/books/DjvuImporter.java create mode 100644 jablib/src/main/java/org/jabref/logic/importer/fileformat/books/Fb2Importer.java diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/DjvuImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/DjvuImporter.java new file mode 100644 index 00000000000..78f79622dd0 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/DjvuImporter.java @@ -0,0 +1,42 @@ +package org.jabref.logic.importer.fileformat.books; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class DjvuImporter extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + // DJVU start with "AT&TFORM" and then "DJVU" some time after that. + + char[] buffer = new char[64]; + int read = input.read(buffer, 0, buffer.length); + input.reset(); + String header = new String(buffer, 0, read); + return header.startsWith("AT&TFORM") && header.contains("DJVU"); + } + + @Override + public String getId() { + return "djvu"; + } + + @Override + public String getName() { + return "DjVu"; + } + + @Override + public String getDescription() { + return Localization.lang("Import DjVu files"); + } + + @Override + public FileType getFileType() { + return StandardFileType.DJVU; + } +} diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/Fb2Importer.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/Fb2Importer.java new file mode 100644 index 00000000000..1aa02c0f577 --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/books/Fb2Importer.java @@ -0,0 +1,40 @@ +package org.jabref.logic.importer.fileformat.books; + +import java.io.BufferedReader; +import java.io.IOException; + +import org.jabref.logic.importer.TikaImporter; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.FileType; +import org.jabref.logic.util.StandardFileType; + +public class Fb2Importer extends TikaImporter { + @Override + public boolean isRecognizedFormat(BufferedReader input) throws IOException { + return input.lines() + .map(String::trim) + .anyMatch(line -> line.startsWith(" Date: Sun, 15 Jun 2025 16:49:34 +0300 Subject: [PATCH 13/13] refactor(importer/docs): add `TikaMetadataParser` class and abstract away common methods --- .../jabref/logic/importer/TikaImporter.java | 139 ++++-------------- .../importer/fileformat/img/JpgImporter.java | 6 +- .../importer/fileformat/img/PngImporter.java | 10 +- .../importer/fileformat/odf/OdfImporter.java | 13 ++ .../importer/util/TikaMetadataParser.java | 132 +++++++++++++++++ .../java/org/jabref/model/entry/BibEntry.java | 21 ++- .../model/entry/identifier/Identifier.java | 2 +- .../java/org/jabref/model/util/ListUtil.java | 7 + 8 files changed, 213 insertions(+), 117 deletions(-) create mode 100644 jablib/src/main/java/org/jabref/logic/importer/util/TikaMetadataParser.java diff --git a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java index f899ab35dca..d164f201da9 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/TikaImporter.java @@ -5,44 +5,29 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; +import org.jabref.logic.importer.util.TikaMetadataParser; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; -import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.StandardEntryType; -import org.jabref.model.strings.StringUtil; import org.apache.tika.exception.TikaException; import org.apache.tika.metadata.Metadata; -import org.apache.tika.metadata.Property; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.sax.BodyContentHandler; -import org.jetbrains.annotations.NotNull; import org.xml.sax.SAXException; /** * Common class for all file importers that use Apache Tika to extract metadata from files. *

- * Child classes should implement the rest of {@link Importer}. + * Child classes should implement the rest of {@link Importer} and method {@link #extractMetadata(TikaMetadataParser, String)} to extract the {@link BibEntry} from the Tika metadata. + *

+ * In case you need to use a specific Tika parser, you can override {@link #getTikaParser()} to return a different parser instance. */ public abstract class TikaImporter extends Importer { - private final static Pattern imageDatePattern = Pattern.compile("(year|month|day|hour|minute|second)=(\\d+)"); - @Override public ParserResult importDatabase(BufferedReader input) throws IOException { throw new UnsupportedOperationException("TikaImporter (and descendants) do not support importDatabase(BufferedReader reader)." @@ -62,7 +47,11 @@ public ParserResult importDatabase(Path filePath) throws IOException { parser.parse(inputStream, handler, metadata, parseContext); String fileName = FileUtil.getBaseName(filePath); - BibEntry entry = extractMetadata(metadata, fileName); + BibEntry entry = extractMetadata(new TikaMetadataParser(metadata)); + + if (!entry.hasField(StandardField.TITLE)) { + entry.setField(StandardField.TITLE, fileName); + } return ParserResult.fromEntry(entry); } catch (SAXException | TikaException e) { @@ -71,105 +60,35 @@ public ParserResult importDatabase(Path filePath) throws IOException { } protected Parser getTikaParser() { - // Use {@link AutoDetectParser} by default, subclasses can override this method to provide a different parser return new AutoDetectParser(); } - protected EntryType getEntryType() { - // Default to `Misc`, subclasses should override this method if they have a specific entry type - return StandardEntryType.Misc; - } - - private BibEntry extractMetadata(Metadata metadata, String titleReplacement) { - String title = Optional.ofNullable(metadata.get("dc:title")).orElse(titleReplacement); - Optional date = extractDate(metadata); - List authors = extractAuthors(metadata); - - Optional year = date.map(d -> { - Calendar cal = Calendar.getInstance(); - cal.setTime(d); - return Integer.toString(cal.get(Calendar.YEAR)); - }); - - Optional dateIso = date.map(d -> { - LocalDate localDate = d.toInstant() - .atZone(ZoneId.systemDefault()) - .toLocalDate(); - - return localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); - }); - - Optional month = date.map(d -> { - LocalDate localDate = d.toInstant() - .atZone(ZoneId.systemDefault()) - .toLocalDate(); - - String[] bibtexMonths = { - "jan", "feb", "mar", "apr", "may", "jun", - "jul", "aug", "sep", "oct", "nov", "dec" - }; - - return bibtexMonths[localDate.getMonthValue() - 1]; - }); - - return new BibEntry(getEntryType()) - .withField(StandardField.TITLE, title) - .withField(StandardField.AUTHOR, !authors.isEmpty() - ? Optional.of(String.join(" and ", authors)) - : Optional.empty()) - .withField(StandardField.YEAR, year) - .withField(StandardField.DATE, dateIso) - .withField(StandardField.MONTH, month); - } - - private static List extractAuthors(Metadata metadata) { - List creators = Arrays.stream(metadata.getValues("dc:creator")) - .filter(StringUtil::isNotBlank) - .toList(); - List contributors = Arrays.stream(metadata.getValues("dc:contributor")) - .filter(StringUtil::isNotBlank) - .toList(); - - return Stream.concat(creators.stream(), contributors.stream()).toList(); - } + /** + * Extracts common metadata from the given Tika metadata object and returns a {@link BibEntry}. + *

+ * This function will add fields that are most standard and common across different file types. Inheritors are + * recommended to override {@link TikaImporter#extractAdditionalMetadata(BibEntry, TikaMetadataParser)} + * process additional metadata that is specific to the file type they are importing. + */ + protected final BibEntry extractMetadata(Metadata metadata) { + TikaMetadataParser metadataParser = new TikaMetadataParser(metadata); - private static Optional extractDate(Metadata metadata) { - Optional date = Optional.ofNullable(metadata.getDate(Property.internalDate("dcterms:created"))); + BibEntry entry = new BibEntry(StandardEntryType.Misc) + .withField(StandardField.TITLE, metadataParser.getDcTitle()) + .withField(StandardField.AUTHOR, TikaMetadataParser.formatBibtexAuthors(metadataParser.getDcCreators())); - if (date.isEmpty()) { - Optional dateEntry = Optional.ofNullable(metadata.get("tIME")) - .or(() -> Optional.ofNullable(metadata.get("Document ImageModificationTime"))); + metadataParser.getDcTermsCreated().ifPresent(date -> TikaMetadataParser.addDateCreated(entry, date)); - if (dateEntry.isPresent()) { - date = Optional.of(parseDateForImages(dateEntry.get())); - } - } + extractAdditionalMetadata(entry, metadataParser); - return date; + return entry; } - private static Date parseDateForImages(String dateString) { - Matcher matcher = imageDatePattern.matcher(dateString); - - int year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0; - - while (matcher.find()) { - String key = matcher.group(1); - int value = Integer.parseInt(matcher.group(2)); - - switch (key) { - case "year" -> year = value; - case "month" -> month = value; - case "day" -> day = value; - case "hour" -> hour = value; - case "minute" -> minute = value; - case "second" -> second = value; - } - } - - Calendar calendar = Calendar.getInstance(); - calendar.set(year, month, day, hour, minute, second); + /** + * Extracts additional metadata that is specific to the file type being imported. Inheritors are allowed to mutate + * the given {@link BibEntry} to add more fields or modify existing ones. + */ + protected void extractAdditionalMetadata(BibEntry entry, TikaMetadataParser metadataParser) { - return calendar.getTime(); } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java index fbe10c69a57..99323e52493 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/JpgImporter.java @@ -5,9 +5,11 @@ import org.jabref.logic.importer.TikaImporter; import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.importer.util.TikaMetadataParser; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.types.BiblatexNonStandardTypes; import org.jabref.model.entry.types.EntryType; @@ -38,7 +40,7 @@ public FileType getFileType() { } @Override - protected EntryType getEntryType() { - return BiblatexNonStandardTypes.Image; + protected void extractAdditionalMetadata(BibEntry entry, TikaMetadataParser metadataParser) { + entry.setType(BiblatexNonStandardTypes.Image); } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java index 29b685db5d7..912a5e5226e 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/img/PngImporter.java @@ -5,9 +5,11 @@ import org.jabref.logic.importer.TikaImporter; import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.importer.util.TikaMetadataParser; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.types.BiblatexNonStandardTypes; import org.jabref.model.entry.types.EntryType; @@ -38,7 +40,11 @@ public FileType getFileType() { } @Override - protected EntryType getEntryType() { - return BiblatexNonStandardTypes.Image; + protected void extractAdditionalMetadata(BibEntry entry, TikaMetadataParser metadataParser) { + entry.setType(BiblatexNonStandardTypes.Image); + + metadataParser + .getPngCreationTime() + .ifPresent(date -> TikaMetadataParser.addDateCreated(entry, date)); } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java index 3cf4963d888..8e5fef010b3 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java +++ b/jablib/src/main/java/org/jabref/logic/importer/fileformat/odf/OdfImporter.java @@ -2,9 +2,15 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.List; import org.jabref.logic.importer.TikaImporter; import org.jabref.logic.importer.util.Constants; +import org.jabref.logic.importer.util.TikaMetadataParser; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.model.util.ListUtil; /** * General importer for Open Document Format files. @@ -14,4 +20,11 @@ public abstract class OdfImporter extends TikaImporter { public boolean isRecognizedFormat(BufferedReader input) throws IOException { return Constants.isZip(input); } + + @Override + protected void extractAdditionalMetadata(BibEntry entry, TikaMetadataParser metadataParser) { + List authors = ListUtil.concat(metadataParser.getDcCreators(), metadataParser.getDcContributors()); + + entry.setField(StandardField.AUTHOR, TikaMetadataParser.formatBibtexAuthors(authors)); + } } diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/TikaMetadataParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/TikaMetadataParser.java new file mode 100644 index 00000000000..0b32d911d2b --- /dev/null +++ b/jablib/src/main/java/org/jabref/logic/importer/util/TikaMetadataParser.java @@ -0,0 +1,132 @@ +package org.jabref.logic.importer.util; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.strings.StringUtil; + +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.Property; + +public class TikaMetadataParser { + private final static Pattern imageDatePattern = Pattern.compile("(year|month|day|hour|minute|second)=(\\d+)"); + + private final Metadata metadata; + + public TikaMetadataParser(Metadata metadata) { + this.metadata = metadata; + } + + public Optional getDcTitle() { + return Optional.ofNullable(metadata.get("dc:title")); + } + + public Optional getDcTermsCreated() { + return Optional.ofNullable( + metadata.getDate( + Property.internalDate("dcterms:created") + ) + ); + } + + public Optional getPngCreationTime() { + return Optional.ofNullable(metadata.get("tIME")) + .or(() -> Optional.ofNullable(metadata.get("Document ImageModificationTime"))) + .map(TikaMetadataParser::parseDateForImages); + } + + private static Date parseDateForImages(String dateString) { + Matcher matcher = imageDatePattern.matcher(dateString); + + int year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0; + + while (matcher.find()) { + String key = matcher.group(1); + int value = Integer.parseInt(matcher.group(2)); + + switch (key) { + case "year" -> year = value; + case "month" -> month = value; + case "day" -> day = value; + case "hour" -> hour = value; + case "minute" -> minute = value; + case "second" -> second = value; + } + } + + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month, day, hour, minute, second); + + return calendar.getTime(); + } + + public Optional getDcIdentifier() { + return Optional.ofNullable(metadata.get("dc:identifier")); + } + + public List getDcCreators() { + return Arrays.stream(metadata.getValues("dc:creator")) + .filter(StringUtil::isNotBlank) + .toList(); + } + + public List getDcContributors() { + return Arrays.stream(metadata.getValues("dc:creator")) + .filter(StringUtil::isNotBlank) + .toList(); + } + + public static String extractYearFromDate(Date date) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return Integer.toString(cal.get(Calendar.YEAR)); + } + + public static String extractBibtexMonthFromDate(Date date) { + LocalDate localDate = date.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + String[] bibtexMonths = { + "jan", "feb", "mar", "apr", "may", "jun", + "jul", "aug", "sep", "oct", "nov", "dec" + }; + + return bibtexMonths[localDate.getMonthValue() - 1]; + } + + public static String formatBibtexDate(Date date) { + LocalDate localDate = date.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + return localDate.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE); + } + + public static Optional formatBibtexAuthors(List authors) { + if (authors.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(String.join(" and ", authors)); + } + + /** + * Adds year, month, and date fields to a BibEntry based on the provided date. Mutates the given object. + */ + public static BibEntry addDateCreated(BibEntry entry, Date date) { + return entry + .withField(StandardField.YEAR, extractYearFromDate(date)) + .withField(StandardField.MONTH, extractBibtexMonthFromDate(date)) + .withField(StandardField.DATE, formatBibtexDate(date)); + } +} diff --git a/jablib/src/main/java/org/jabref/model/entry/BibEntry.java b/jablib/src/main/java/org/jabref/model/entry/BibEntry.java index 5d8115a4442..c98a66bedec 100644 --- a/jablib/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/jablib/src/main/java/org/jabref/model/entry/BibEntry.java @@ -645,6 +645,17 @@ public Optional setField(Field field, String value) { return setField(field, value, EntriesEventSource.LOCAL); } + /** + * Set a field and notify listeners about the change if the value is present. Otherwise, do nothing. + */ + public Optional setField(Field field, Optional value) { + if (value.isPresent()) { + return setField(field, value.get()); + } + + return Optional.empty(); + } + /** * Remove the mapping for the field name, and notify listeners about the change. * @@ -963,16 +974,22 @@ public void unregisterListener(Object object) { } } + public BibEntry withType(EntryType type) { + setType(type); + this.setChanged(true); + return this; + } + public BibEntry withField(Field field, String value) { setField(field, value); - this.setChanged(false); + this.setChanged(true); return this; } public BibEntry withField(Field field, Optional value) { value.ifPresent(v -> { setField(field, v); - this.setChanged(false); + this.setChanged(true); }); return this; } diff --git a/jablib/src/main/java/org/jabref/model/entry/identifier/Identifier.java b/jablib/src/main/java/org/jabref/model/entry/identifier/Identifier.java index d17ce6270bb..60036677eab 100644 --- a/jablib/src/main/java/org/jabref/model/entry/identifier/Identifier.java +++ b/jablib/src/main/java/org/jabref/model/entry/identifier/Identifier.java @@ -27,7 +27,7 @@ public interface Identifier { Optional getExternalURI(); - public static Optional from(String identifier) { + static Optional from(String identifier) { if (StringUtil.isBlank(identifier)) { return Optional.empty(); } diff --git a/jablib/src/main/java/org/jabref/model/util/ListUtil.java b/jablib/src/main/java/org/jabref/model/util/ListUtil.java index 207fab5c3d1..3eecb1bbb23 100644 --- a/jablib/src/main/java/org/jabref/model/util/ListUtil.java +++ b/jablib/src/main/java/org/jabref/model/util/ListUtil.java @@ -48,4 +48,11 @@ public static Stream getLinkedFiles(Iterable entries) { .flatMap(List::stream) .distinct(); } + + /** + * Concatenate two {@link List}s. Does not modify the original lists. + */ + public static List concat(List first, List second) { + return Stream.concat(first.stream(), second.stream()).toList(); + } }