From 1d3a3ac75c5501e93c58cf51a2593fc797b737c0 Mon Sep 17 00:00:00 2001 From: subhramit Date: Fri, 5 Apr 2024 17:54:51 +0530 Subject: [PATCH 01/78] Fix LICENSE link --- src/main/java/org/jabref/gui/help/AboutDialogViewModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java index 9d37b661a29..8283945ea1d 100644 --- a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java +++ b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java @@ -28,7 +28,7 @@ public class AboutDialogViewModel extends AbstractViewModel { private static final String DONATION_URL = "https://donations.jabref.org"; private static final String LIBRARIES_URL = "https://github.com/JabRef/jabref/blob/main/external-libraries.md"; private static final String GITHUB_URL = "https://github.com/JabRef/jabref"; - private static final String LICENSE_URL = "https://github.com/JabRef/jabref/blob/main/LICENSE.md"; + private static final String LICENSE_URL = "https://github.com/JabRef/jabref/blob/main/LICENSE"; private static final String CONTRIBUTORS_URL = "https://github.com/JabRef/jabref/graphs/contributors"; private static final String PRIVACY_POLICY_URL = "https://github.com/JabRef/jabref/blob/main/PRIVACY.md"; private final String changelogUrl; From 316753f93a5e633d05834c02f2c0be846c978fe5 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 7 Apr 2024 06:18:23 +0530 Subject: [PATCH 02/78] Add Endnote XML Exporter --- .../logic/exporter/EndnoteXmlExporter.java | 199 ++++++++++++++++++ .../logic/exporter/ExporterFactory.java | 2 + 2 files changed, 201 insertions(+) create mode 100644 src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java new file mode 100644 index 00000000000..13ca00eb23f --- /dev/null +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -0,0 +1,199 @@ +package org.jabref.logic.exporter; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.jabref.logic.util.StandardFileType; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.EntryType; +import org.jabref.model.entry.types.IEEETranEntryType; +import org.jabref.model.entry.types.StandardEntryType; + +public class EndnoteXmlExporter extends Exporter { + + private static final String ENDNOTE_XML_VERSION = "20.1"; + private static final String ENDNOTE_NAMESPACE_URI = "http://www.endnote.com/ns/ENdnx"; + private static final Map EXPORT_ITEM_TYPE = Map.ofEntries( + Map.entry(StandardEntryType.Article, "Journal Article"), + Map.entry(StandardEntryType.Book, "Book"), + Map.entry(StandardEntryType.InBook, "Book Section"), + Map.entry(StandardEntryType.InProceedings, "Conference Proceedings"), + Map.entry(StandardEntryType.InCollection, "Book Section"), + Map.entry(StandardEntryType.MastersThesis, "Thesis"), + Map.entry(StandardEntryType.PhdThesis, "Thesis"), + Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), + Map.entry(StandardEntryType.TechReport, "Report"), + Map.entry(StandardEntryType.Unpublished, "Manuscript"), + Map.entry(IEEETranEntryType.Patent, "Patent"), + Map.entry(StandardEntryType.Online, "Web Page"), + Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), + Map.entry(StandardEntryType.Article, "Newspaper Article") + ); + private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> Integer.toString(EXPORT_ITEM_TYPE.entrySet().stream() + .map(Map.Entry::getValue) + .collect(Collectors.toList()) + .indexOf(entry.getValue()) + 1))); + + public EndnoteXmlExporter() { + super("endnote", "EndNote XML", StandardFileType.XML); + } + + @Override + public void export(BibDatabaseContext databaseContext, Path file, List entries) throws Exception { + Objects.requireNonNull(databaseContext); + Objects.requireNonNull(file); + Objects.requireNonNull(entries); + + if (entries.isEmpty()) { + return; + } + + try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { + XMLOutputFactory xof = XMLOutputFactory.newFactory(); + XMLStreamWriter xml = xof.createXMLStreamWriter(writer); + xml.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0"); + xml.writeStartElement("xml"); + xml.writeStartElement("records"); + + for (BibEntry entry : entries) { + writeEntry(entry, xml); + } + + xml.writeEndElement(); // records + xml.writeEndElement(); // xml + xml.writeEndDocument(); + xml.close(); + } catch ( + IOException | + XMLStreamException e) { + throw new SaveException(e); + } + } + + private void writeEntry(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + xml.writeStartElement("record"); + + writeField(xml, "database", "endnote.enl"); + writeField(xml, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); + writeField(xml, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); + + writeContributors(entry, xml); + writeTitles(entry, xml); + writeField(xml, "periodical", entry.getField(StandardField.JOURNAL).orElse("")); + writeField(xml, "pages", entry.getField(StandardField.PAGES).orElse("")); + writeField(xml, "volume", entry.getField(StandardField.VOLUME).orElse("")); + writeField(xml, "number", entry.getField(StandardField.NUMBER).orElse("")); + writeField(xml, "issue", entry.getField(StandardField.ISSUE).orElse("")); + writeField(xml, "keywords", entry.getField(StandardField.KEYWORDS).orElse("")); + writeDates(entry, xml); + writeField(xml, "pub-location", entry.getField(StandardField.ADDRESS).orElse("")); + writeField(xml, "publisher", entry.getField(StandardField.PUBLISHER).orElse("")); + writeField(xml, "isbn", entry.getField(StandardField.ISBN).orElse("")); + writeField(xml, "electronic-resource-num", entry.getField(StandardField.DOI).orElse("")); + writeField(xml, "abstract", entry.getField(StandardField.ABSTRACT).orElse("")); + writeField(xml, "label", entry.getCitationKey().orElse("")); + writeField(xml, "notes", entry.getField(StandardField.NOTE).orElse("")); + writeUrls(entry, xml); + + xml.writeEndElement(); // record + } + + private void writeField(XMLStreamWriter xml, String name, String value) throws XMLStreamException { + xml.writeStartElement(name); + xml.writeCharacters(value); + xml.writeEndElement(); + } + + private void writeField(XMLStreamWriter xml, String name, String value, Map attributes) throws XMLStreamException { + xml.writeStartElement(name); + attributes.forEach((attr, attrValue) -> { + try { + xml.writeAttribute(attr, attrValue); + } catch ( + XMLStreamException e) { + // Ignore exception and continue + } + }); + xml.writeCharacters(value); + xml.writeEndElement(); + } + + private void writeContributors(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + xml.writeStartElement("contributors"); + writeAuthors(entry, xml, StandardField.AUTHOR, "authors"); + writeAuthors(entry, xml, StandardField.EDITOR, "secondary-authors"); + xml.writeEndElement(); // contributors + } + + private void writeAuthors(BibEntry entry, XMLStreamWriter xml, Field field, String elementName) throws XMLStreamException { + entry.getField(field).ifPresent(authors -> { + try { + xml.writeStartElement(elementName); + for (String author : authors.split("and")) { + xml.writeStartElement("author"); + xml.writeCharacters(author.trim()); + xml.writeEndElement(); // author + } + xml.writeEndElement(); // elementName + } catch ( + XMLStreamException e) { + // Ignore exception and continue + } + }); + } + + private void writeTitles(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + xml.writeStartElement("titles"); + writeField(xml, "title", entry.getField(StandardField.TITLE).orElse("")); + writeField(xml, "secondary-title", entry.getField(StandardField.BOOKTITLE).orElse("")); + writeField(xml, "short-title", entry.getField(StandardField.SHORTTITLE).orElse("")); + xml.writeEndElement(); // titles + } + + private void writeDates(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + xml.writeStartElement("dates"); + entry.getField(StandardField.YEAR).ifPresent(year -> { + try { + xml.writeStartElement("year"); + xml.writeCharacters(year); + xml.writeEndElement(); // year + } catch ( + XMLStreamException e) { + // Ignore exception and continue + } + }); + xml.writeEndElement(); // dates + } + + private void writeUrls(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + xml.writeStartElement("urls"); + entry.getField(StandardField.URL).ifPresent(url -> { + try { + xml.writeStartElement("web-urls"); + xml.writeStartElement("url"); + xml.writeCharacters(url); + xml.writeEndElement(); // url + xml.writeEndElement(); // web-urls + } catch ( + XMLStreamException e) { + // Ignore exception and continue + } + }); + xml.writeEndElement(); // urls + } +} diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 23c374c3b87..fc0a4eeea70 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -55,6 +55,7 @@ public static ExporterFactory create(PreferencesService preferencesService, exporters.add(new TemplateExporter("MIS Quarterly", "misq", "misq", "misq", StandardFileType.RTF, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter("CSL YAML", "yaml", "yaml", null, StandardFileType.YAML, layoutPreferences, saveOrder, BlankLineBehaviour.DELETE_BLANKS)); exporters.add(new TemplateExporter("Hayagriva YAML", "hayagrivayaml", "hayagrivayaml", null, StandardFileType.YAML, layoutPreferences, saveOrder, BlankLineBehaviour.DELETE_BLANKS)); + exporters.add(new TemplateExporter("Endnote XML", "endnotexml", "Endnote XML", "endnotexml", StandardFileType.XML, layoutPreferences, saveOrder)); exporters.add(new OpenOfficeDocumentCreator()); exporters.add(new OpenDocumentSpreadsheetCreator()); exporters.add(new MSBibExporter()); @@ -63,6 +64,7 @@ public static ExporterFactory create(PreferencesService preferencesService, exporters.add(new XmpPdfExporter(xmpPreferences)); exporters.add(new EmbeddedBibFilePdfExporter(bibDatabaseMode, entryTypesManager, fieldPreferences)); exporters.add(new CffExporter()); + exporters.add(new EndnoteXmlExporter()); // Now add custom export formats exporters.addAll(customFormats); From 5da187abe9bc85ef4de4780273c8e39c2ab1a181 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 7 Apr 2024 15:00:14 +0530 Subject: [PATCH 03/78] Fix Exporter and Importer - stage 1 --- .../logic/exporter/EndnoteXmlExporter.java | 177 ++++++++++-------- .../fileformat/EndnoteXmlImporter.java | 7 +- 2 files changed, 104 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 13ca00eb23f..fa1a0c6fa8a 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import javax.xml.stream.XMLOutputFactory; @@ -17,7 +18,6 @@ import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; @@ -31,8 +31,9 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), Map.entry(StandardEntryType.InBook, "Book Section"), - Map.entry(StandardEntryType.InProceedings, "Conference Proceedings"), Map.entry(StandardEntryType.InCollection, "Book Section"), + Map.entry(StandardEntryType.InProceedings, "Conference Paper"), + Map.entry(StandardEntryType.Conference, "Conference"), Map.entry(StandardEntryType.MastersThesis, "Thesis"), Map.entry(StandardEntryType.PhdThesis, "Thesis"), Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), @@ -41,8 +42,9 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(IEEETranEntryType.Patent, "Patent"), Map.entry(StandardEntryType.Online, "Web Page"), Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), - Map.entry(StandardEntryType.Article, "Newspaper Article") + Map.entry(StandardEntryType.Misc, "Generic") ); + private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, entry -> Integer.toString(EXPORT_ITEM_TYPE.entrySet().stream() .map(Map.Entry::getValue) @@ -78,9 +80,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List xml.writeEndElement(); // xml xml.writeEndDocument(); xml.close(); - } catch ( - IOException | - XMLStreamException e) { + } catch (IOException | XMLStreamException e) { throw new SaveException(e); } } @@ -88,96 +88,105 @@ public void export(BibDatabaseContext databaseContext, Path file, List private void writeEntry(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { xml.writeStartElement("record"); - writeField(xml, "database", "endnote.enl"); + // Write the necessary fields and elements + writeField(xml, "database", "endnote.enl", Map.of("name", "My EndNote Library.enl", "path", "/path/to/My EndNote Library.enl")); writeField(xml, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); + writeField(xml, "rec-number", String.valueOf(entry.getId()), null); + + xml.writeStartElement("foreign-keys"); + xml.writeStartElement("key"); + xml.writeAttribute("app", "EN"); + xml.writeCharacters(String.valueOf(entry.getId())); + xml.writeEndElement(); // key + xml.writeEndElement(); // foreign-keys + writeField(xml, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); writeContributors(entry, xml); - writeTitles(entry, xml); - writeField(xml, "periodical", entry.getField(StandardField.JOURNAL).orElse("")); - writeField(xml, "pages", entry.getField(StandardField.PAGES).orElse("")); - writeField(xml, "volume", entry.getField(StandardField.VOLUME).orElse("")); - writeField(xml, "number", entry.getField(StandardField.NUMBER).orElse("")); - writeField(xml, "issue", entry.getField(StandardField.ISSUE).orElse("")); - writeField(xml, "keywords", entry.getField(StandardField.KEYWORDS).orElse("")); - writeDates(entry, xml); - writeField(xml, "pub-location", entry.getField(StandardField.ADDRESS).orElse("")); - writeField(xml, "publisher", entry.getField(StandardField.PUBLISHER).orElse("")); - writeField(xml, "isbn", entry.getField(StandardField.ISBN).orElse("")); - writeField(xml, "electronic-resource-num", entry.getField(StandardField.DOI).orElse("")); - writeField(xml, "abstract", entry.getField(StandardField.ABSTRACT).orElse("")); - writeField(xml, "label", entry.getCitationKey().orElse("")); - writeField(xml, "notes", entry.getField(StandardField.NOTE).orElse("")); - writeUrls(entry, xml); + writeField(xml, "titles", null, Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); + writeField(xml, "periodical", null, Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); + writeField(xml, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); + writeField(xml, "pages", entry.getField(StandardField.PAGES).orElse(""), null); + writeField(xml, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); + writeField(xml, "number", entry.getField(StandardField.NUMBER).orElse(""), null); + writeField(xml, "dates", null, Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); + writeField(xml, "publisher", entry.getField(StandardField.PUBLISHER).orElse(""), null); + writeField(xml, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); + writeField(xml, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); + writeField(xml, "notes", entry.getField(StandardField.NOTE).orElse(""), null); + writeField(xml, "urls", null, Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); + writeField(xml, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); xml.writeEndElement(); // record } - private void writeField(XMLStreamWriter xml, String name, String value) throws XMLStreamException { - xml.writeStartElement(name); - xml.writeCharacters(value); - xml.writeEndElement(); + private void writeField(XMLStreamWriter xml, String name, String value, Map attributes) throws XMLStreamException { + if (value != null && !value.isEmpty()) { + xml.writeStartElement(name); + if (attributes != null) { + for (Map.Entry attribute : attributes.entrySet()) { + xml.writeAttribute(attribute.getKey(), attribute.getValue()); + } + } + xml.writeStartElement("style"); + xml.writeAttribute("face", "normal"); + xml.writeAttribute("font", "default"); + xml.writeAttribute("size", "100%"); + xml.writeCharacters(value); + xml.writeEndElement(); // style + xml.writeEndElement(); // name + } } - private void writeField(XMLStreamWriter xml, String name, String value, Map attributes) throws XMLStreamException { + private void writeField(XMLStreamWriter xml, String name, String value, Map attributes, String childValue, String childElementName) throws XMLStreamException { xml.writeStartElement(name); - attributes.forEach((attr, attrValue) -> { - try { - xml.writeAttribute(attr, attrValue); - } catch ( - XMLStreamException e) { - // Ignore exception and continue + if (attributes != null) { + for (Map.Entry attribute : attributes.entrySet()) { + xml.writeAttribute(attribute.getKey(), attribute.getValue()); } - }); - xml.writeCharacters(value); - xml.writeEndElement(); + } + if (childValue != null && !childValue.isEmpty()) { + xml.writeStartElement(childElementName); + xml.writeStartElement("style"); + xml.writeAttribute("face", "normal"); + xml.writeAttribute("font", "default"); + xml.writeAttribute("size", "100%"); + xml.writeCharacters(childValue); + xml.writeEndElement(); // style + xml.writeEndElement(); // childElementName + } + xml.writeEndElement(); // name } private void writeContributors(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - xml.writeStartElement("contributors"); - writeAuthors(entry, xml, StandardField.AUTHOR, "authors"); - writeAuthors(entry, xml, StandardField.EDITOR, "secondary-authors"); - xml.writeEndElement(); // contributors - } - - private void writeAuthors(BibEntry entry, XMLStreamWriter xml, Field field, String elementName) throws XMLStreamException { - entry.getField(field).ifPresent(authors -> { - try { - xml.writeStartElement(elementName); - for (String author : authors.split("and")) { - xml.writeStartElement("author"); - xml.writeCharacters(author.trim()); - xml.writeEndElement(); // author - } - xml.writeEndElement(); // elementName - } catch ( - XMLStreamException e) { - // Ignore exception and continue + Optional authors = entry.getField(StandardField.AUTHOR); + if (authors.isPresent()) { + xml.writeStartElement("contributors"); + xml.writeStartElement("authors"); + for (String author : authors.get().split("and")) { + xml.writeStartElement("author"); + xml.writeStartElement("style"); + xml.writeAttribute("face", "normal"); + xml.writeAttribute("font", "default"); + xml.writeAttribute("size", "100%"); + xml.writeCharacters(author.trim()); + xml.writeEndElement(); // style + xml.writeEndElement(); // author } - }); - } - - private void writeTitles(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - xml.writeStartElement("titles"); - writeField(xml, "title", entry.getField(StandardField.TITLE).orElse("")); - writeField(xml, "secondary-title", entry.getField(StandardField.BOOKTITLE).orElse("")); - writeField(xml, "short-title", entry.getField(StandardField.SHORTTITLE).orElse("")); - xml.writeEndElement(); // titles + xml.writeEndElement(); // authors + xml.writeEndElement(); // contributors + } } private void writeDates(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - xml.writeStartElement("dates"); - entry.getField(StandardField.YEAR).ifPresent(year -> { - try { - xml.writeStartElement("year"); - xml.writeCharacters(year); - xml.writeEndElement(); // year - } catch ( - XMLStreamException e) { - // Ignore exception and continue - } - }); - xml.writeEndElement(); // dates + Optional year = entry.getField(StandardField.YEAR); + if (year.isPresent()) { + xml.writeStartElement("dates"); + xml.writeStartElement("year"); + xml.writeCharacters(year.get()); + xml.writeEndElement(); // year + xml.writeEndElement(); // dates + } } private void writeUrls(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { @@ -189,8 +198,18 @@ private void writeUrls(BibEntry entry, XMLStreamWriter xml) throws XMLStreamExce xml.writeCharacters(url); xml.writeEndElement(); // url xml.writeEndElement(); // web-urls - } catch ( - XMLStreamException e) { + } catch (XMLStreamException e) { + // Ignore exception and continue + } + }); + entry.getField(StandardField.FILE).ifPresent(file -> { + try { + xml.writeStartElement("file-urls"); + xml.writeStartElement("url"); + xml.writeCharacters(file); + xml.writeEndElement(); // url + xml.writeEndElement(); // file-urls + } catch (XMLStreamException e) { // Ignore exception and continue } }); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 0e05618632a..5bbdde5d5e6 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -158,6 +158,9 @@ private void parseRecord(XMLStreamReader reader, List bibItems, String case "number" -> { parseStyleContent(reader, fields, StandardField.NUMBER, elementName); } + case "tertiary-title" -> { + parseStyleContent(reader, fields, StandardField.BOOKTITLE, elementName); + } case "dates" -> { parseYear(reader, fields); } @@ -207,7 +210,9 @@ private static EntryType convertRefNameToType(String refName) { case "book section" -> StandardEntryType.InBook; case "book" -> StandardEntryType.Book; case "report" -> StandardEntryType.Report; - // case "journal article" -> StandardEntryType.Article; + case "conference paper" -> StandardEntryType.InProceedings; + case "conference" -> StandardEntryType.Conference; + case "conference proceedings" -> StandardEntryType.Proceedings; default -> StandardEntryType.Article; }; } From 1b211e84bdf1bf42522bfc3133900cadc062c445 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 7 Apr 2024 19:01:37 +0530 Subject: [PATCH 04/78] Review changes-1 --- .../logic/exporter/EndnoteXmlExporter.java | 101 ++++++++---------- .../logic/exporter/ExporterFactory.java | 1 - 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index fa1a0c6fa8a..4485ecc5a4a 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -8,15 +8,16 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import org.jabref.logic.importer.AuthorListParser; import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.Author; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryType; @@ -26,7 +27,6 @@ public class EndnoteXmlExporter extends Exporter { private static final String ENDNOTE_XML_VERSION = "20.1"; - private static final String ENDNOTE_NAMESPACE_URI = "http://www.endnote.com/ns/ENdnx"; private static final Map EXPORT_ITEM_TYPE = Map.ofEntries( Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), @@ -51,8 +51,13 @@ public class EndnoteXmlExporter extends Exporter { .collect(Collectors.toList()) .indexOf(entry.getValue()) + 1))); + private final XMLOutputFactory xmlOutputFactory; + private final AuthorListParser authorListParser; + public EndnoteXmlExporter() { super("endnote", "EndNote XML", StandardFileType.XML); + this.xmlOutputFactory = XMLOutputFactory.newFactory(); + this.authorListParser = new AuthorListParser(); } @Override @@ -66,8 +71,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List } try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { - XMLOutputFactory xof = XMLOutputFactory.newFactory(); - XMLStreamWriter xml = xof.createXMLStreamWriter(writer); + XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(writer); xml.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0"); xml.writeStartElement("xml"); xml.writeStartElement("records"); @@ -91,12 +95,12 @@ private void writeEntry(BibEntry entry, XMLStreamWriter xml) throws XMLStreamExc // Write the necessary fields and elements writeField(xml, "database", "endnote.enl", Map.of("name", "My EndNote Library.enl", "path", "/path/to/My EndNote Library.enl")); writeField(xml, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); - writeField(xml, "rec-number", String.valueOf(entry.getId()), null); + writeField(xml, "rec-number", entry.getId(), null); xml.writeStartElement("foreign-keys"); xml.writeStartElement("key"); xml.writeAttribute("app", "EN"); - xml.writeCharacters(String.valueOf(entry.getId())); + xml.writeCharacters(entry.getId()); xml.writeEndElement(); // key xml.writeEndElement(); // foreign-keys @@ -110,7 +114,7 @@ private void writeEntry(BibEntry entry, XMLStreamWriter xml) throws XMLStreamExc writeField(xml, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); writeField(xml, "number", entry.getField(StandardField.NUMBER).orElse(""), null); writeField(xml, "dates", null, Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); - writeField(xml, "publisher", entry.getField(StandardField.PUBLISHER).orElse(""), null); + writePublisher(entry, xml); writeField(xml, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); writeField(xml, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); writeField(xml, "notes", entry.getField(StandardField.NOTE).orElse(""), null); @@ -159,60 +163,47 @@ private void writeField(XMLStreamWriter xml, String name, String value, Map authors = entry.getField(StandardField.AUTHOR); - if (authors.isPresent()) { - xml.writeStartElement("contributors"); - xml.writeStartElement("authors"); - for (String author : authors.get().split("and")) { - xml.writeStartElement("author"); + entry.getField(StandardField.AUTHOR).ifPresent(authors -> { + try { + xml.writeStartElement("contributors"); + xml.writeStartElement("authors"); + for (Author author : authorListParser.parse(authors).getAuthors()) { + xml.writeStartElement("author"); + xml.writeStartElement("style"); + xml.writeAttribute("face", "normal"); + xml.writeAttribute("font", "default"); + xml.writeAttribute("size", "100%"); + xml.writeCharacters(author.getFamilyGiven(false)); + xml.writeEndElement(); // style + xml.writeEndElement(); // author + } + xml.writeEndElement(); // authors + xml.writeEndElement(); // contributors + } catch (XMLStreamException e) { + throw new RuntimeException("Error writing contributors", e); + } + }); + } + + private void writePublisher(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + String publisher = entry.getField(StandardField.PUBLISHER).orElse(""); + String address = entry.getField(StandardField.ADDRESS).orElse(""); + if (!publisher.isEmpty() || !address.isEmpty()) { + xml.writeStartElement("publisher"); + if (!publisher.isEmpty()) { + writeField(xml, "publisher", publisher, null); + } + if (!address.isEmpty()) { + xml.writeStartElement("place"); xml.writeStartElement("style"); xml.writeAttribute("face", "normal"); xml.writeAttribute("font", "default"); xml.writeAttribute("size", "100%"); - xml.writeCharacters(author.trim()); + xml.writeCharacters(address); xml.writeEndElement(); // style - xml.writeEndElement(); // author + xml.writeEndElement(); // place } - xml.writeEndElement(); // authors - xml.writeEndElement(); // contributors - } - } - - private void writeDates(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - Optional year = entry.getField(StandardField.YEAR); - if (year.isPresent()) { - xml.writeStartElement("dates"); - xml.writeStartElement("year"); - xml.writeCharacters(year.get()); - xml.writeEndElement(); // year - xml.writeEndElement(); // dates + xml.writeEndElement(); // publisher } } - - private void writeUrls(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - xml.writeStartElement("urls"); - entry.getField(StandardField.URL).ifPresent(url -> { - try { - xml.writeStartElement("web-urls"); - xml.writeStartElement("url"); - xml.writeCharacters(url); - xml.writeEndElement(); // url - xml.writeEndElement(); // web-urls - } catch (XMLStreamException e) { - // Ignore exception and continue - } - }); - entry.getField(StandardField.FILE).ifPresent(file -> { - try { - xml.writeStartElement("file-urls"); - xml.writeStartElement("url"); - xml.writeCharacters(file); - xml.writeEndElement(); // url - xml.writeEndElement(); // file-urls - } catch (XMLStreamException e) { - // Ignore exception and continue - } - }); - xml.writeEndElement(); // urls - } } diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index fc0a4eeea70..8a2be8baef3 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -55,7 +55,6 @@ public static ExporterFactory create(PreferencesService preferencesService, exporters.add(new TemplateExporter("MIS Quarterly", "misq", "misq", "misq", StandardFileType.RTF, layoutPreferences, saveOrder)); exporters.add(new TemplateExporter("CSL YAML", "yaml", "yaml", null, StandardFileType.YAML, layoutPreferences, saveOrder, BlankLineBehaviour.DELETE_BLANKS)); exporters.add(new TemplateExporter("Hayagriva YAML", "hayagrivayaml", "hayagrivayaml", null, StandardFileType.YAML, layoutPreferences, saveOrder, BlankLineBehaviour.DELETE_BLANKS)); - exporters.add(new TemplateExporter("Endnote XML", "endnotexml", "Endnote XML", "endnotexml", StandardFileType.XML, layoutPreferences, saveOrder)); exporters.add(new OpenOfficeDocumentCreator()); exporters.add(new OpenDocumentSpreadsheetCreator()); exporters.add(new MSBibExporter()); From c84619ebb4ff239a0b35d8dc609eb798e7548697 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 7 Apr 2024 23:59:50 +0530 Subject: [PATCH 05/78] Changelog addition --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d88155777dc..2a3b7f56267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added support for BibTeX String constants during copy & paste between libraries. [#10872](https://github.com/JabRef/jabref/issues/10872) - We added the field `langid` which is important for hyphenation and casing in LaTeX. [#10868](https://github.com/JabRef/jabref/issues/10868) - Event log entries can now be copied via a context menu. [#11100](https://github.com/JabRef/jabref/issues/11100) +- We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed From 06a314eb69f77a9ab75f600fd061ecb5ac172d3e Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 8 Apr 2024 00:04:16 +0530 Subject: [PATCH 06/78] Changelog line location change --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a3b7f56267..76c4ab3f14f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added - We added a new keyboard shortcut ctrl + , to open the preferences. [#11154](https://github.com/JabRef/jabref/pull/11154) +- We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed @@ -57,7 +58,6 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added support for BibTeX String constants during copy & paste between libraries. [#10872](https://github.com/JabRef/jabref/issues/10872) - We added the field `langid` which is important for hyphenation and casing in LaTeX. [#10868](https://github.com/JabRef/jabref/issues/10868) - Event log entries can now be copied via a context menu. [#11100](https://github.com/JabRef/jabref/issues/11100) -- We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed From 571e226e9783454c9d8c5cb7e768736c68749df6 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 8 Apr 2024 17:21:11 +0530 Subject: [PATCH 07/78] Review changes-2 (Majorly formatted XML) --- .../logic/exporter/EndnoteXmlExporter.java | 220 ++++++++++-------- 1 file changed, 121 insertions(+), 99 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 4485ecc5a4a..b900faf2063 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -1,18 +1,22 @@ package org.jabref.logic.exporter; -import java.io.BufferedWriter; -import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import org.jabref.logic.importer.AuthorListParser; import org.jabref.logic.util.StandardFileType; @@ -24,6 +28,9 @@ import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + public class EndnoteXmlExporter extends Exporter { private static final String ENDNOTE_XML_VERSION = "20.1"; @@ -70,140 +77,155 @@ public void export(BibDatabaseContext databaseContext, Path file, List return; } - try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { - XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(writer); - xml.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0"); - xml.writeStartElement("xml"); - xml.writeStartElement("records"); + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document document = dBuilder.newDocument(); + + Element rootElement = document.createElement("xml"); + document.appendChild(rootElement); + + Element recordsElement = document.createElement("records"); + rootElement.appendChild(recordsElement); for (BibEntry entry : entries) { - writeEntry(entry, xml); + Element recordElement = writeEntry(entry, document); + recordsElement.appendChild(recordElement); } - xml.writeEndElement(); // records - xml.writeEndElement(); // xml - xml.writeEndDocument(); - xml.close(); - } catch (IOException | XMLStreamException e) { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(file.toFile()); + transformer.transform(source, result); + } catch ( + ParserConfigurationException | + TransformerException e) { throw new SaveException(e); } } - private void writeEntry(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { - xml.writeStartElement("record"); + private Element writeEntry(BibEntry entry, Document document) { + Element recordElement = document.createElement("record"); // Write the necessary fields and elements - writeField(xml, "database", "endnote.enl", Map.of("name", "My EndNote Library.enl", "path", "/path/to/My EndNote Library.enl")); - writeField(xml, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); - writeField(xml, "rec-number", entry.getId(), null); - - xml.writeStartElement("foreign-keys"); - xml.writeStartElement("key"); - xml.writeAttribute("app", "EN"); - xml.writeCharacters(entry.getId()); - xml.writeEndElement(); // key - xml.writeEndElement(); // foreign-keys - - writeField(xml, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); - - writeContributors(entry, xml); - writeField(xml, "titles", null, Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); - writeField(xml, "periodical", null, Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); - writeField(xml, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); - writeField(xml, "pages", entry.getField(StandardField.PAGES).orElse(""), null); - writeField(xml, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); - writeField(xml, "number", entry.getField(StandardField.NUMBER).orElse(""), null); - writeField(xml, "dates", null, Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); - writePublisher(entry, xml); - writeField(xml, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); - writeField(xml, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); - writeField(xml, "notes", entry.getField(StandardField.NOTE).orElse(""), null); - writeField(xml, "urls", null, Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); - writeField(xml, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); - - xml.writeEndElement(); // record + writeField(document, recordElement, "database", "endnote.enl", Map.of("name", "My EndNote Library.enl", "path", "/path/to/My EndNote Library.enl")); + writeField(document, recordElement, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); + writeField(document, recordElement, "rec-number", entry.getId(), null); + + Element foreignKeysElement = document.createElement("foreign-keys"); + Element keyElement = document.createElement("key"); + keyElement.setAttribute("app", "EN"); + keyElement.appendChild(document.createTextNode(entry.getId())); + foreignKeysElement.appendChild(keyElement); + recordElement.appendChild(foreignKeysElement); + + writeField(document, recordElement, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); + + writeContributors(entry, document, recordElement); + writeField(document, recordElement, "titles", null, Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); + writeField(document, recordElement, "periodical", null, Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); + writeField(document, recordElement, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); + writeField(document, recordElement, "pages", entry.getField(StandardField.PAGES).orElse(""), null); + writeField(document, recordElement, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); + writeField(document, recordElement, "number", entry.getField(StandardField.NUMBER).orElse(""), null); + writeField(document, recordElement, "dates", null, Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); + writePublisher(entry, document, recordElement); + writeField(document, recordElement, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); + writeField(document, recordElement, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); + writeField(document, recordElement, "notes", entry.getField(StandardField.NOTE).orElse(""), null); + writeField(document, recordElement, "urls", null, Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); + writeField(document, recordElement, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); + + return recordElement; } - private void writeField(XMLStreamWriter xml, String name, String value, Map attributes) throws XMLStreamException { + private void writeField(Document document, Element parentElement, String name, String value, Map attributes) { if (value != null && !value.isEmpty()) { - xml.writeStartElement(name); + Element fieldElement = document.createElement(name); if (attributes != null) { for (Map.Entry attribute : attributes.entrySet()) { - xml.writeAttribute(attribute.getKey(), attribute.getValue()); + fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); } } - xml.writeStartElement("style"); - xml.writeAttribute("face", "normal"); - xml.writeAttribute("font", "default"); - xml.writeAttribute("size", "100%"); - xml.writeCharacters(value); - xml.writeEndElement(); // style - xml.writeEndElement(); // name + Element styleElement = document.createElement("style"); + styleElement.setAttribute("face", "normal"); + styleElement.setAttribute("font", "default"); + styleElement.setAttribute("size", "100%"); + styleElement.appendChild(document.createTextNode(value)); + fieldElement.appendChild(styleElement); + parentElement.appendChild(fieldElement); } } - private void writeField(XMLStreamWriter xml, String name, String value, Map attributes, String childValue, String childElementName) throws XMLStreamException { - xml.writeStartElement(name); + private void writeField(Document document, Element parentElement, String name, String value, Map attributes, String childValue, String childElementName) { + Element fieldElement = document.createElement(name); if (attributes != null) { for (Map.Entry attribute : attributes.entrySet()) { - xml.writeAttribute(attribute.getKey(), attribute.getValue()); + fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); } } if (childValue != null && !childValue.isEmpty()) { - xml.writeStartElement(childElementName); - xml.writeStartElement("style"); - xml.writeAttribute("face", "normal"); - xml.writeAttribute("font", "default"); - xml.writeAttribute("size", "100%"); - xml.writeCharacters(childValue); - xml.writeEndElement(); // style - xml.writeEndElement(); // childElementName + Element childElement = document.createElement(childElementName); + Element styleElement = document.createElement("style"); + styleElement.setAttribute("face", "normal"); + styleElement.setAttribute("font", "default"); + styleElement.setAttribute("size", "100%"); + styleElement.appendChild(document.createTextNode(childValue)); + childElement.appendChild(styleElement); + fieldElement.appendChild(childElement); } - xml.writeEndElement(); // name + parentElement.appendChild(fieldElement); } - private void writeContributors(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + private void writeContributors(BibEntry entry, Document document, Element parentElement) { entry.getField(StandardField.AUTHOR).ifPresent(authors -> { - try { - xml.writeStartElement("contributors"); - xml.writeStartElement("authors"); - for (Author author : authorListParser.parse(authors).getAuthors()) { - xml.writeStartElement("author"); - xml.writeStartElement("style"); - xml.writeAttribute("face", "normal"); - xml.writeAttribute("font", "default"); - xml.writeAttribute("size", "100%"); - xml.writeCharacters(author.getFamilyGiven(false)); - xml.writeEndElement(); // style - xml.writeEndElement(); // author - } - xml.writeEndElement(); // authors - xml.writeEndElement(); // contributors - } catch (XMLStreamException e) { - throw new RuntimeException("Error writing contributors", e); + Element contributorsElement = document.createElement("contributors"); + Element authorsElement = document.createElement("authors"); + + // Parse the authors string and get the list of Author objects + List authorList = authorListParser.parse(authors).getAuthors(); + + // Iterate over each Author object and create the corresponding XML elements + for (Author author : authorList) { + Element authorElement = document.createElement("author"); + Element styleElement = document.createElement("style"); + styleElement.setAttribute("face", "normal"); + styleElement.setAttribute("font", "default"); + styleElement.setAttribute("size", "100%"); + styleElement.appendChild(document.createTextNode(author.getFamilyGiven(false))); + authorElement.appendChild(styleElement); + authorsElement.appendChild(authorElement); } + + contributorsElement.appendChild(authorsElement); + parentElement.appendChild(contributorsElement); }); } - private void writePublisher(BibEntry entry, XMLStreamWriter xml) throws XMLStreamException { + private void writePublisher(BibEntry entry, Document document, Element parentElement) { String publisher = entry.getField(StandardField.PUBLISHER).orElse(""); String address = entry.getField(StandardField.ADDRESS).orElse(""); if (!publisher.isEmpty() || !address.isEmpty()) { - xml.writeStartElement("publisher"); + Element publisherElement = document.createElement("publisher"); if (!publisher.isEmpty()) { - writeField(xml, "publisher", publisher, null); + writeField(document, publisherElement, "publisher", publisher, null); } if (!address.isEmpty()) { - xml.writeStartElement("place"); - xml.writeStartElement("style"); - xml.writeAttribute("face", "normal"); - xml.writeAttribute("font", "default"); - xml.writeAttribute("size", "100%"); - xml.writeCharacters(address); - xml.writeEndElement(); // style - xml.writeEndElement(); // place + Element placeElement = document.createElement("place"); + Element styleElement = document.createElement("style"); + styleElement.setAttribute("face", "normal"); + styleElement.setAttribute("font", "default"); + styleElement.setAttribute("size", "100%"); + styleElement.appendChild(document.createTextNode(address)); + placeElement.appendChild(styleElement); + publisherElement.appendChild(placeElement); } - xml.writeEndElement(); // publisher + parentElement.appendChild(publisherElement); } } } From 354d514b934b4e0f2dae253549032a5d91983945 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 04:44:38 +0530 Subject: [PATCH 08/78] Add test --- CHANGELOG.md | 1 + .../exporter/EndnoteXmlExporterTest.java | 135 ++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e8c6d31f61a..594eb8b6a22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added support for offline extracting refereferences from PDFs following the IEEE format. [#11156](https://github.com/JabRef/jabref/pull/11156) - We added a new keyboard shortcut ctrl + , to open the preferences. [#11154](https://github.com/JabRef/jabref/pull/11154) +- We added value selection (such as for month) for content selectors in custom entry types. [#11109](https://github.com/JabRef/jabref/issues/11109) - We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java new file mode 100644 index 00000000000..9aa26e1eb46 --- /dev/null +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -0,0 +1,135 @@ +package org.jabref.logic.exporter; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.StandardEntryType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class EndnoteXmlExporterTest { + private Exporter exporter; + private final BibDatabaseContext databaseContext = new BibDatabaseContext(); + private BibEntry entry; + + @BeforeEach + public void setUp() { + exporter = new EndnoteXmlExporter(); + + entry = new BibEntry(StandardEntryType.Article); + entry.setCitationKey("Tural2020"); + entry.setField(StandardField.AUTHOR, "Tural, Eray and Tural, Hale"); + entry.setField(StandardField.TITLE, "An overview of research on Big Data"); + entry.setField(StandardField.JOURNAL, "Journal of Big Data Analytics"); + entry.setField(StandardField.YEAR, "2020"); + entry.setField(StandardField.VOLUME, "7"); + entry.setField(StandardField.NUMBER, "1"); + entry.setField(StandardField.DOI, "10.1186/s41044-020-00047-z"); + } + + @Test + public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("ThisIsARandomlyNamedFile"); + Files.createFile(file); + + exporter.export(databaseContext, file, Collections.singletonList(entry)); + + List lines = Files.readAllLines(file); + String expectedXml = String.join(System.lineSeparator(), + "", + "", + " ", + " ", + " endnote.enl", + " JabRef", + " " + entry.getId() + "", + " ", + " " + entry.getId() + "", + " ", + " 1", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " <style face=\"normal\" font=\"default\" size=\"100%\">An overview of research on Big Data</style>", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " 7", + " 1", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " 10.1186/s41044-020-00047-z", + " ", + " ", + "" + ); + assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); + } + + @Test + public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("EmptyFile"); + Files.createFile(file); + + exporter.export(databaseContext, file, Collections.emptyList()); + + assertEquals(Collections.emptyList(), Files.readAllLines(file)); + } + + @Test + public void exportForNullDBThrowsException(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("NullDB"); + Files.createFile(file); + + assertThrows(NullPointerException.class, () -> + exporter.export(null, file, Collections.singletonList(entry))); + } + + @Test + public void exportForNullExportPathThrowsException(@TempDir Path tempDir) { + assertThrows(NullPointerException.class, () -> + exporter.export(databaseContext, null, Collections.singletonList(entry))); + } + + @Test + public void exportForNullEntryListThrowsException(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("EntryNull"); + Files.createFile(file); + + assertThrows(NullPointerException.class, () -> + exporter.export(databaseContext, file, null)); + } +} From 100ebf4b336500d36e12f4ac7a3370db46b33d49 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 04:57:39 +0530 Subject: [PATCH 09/78] Fix single entry export test --- .../exporter/EndnoteXmlExporterTest.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 9aa26e1eb46..a6b7d6cbc21 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -50,13 +50,21 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { "", " ", " ", - " endnote.enl", - " JabRef", - " " + entry.getId() + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", " ", " " + entry.getId() + "", " ", - " 1", + " ", + " ", + " ", " ", " ", " ", @@ -77,21 +85,21 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " ", " ", - " ", - " 7", - " 1", + " ", + " ", + " ", + " ", + " ", + " ", " ", " ", " ", " ", " ", - " ", - " ", - " ", - " ", - " ", - " ", - " 10.1186/s41044-020-00047-z", + " ", + " ", + " ", + " ", " ", " ", "" From 07b2616f51c15e53bbc5ca296591765c944fabd9 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 05:05:14 +0530 Subject: [PATCH 10/78] Fix ref-type in test --- .../java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index a6b7d6cbc21..09e2b1e4311 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -63,7 +63,7 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " " + entry.getId() + "", " ", " ", - " ", + " ", " ", " ", " ", From 720d0acabcac795fbb43f9b5e67d741a6899d0bb Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 05:16:29 +0530 Subject: [PATCH 11/78] Fix ref-type in test --- .../java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 09e2b1e4311..20223813c96 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -63,7 +63,7 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " " + entry.getId() + "", " ", " ", - " ", + " ", " ", " ", " ", From a0999c4dab05680fc3182c2abc40c100cafde010 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 06:00:53 +0530 Subject: [PATCH 12/78] Ordered export item types --- .../logic/exporter/EndnoteXmlExporter.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index b900faf2063..47888c8195f 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -10,7 +10,6 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.stream.XMLOutputFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; @@ -52,18 +51,31 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Misc, "Generic") ); + private static final List EXPORT_ITEM_TYPE_ORDER = List.of( + "Journal Article", + "Book", + "Book Section", + "Conference Paper", + "Conference", + "Thesis", + "Conference Proceedings", + "Report", + "Manuscript", + "Patent", + "Web Page", + "Electronic Article", + "Generic" + ); + private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, entry -> Integer.toString(EXPORT_ITEM_TYPE.entrySet().stream() - .map(Map.Entry::getValue) - .collect(Collectors.toList()) - .indexOf(entry.getValue()) + 1))); + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> Integer.toString(EXPORT_ITEM_TYPE_ORDER.indexOf(entry.getValue()) + 1))); - private final XMLOutputFactory xmlOutputFactory; private final AuthorListParser authorListParser; public EndnoteXmlExporter() { super("endnote", "EndNote XML", StandardFileType.XML); - this.xmlOutputFactory = XMLOutputFactory.newFactory(); this.authorListParser = new AuthorListParser(); } From ba01435bfacd9d87b05d334a34ba89fbb041f2d3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 06:06:49 +0530 Subject: [PATCH 13/78] Adapt test to Journal Entry type --- .../java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 20223813c96..43746a99f65 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -63,7 +63,7 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " " + entry.getId() + "", " ", " ", - " ", + " ", " ", " ", " ", From 1d26c65f0f2475023913d323494452785bce6a11 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 06:26:26 +0530 Subject: [PATCH 14/78] Shift factory initialization to constructor, remove code duplicacy & more enhancements --- .../logic/exporter/EndnoteXmlExporter.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 47888c8195f..8d09270b6b1 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -73,10 +73,12 @@ public class EndnoteXmlExporter extends Exporter { entry -> Integer.toString(EXPORT_ITEM_TYPE_ORDER.indexOf(entry.getValue()) + 1))); private final AuthorListParser authorListParser; + private final DocumentBuilderFactory dbFactory; public EndnoteXmlExporter() { super("endnote", "EndNote XML", StandardFileType.XML); this.authorListParser = new AuthorListParser(); + this.dbFactory = DocumentBuilderFactory.newInstance(); } @Override @@ -90,7 +92,6 @@ public void export(BibDatabaseContext databaseContext, Path file, List } try { - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document document = dBuilder.newDocument(); @@ -139,18 +140,18 @@ private Element writeEntry(BibEntry entry, Document document) { writeField(document, recordElement, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); writeContributors(entry, document, recordElement); - writeField(document, recordElement, "titles", null, Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); - writeField(document, recordElement, "periodical", null, Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); + writeField(document, recordElement, "titles", Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); + writeField(document, recordElement, "periodical", Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); writeField(document, recordElement, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); writeField(document, recordElement, "pages", entry.getField(StandardField.PAGES).orElse(""), null); writeField(document, recordElement, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); writeField(document, recordElement, "number", entry.getField(StandardField.NUMBER).orElse(""), null); - writeField(document, recordElement, "dates", null, Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); + writeField(document, recordElement, "dates", Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); writePublisher(entry, document, recordElement); writeField(document, recordElement, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); writeField(document, recordElement, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); writeField(document, recordElement, "notes", entry.getField(StandardField.NOTE).orElse(""), null); - writeField(document, recordElement, "urls", null, Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); + writeField(document, recordElement, "urls", Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); writeField(document, recordElement, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); return recordElement; @@ -164,17 +165,12 @@ private void writeField(Document document, Element parentElement, String name, S fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); } } - Element styleElement = document.createElement("style"); - styleElement.setAttribute("face", "normal"); - styleElement.setAttribute("font", "default"); - styleElement.setAttribute("size", "100%"); - styleElement.appendChild(document.createTextNode(value)); - fieldElement.appendChild(styleElement); + createStyleElement(document, fieldElement, value); parentElement.appendChild(fieldElement); } } - private void writeField(Document document, Element parentElement, String name, String value, Map attributes, String childValue, String childElementName) { + private void writeField(Document document, Element parentElement, String name, Map attributes, String childValue, String childElementName) { Element fieldElement = document.createElement(name); if (attributes != null) { for (Map.Entry attribute : attributes.entrySet()) { @@ -183,17 +179,21 @@ private void writeField(Document document, Element parentElement, String name, S } if (childValue != null && !childValue.isEmpty()) { Element childElement = document.createElement(childElementName); - Element styleElement = document.createElement("style"); - styleElement.setAttribute("face", "normal"); - styleElement.setAttribute("font", "default"); - styleElement.setAttribute("size", "100%"); - styleElement.appendChild(document.createTextNode(childValue)); - childElement.appendChild(styleElement); + createStyleElement(document, childElement, childValue); fieldElement.appendChild(childElement); } parentElement.appendChild(fieldElement); } + private void createStyleElement(Document document, Element parentElement, String value) { + Element styleElement = document.createElement("style"); + styleElement.setAttribute("face", "normal"); + styleElement.setAttribute("font", "default"); + styleElement.setAttribute("size", "100%"); + styleElement.appendChild(document.createTextNode(value)); + parentElement.appendChild(styleElement); + } + private void writeContributors(BibEntry entry, Document document, Element parentElement) { entry.getField(StandardField.AUTHOR).ifPresent(authors -> { Element contributorsElement = document.createElement("contributors"); From a091fb7db4bfe3d74c880791dbabff7b750ff8d8 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 07:43:07 +0530 Subject: [PATCH 15/78] Add fields - pagetotal, month, day, etc. --- .../logic/exporter/EndnoteXmlExporter.java | 24 ++++++++++------- .../fileformat/EndnoteXmlImporter.java | 12 +++++++++ .../exporter/EndnoteXmlExporterTest.java | 27 ++++++++++++++++++- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 8d09270b6b1..b6c2de65ab8 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -151,8 +151,11 @@ private Element writeEntry(BibEntry entry, Document document) { writeField(document, recordElement, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); writeField(document, recordElement, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); writeField(document, recordElement, "notes", entry.getField(StandardField.NOTE).orElse(""), null); - writeField(document, recordElement, "urls", Map.of(), entry.getField(StandardField.URL).orElse(""), "web-urls"); + writeField(document, recordElement, "urls", Map.of(), entry.getField(StandardField.URL).orElse(""), "related-urls"); writeField(document, recordElement, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); + writeField(document, recordElement, "month", entry.getField(StandardField.MONTH).orElse(""), null); + writeField(document, recordElement, "day", entry.getField(StandardField.DAY).orElse(""), null); + writeField(document, recordElement, "pagetotal", entry.getField(StandardField.PAGETOTAL).orElse(""), null); return recordElement; } @@ -165,7 +168,15 @@ private void writeField(Document document, Element parentElement, String name, S fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); } } - createStyleElement(document, fieldElement, value); + if ("url".equals(name)) { + Element urlsElement = document.createElement("urls"); + Element webUrlsElement = document.createElement("web-urls"); + createStyleElement(document, webUrlsElement, value); + urlsElement.appendChild(webUrlsElement); + fieldElement.appendChild(urlsElement); + } else { + createStyleElement(document, fieldElement, value); + } parentElement.appendChild(fieldElement); } } @@ -228,14 +239,7 @@ private void writePublisher(BibEntry entry, Document document, Element parentEle writeField(document, publisherElement, "publisher", publisher, null); } if (!address.isEmpty()) { - Element placeElement = document.createElement("place"); - Element styleElement = document.createElement("style"); - styleElement.setAttribute("face", "normal"); - styleElement.setAttribute("font", "default"); - styleElement.setAttribute("size", "100%"); - styleElement.appendChild(document.createTextNode(address)); - placeElement.appendChild(styleElement); - publisherElement.appendChild(placeElement); + writeField(document, publisherElement, "address", address, null); } parentElement.appendChild(publisherElement); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 5bbdde5d5e6..a8f13f0ebfc 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -188,6 +188,18 @@ private void parseRecord(XMLStreamReader reader, List bibItems, String case "label" -> { parseStyleContent(reader, fields, new UnknownField("endnote-label"), elementName); } + case "month" -> { + parseStyleContent(reader, fields, StandardField.MONTH, elementName); + } + case "day" -> { + parseStyleContent(reader, fields, StandardField.DAY, elementName); + } + case "address" -> { + parseStyleContent(reader, fields, StandardField.ADDRESS, elementName); + } + case "pagetotal" -> { + parseStyleContent(reader, fields, new UnknownField("pagetotal"), elementName); + } } } if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 43746a99f65..cc3a371048d 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -34,7 +34,13 @@ public void setUp() { entry.setField(StandardField.YEAR, "2020"); entry.setField(StandardField.VOLUME, "7"); entry.setField(StandardField.NUMBER, "1"); + entry.setField(StandardField.PAGES, "123-456"); entry.setField(StandardField.DOI, "10.1186/s41044-020-00047-z"); + entry.setField(StandardField.URL, "https://doi.org/10.1186/s41044-020-00047-z"); + entry.setField(StandardField.ABSTRACT, "This is the abstract of the article."); + entry.setField(StandardField.MONTH, "7"); + entry.setField(StandardField.DAY, "15"); + entry.setField(StandardField.PAGETOTAL, "334"); } @Test @@ -85,6 +91,9 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " ", " ", + " ", + " ", + " ", " ", " ", " ", @@ -96,10 +105,26 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " ", " ", - " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", " ", " ", " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", " ", " ", "" From b252d8c7e88e1ce5520ea9fe5cab658cc2c46c62 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 08:07:40 +0530 Subject: [PATCH 16/78] Add series/secondary title --- src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index b6c2de65ab8..06d65f73f38 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -141,6 +141,7 @@ private Element writeEntry(BibEntry entry, Document document) { writeContributors(entry, document, recordElement); writeField(document, recordElement, "titles", Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); + writeField(document, recordElement, "secondary-title", entry.getField(StandardField.SERIES).orElse(""), null); writeField(document, recordElement, "periodical", Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); writeField(document, recordElement, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); writeField(document, recordElement, "pages", entry.getField(StandardField.PAGES).orElse(""), null); From 3309cd98c9e60a469c4bc758fbf83e29344e70e3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 08:08:44 +0530 Subject: [PATCH 17/78] Update test --- .../fileformat/EndnoteXmlImporter.java | 3 + .../exporter/EndnoteXmlExporterTest.java | 85 ++++++++++--------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index a8f13f0ebfc..434329feb2a 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -158,6 +158,9 @@ private void parseRecord(XMLStreamReader reader, List bibItems, String case "number" -> { parseStyleContent(reader, fields, StandardField.NUMBER, elementName); } + case "secondary-title" -> { + parseStyleContent(reader, fields, StandardField.SERIES, elementName); + } case "tertiary-title" -> { parseStyleContent(reader, fields, StandardField.BOOKTITLE, elementName); } diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index cc3a371048d..df19c88ce69 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -26,21 +26,23 @@ public class EndnoteXmlExporterTest { public void setUp() { exporter = new EndnoteXmlExporter(); - entry = new BibEntry(StandardEntryType.Article); - entry.setCitationKey("Tural2020"); - entry.setField(StandardField.AUTHOR, "Tural, Eray and Tural, Hale"); - entry.setField(StandardField.TITLE, "An overview of research on Big Data"); - entry.setField(StandardField.JOURNAL, "Journal of Big Data Analytics"); - entry.setField(StandardField.YEAR, "2020"); - entry.setField(StandardField.VOLUME, "7"); - entry.setField(StandardField.NUMBER, "1"); - entry.setField(StandardField.PAGES, "123-456"); - entry.setField(StandardField.DOI, "10.1186/s41044-020-00047-z"); - entry.setField(StandardField.URL, "https://doi.org/10.1186/s41044-020-00047-z"); - entry.setField(StandardField.ABSTRACT, "This is the abstract of the article."); - entry.setField(StandardField.MONTH, "7"); - entry.setField(StandardField.DAY, "15"); - entry.setField(StandardField.PAGETOTAL, "334"); + entry = new BibEntry(StandardEntryType.Conference); + entry.setCitationKey("Dai2018"); + entry.setField(StandardField.AUTHOR, "Dai, H. K."); + entry.setField(StandardField.TITLE, "Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence"); + entry.setField(StandardField.BOOKTITLE, "Proceedings of the 9th International Symposium on Information and Communication Technology"); + entry.setField(StandardField.YEAR, "2018"); + entry.setField(StandardField.MONTH, "12"); + entry.setField(StandardField.DAY, "6"); + entry.setField(StandardField.SERIES, "SoICT '18"); + entry.setField(StandardField.PAGES, "130--136"); + entry.setField(StandardField.ADDRESS, "New York, NY, USA"); + entry.setField(StandardField.PUBLISHER, "Association for Computing Machinery"); + entry.setField(StandardField.PAGETOTAL, "7"); + entry.setField(StandardField.DOI, "10.1145/3287921.3287982"); + entry.setField(StandardField.ISBN, "9781450365390"); + entry.setField(StandardField.ABSTRACT, "An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets."); + entry.setField(StandardField.URL, "https://doi.org/10.1145/3287921.3287982"); } @Test @@ -68,62 +70,63 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " " + entry.getId() + "", " ", - " ", - " ", + " ", + " ", " ", " ", " ", " ", - " ", - " ", - " ", - " ", + " ", " ", " ", " ", " ", " ", - " <style face=\"normal\" font=\"default\" size=\"100%\">An overview of research on Big Data</style>", + " <style face=\"normal\" font=\"default\" size=\"100%\">Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence</style>", " ", " ", - " ", - " ", - " ", - " ", - " ", + " ", + " ", + " ", + " ", " ", - " ", + " ", " ", - " ", - " ", - " ", - " ", - " ", - " ", " ", " ", - " ", + " ", " ", " ", + " ", + " ", + " ", + " ", + "
", + " ", + "
", + "
", + " ", + " ", + " ", " ", - " ", + " ", " ", " ", " ", - " ", + " ", " ", " ", " ", - " ", + " ", " ", " ", - " ", + " ", " ", " ", - " ", + " ", " ", " ", - " ", + " ", " ", " ", " ", From f05675a01a2eab4ac3e332eb975b6d579b6d0fa8 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 08:18:10 +0530 Subject: [PATCH 18/78] Update test - add tertiary title, fix ref no --- .../jabref/logic/exporter/EndnoteXmlExporterTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index df19c88ce69..8f8dbcfa8d4 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -70,8 +70,8 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " " + entry.getId() + "", " ", - " ", - " ", + " ", + " ", " ", " ", " ", @@ -85,10 +85,13 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { " ", " ", " ", - " ", " ", " ", " ", + " ", + " ", + " ", + " ", " ", " ", " ", From 2b4cab9b58474c74a3027af7f88bc9d63a1307e7 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 18:49:20 +0530 Subject: [PATCH 19/78] Review changes -3 (LinkedHashMap) --- .../logic/exporter/EndnoteXmlExporter.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 06d65f73f38..b877565cbce 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -2,6 +2,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -51,26 +52,19 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Misc, "Generic") ); - private static final List EXPORT_ITEM_TYPE_ORDER = List.of( - "Journal Article", - "Book", - "Book Section", - "Conference Paper", - "Conference", - "Thesis", - "Conference Proceedings", - "Report", - "Manuscript", - "Patent", - "Web Page", - "Electronic Article", - "Generic" - ); - - private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet().stream() + private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet() + .stream() .collect(Collectors.toMap( Map.Entry::getKey, - entry -> Integer.toString(EXPORT_ITEM_TYPE_ORDER.indexOf(entry.getValue()) + 1))); + entry -> Integer.toString(EXPORT_ITEM_TYPE.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (e1, e2) -> e1, LinkedHashMap::new)) + .keySet() + .stream() + .toList() + .indexOf(entry.getValue()) + 1), + (e1, e2) -> e1, + LinkedHashMap::new + )); private final AuthorListParser authorListParser; private final DocumentBuilderFactory dbFactory; From f56dadb5b49af16707b88130e860ae7d319f8bd3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 18:54:40 +0530 Subject: [PATCH 20/78] Fix LinkedHashMap implementation --- .../java/org/jabref/logic/exporter/EndnoteXmlExporter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index b877565cbce..f9430071c3d 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -34,7 +34,7 @@ public class EndnoteXmlExporter extends Exporter { private static final String ENDNOTE_XML_VERSION = "20.1"; - private static final Map EXPORT_ITEM_TYPE = Map.ofEntries( + private static final Map EXPORT_ITEM_TYPE = new LinkedHashMap<>(Map.ofEntries( Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), Map.entry(StandardEntryType.InBook, "Book Section"), @@ -50,7 +50,7 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Online, "Web Page"), Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), Map.entry(StandardEntryType.Misc, "Generic") - ); + )); private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet() .stream() From 04c9bc852193ec26809ce06d785d45a995878bd1 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 9 Apr 2024 20:51:43 +0530 Subject: [PATCH 21/78] Attempt fix of LHM --- .../org/jabref/logic/exporter/EndnoteXmlExporter.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index f9430071c3d..2986c19a1e3 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -52,16 +52,11 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Misc, "Generic") )); - private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.entrySet() + private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.keySet() .stream() .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> Integer.toString(EXPORT_ITEM_TYPE.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (e1, e2) -> e1, LinkedHashMap::new)) - .keySet() - .stream() - .toList() - .indexOf(entry.getValue()) + 1), + entryType -> entryType, + entryType -> Integer.toString(EXPORT_ITEM_TYPE.keySet().stream().toList().indexOf(entryType) + 1), (e1, e2) -> e1, LinkedHashMap::new )); From 35421691dd6ec20e2f802865a1e4d3d5a77fc428 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 04:54:45 +0530 Subject: [PATCH 22/78] Major rehaul: Conform to Endnote DTD, add missing fields, fix missing editor, importer changes --- CHANGELOG.md | 3 + .../logic/exporter/EndnoteXmlExporter.java | 271 ++++------ .../fileformat/EndnoteXmlImporter.java | 465 ++++-------------- .../exporter/EndnoteXmlExporterTest.java | 230 +++++---- 4 files changed, 318 insertions(+), 651 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594eb8b6a22..9adf44fbf8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added support for offline extracting refereferences from PDFs following the IEEE format. [#11156](https://github.com/JabRef/jabref/pull/11156) - We added a new keyboard shortcut ctrl + , to open the preferences. [#11154](https://github.com/JabRef/jabref/pull/11154) - We added value selection (such as for month) for content selectors in custom entry types. [#11109](https://github.com/JabRef/jabref/issues/11109) +- We added a duplicate checker for the Citation Relations tab. [#10414](https://github.com/JabRef/jabref/issues/10414) +- We added tooltip on main table cells that shows cell content or cell content and entry preview if set in preferences. [10925](https://github.com/JabRef/jabref/issues/10925) +- We added the ability to add a keyword/crossref when typing the separator character (e.g., comma) in the keywords/crossref fields. [#11178](https://github.com/JabRef/jabref/issues/11178) - We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 2986c19a1e3..f0e5469e14c 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -2,27 +2,23 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.LinkedHashMap; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.jabref.logic.importer.AuthorListParser; import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.Author; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; @@ -32,42 +28,57 @@ import org.w3c.dom.Element; public class EndnoteXmlExporter extends Exporter { - - private static final String ENDNOTE_XML_VERSION = "20.1"; - private static final Map EXPORT_ITEM_TYPE = new LinkedHashMap<>(Map.ofEntries( + private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), Map.entry(StandardEntryType.InBook, "Book Section"), Map.entry(StandardEntryType.InCollection, "Book Section"), - Map.entry(StandardEntryType.InProceedings, "Conference Paper"), - Map.entry(StandardEntryType.Conference, "Conference"), + Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), Map.entry(StandardEntryType.MastersThesis, "Thesis"), Map.entry(StandardEntryType.PhdThesis, "Thesis"), - Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), Map.entry(StandardEntryType.TechReport, "Report"), Map.entry(StandardEntryType.Unpublished, "Manuscript"), + Map.entry(StandardEntryType.InProceedings, "Conference Paper"), + Map.entry(StandardEntryType.Conference, "Conference"), Map.entry(IEEETranEntryType.Patent, "Patent"), Map.entry(StandardEntryType.Online, "Web Page"), Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), Map.entry(StandardEntryType.Misc, "Generic") - )); - - private static final Map EXPORT_REF_NUMBER = EXPORT_ITEM_TYPE.keySet() - .stream() - .collect(Collectors.toMap( - entryType -> entryType, - entryType -> Integer.toString(EXPORT_ITEM_TYPE.keySet().stream().toList().indexOf(entryType) + 1), - (e1, e2) -> e1, - LinkedHashMap::new - )); - - private final AuthorListParser authorListParser; - private final DocumentBuilderFactory dbFactory; + ); + + private static final Map FIELD_MAPPING = Map.ofEntries( + Map.entry(StandardField.TITLE, "title"), + Map.entry(StandardField.AUTHOR, "authors"), + Map.entry(StandardField.EDITOR, "secondary-authors"), + Map.entry(StandardField.YEAR, "year"), + Map.entry(StandardField.MONTH, "pub-dates"), + Map.entry(StandardField.JOURNAL, "full-title"), + Map.entry(StandardField.JOURNALTITLE, "full-title"), + Map.entry(StandardField.BOOKTITLE, "secondary-title"), + Map.entry(StandardField.EDITION, "edition"), + Map.entry(StandardField.SERIES, "tertiary-title"), + Map.entry(StandardField.VOLUME, "volume"), + Map.entry(StandardField.NUMBER, "number"), + Map.entry(StandardField.ISSUE, "issue"), + Map.entry(StandardField.PAGES, "pages"), + Map.entry(StandardField.PUBLISHER, "publisher"), + Map.entry(StandardField.ADDRESS, "pub-location"), + Map.entry(StandardField.CHAPTER, "section"), + Map.entry(StandardField.HOWPUBLISHED, "work-type"), + Map.entry(StandardField.INSTITUTION, "publisher"), + Map.entry(StandardField.ORGANIZATION, "publisher"), + Map.entry(StandardField.SCHOOL, "publisher"), + Map.entry(StandardField.ISBN, "isbn"), + Map.entry(StandardField.ISSN, "isbn"), + Map.entry(StandardField.DOI, "electronic-resource-num"), + Map.entry(StandardField.URL, "web-urls"), + Map.entry(StandardField.FILE, "pdf-urls"), + Map.entry(StandardField.ABSTRACT, "abstract"), + Map.entry(StandardField.KEYWORDS, "keywords") + ); public EndnoteXmlExporter() { super("endnote", "EndNote XML", StandardFileType.XML); - this.authorListParser = new AuthorListParser(); - this.dbFactory = DocumentBuilderFactory.newInstance(); } @Override @@ -80,158 +91,68 @@ public void export(BibDatabaseContext databaseContext, Path file, List return; } - try { - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document document = dBuilder.newDocument(); - - Element rootElement = document.createElement("xml"); - document.appendChild(rootElement); - - Element recordsElement = document.createElement("records"); - rootElement.appendChild(recordsElement); - - for (BibEntry entry : entries) { - Element recordElement = writeEntry(entry, document); - recordsElement.appendChild(recordElement); - } - - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - - DOMSource source = new DOMSource(document); - StreamResult result = new StreamResult(file.toFile()); - transformer.transform(source, result); - } catch ( - ParserConfigurationException | - TransformerException e) { - throw new SaveException(e); - } - } - - private Element writeEntry(BibEntry entry, Document document) { - Element recordElement = document.createElement("record"); - - // Write the necessary fields and elements - writeField(document, recordElement, "database", "endnote.enl", Map.of("name", "My EndNote Library.enl", "path", "/path/to/My EndNote Library.enl")); - writeField(document, recordElement, "source-app", "JabRef", Map.of("name", "JabRef", "version", ENDNOTE_XML_VERSION)); - writeField(document, recordElement, "rec-number", entry.getId(), null); - - Element foreignKeysElement = document.createElement("foreign-keys"); - Element keyElement = document.createElement("key"); - keyElement.setAttribute("app", "EN"); - keyElement.appendChild(document.createTextNode(entry.getId())); - foreignKeysElement.appendChild(keyElement); - recordElement.appendChild(foreignKeysElement); - - writeField(document, recordElement, "ref-type", EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"), Map.of("name", EXPORT_ITEM_TYPE.getOrDefault(entry.getType(), "Generic"))); - - writeContributors(entry, document, recordElement); - writeField(document, recordElement, "titles", Map.of(), entry.getField(StandardField.TITLE).orElse(""), "title"); - writeField(document, recordElement, "secondary-title", entry.getField(StandardField.SERIES).orElse(""), null); - writeField(document, recordElement, "periodical", Map.of(), entry.getField(StandardField.JOURNAL).orElse(""), "full-title"); - writeField(document, recordElement, "tertiary-title", entry.getField(StandardField.BOOKTITLE).orElse(""), null); - writeField(document, recordElement, "pages", entry.getField(StandardField.PAGES).orElse(""), null); - writeField(document, recordElement, "volume", entry.getField(StandardField.VOLUME).orElse(""), null); - writeField(document, recordElement, "number", entry.getField(StandardField.NUMBER).orElse(""), null); - writeField(document, recordElement, "dates", Map.of(), entry.getField(StandardField.YEAR).orElse(""), "year"); - writePublisher(entry, document, recordElement); - writeField(document, recordElement, "isbn", entry.getField(StandardField.ISBN).orElse(""), null); - writeField(document, recordElement, "abstract", entry.getField(StandardField.ABSTRACT).orElse(""), null); - writeField(document, recordElement, "notes", entry.getField(StandardField.NOTE).orElse(""), null); - writeField(document, recordElement, "urls", Map.of(), entry.getField(StandardField.URL).orElse(""), "related-urls"); - writeField(document, recordElement, "electronic-resource-num", entry.getField(StandardField.DOI).orElse(""), null); - writeField(document, recordElement, "month", entry.getField(StandardField.MONTH).orElse(""), null); - writeField(document, recordElement, "day", entry.getField(StandardField.DAY).orElse(""), null); - writeField(document, recordElement, "pagetotal", entry.getField(StandardField.PAGETOTAL).orElse(""), null); - - return recordElement; - } - - private void writeField(Document document, Element parentElement, String name, String value, Map attributes) { - if (value != null && !value.isEmpty()) { - Element fieldElement = document.createElement(name); - if (attributes != null) { - for (Map.Entry attribute : attributes.entrySet()) { - fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document document = dBuilder.newDocument(); + + Element rootElement = document.createElement("xml"); + document.appendChild(rootElement); + + Element recordsElement = document.createElement("records"); + rootElement.appendChild(recordsElement); + + for (BibEntry entry : entries) { + Element recordElement = document.createElement("record"); + recordsElement.appendChild(recordElement); + + // Map entry type + EntryType entryType = entry.getType(); + String refType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, "Generic"); + Element refTypeElement = document.createElement("ref-type"); + refTypeElement.setAttribute("name", refType); + refTypeElement.setTextContent(String.valueOf(new ArrayList<>(ENTRY_TYPE_MAPPING.values()).indexOf(refType))); + recordElement.appendChild(refTypeElement); + + // Map authors and editors + entry.getField(StandardField.AUTHOR).ifPresent(authors -> { + Element authorsElement = document.createElement("contributors"); + Element authorsNameElement = document.createElement("authors"); + authorsNameElement.setTextContent(authors); + authorsElement.appendChild(authorsNameElement); + recordElement.appendChild(authorsElement); + }); + + entry.getField(StandardField.EDITOR).ifPresent(editors -> { + Element contributorsElement = document.createElement("contributors"); + Element editorsElement = document.createElement("secondary-authors"); + editorsElement.setTextContent(editors); + contributorsElement.appendChild(editorsElement); + recordElement.appendChild(contributorsElement); + }); + + // Map fields + for (Map.Entry fieldMapping : FIELD_MAPPING.entrySet()) { + Field field = fieldMapping.getKey(); + String xmlElement = fieldMapping.getValue(); + + if (field != StandardField.AUTHOR && field != StandardField.EDITOR) { + entry.getField(field).ifPresent(value -> { + Element fieldElement = document.createElement(xmlElement); + fieldElement.setTextContent(value); + recordElement.appendChild(fieldElement); + }); } } - if ("url".equals(name)) { - Element urlsElement = document.createElement("urls"); - Element webUrlsElement = document.createElement("web-urls"); - createStyleElement(document, webUrlsElement, value); - urlsElement.appendChild(webUrlsElement); - fieldElement.appendChild(urlsElement); - } else { - createStyleElement(document, fieldElement, value); - } - parentElement.appendChild(fieldElement); } - } - private void writeField(Document document, Element parentElement, String name, Map attributes, String childValue, String childElementName) { - Element fieldElement = document.createElement(name); - if (attributes != null) { - for (Map.Entry attribute : attributes.entrySet()) { - fieldElement.setAttribute(attribute.getKey(), attribute.getValue()); - } - } - if (childValue != null && !childValue.isEmpty()) { - Element childElement = document.createElement(childElementName); - createStyleElement(document, childElement, childValue); - fieldElement.appendChild(childElement); - } - parentElement.appendChild(fieldElement); - } + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - private void createStyleElement(Document document, Element parentElement, String value) { - Element styleElement = document.createElement("style"); - styleElement.setAttribute("face", "normal"); - styleElement.setAttribute("font", "default"); - styleElement.setAttribute("size", "100%"); - styleElement.appendChild(document.createTextNode(value)); - parentElement.appendChild(styleElement); - } - - private void writeContributors(BibEntry entry, Document document, Element parentElement) { - entry.getField(StandardField.AUTHOR).ifPresent(authors -> { - Element contributorsElement = document.createElement("contributors"); - Element authorsElement = document.createElement("authors"); - - // Parse the authors string and get the list of Author objects - List authorList = authorListParser.parse(authors).getAuthors(); - - // Iterate over each Author object and create the corresponding XML elements - for (Author author : authorList) { - Element authorElement = document.createElement("author"); - Element styleElement = document.createElement("style"); - styleElement.setAttribute("face", "normal"); - styleElement.setAttribute("font", "default"); - styleElement.setAttribute("size", "100%"); - styleElement.appendChild(document.createTextNode(author.getFamilyGiven(false))); - authorElement.appendChild(styleElement); - authorsElement.appendChild(authorElement); - } - - contributorsElement.appendChild(authorsElement); - parentElement.appendChild(contributorsElement); - }); - } - - private void writePublisher(BibEntry entry, Document document, Element parentElement) { - String publisher = entry.getField(StandardField.PUBLISHER).orElse(""); - String address = entry.getField(StandardField.ADDRESS).orElse(""); - if (!publisher.isEmpty() || !address.isEmpty()) { - Element publisherElement = document.createElement("publisher"); - if (!publisher.isEmpty()) { - writeField(document, publisherElement, "publisher", publisher, null); - } - if (!address.isEmpty()) { - writeField(document, publisherElement, "address", address, null); - } - parentElement.appendChild(publisherElement); - } + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(file.toFile()); + transformer.transform(source, result); } } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 434329feb2a..e84d0cbe105 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -4,12 +4,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -27,43 +24,72 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.KeywordList; -import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; -import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; -import org.jabref.model.strings.StringUtil; -import com.google.common.base.Joiner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * Importer for the Endnote XML format. - *

- * Based on dtd scheme downloaded from Article #122577 in http://kbportal.thomson.com. - */ public class EndnoteXmlImporter extends Importer implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(EndnoteXmlImporter.class); + private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( + Map.entry(StandardEntryType.Article, "Journal Article"), + Map.entry(StandardEntryType.Book, "Book"), + Map.entry(StandardEntryType.InBook, "Book Section"), + Map.entry(StandardEntryType.InCollection, "Book Section"), + Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), + Map.entry(StandardEntryType.MastersThesis, "Thesis"), + Map.entry(StandardEntryType.PhdThesis, "Thesis"), + Map.entry(StandardEntryType.TechReport, "Report"), + Map.entry(StandardEntryType.Unpublished, "Manuscript"), + Map.entry(StandardEntryType.InProceedings, "Conference Paper"), + Map.entry(StandardEntryType.Conference, "Conference"), + Map.entry(IEEETranEntryType.Patent, "Patent"), + Map.entry(StandardEntryType.Online, "Web Page"), + Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), + Map.entry(StandardEntryType.Misc, "Generic") + ); + + private static final Map FIELD_MAPPING = Map.ofEntries( + Map.entry(StandardField.TITLE, "title"), + Map.entry(StandardField.AUTHOR, "authors"), + Map.entry(StandardField.EDITOR, "secondary-authors"), + Map.entry(StandardField.YEAR, "year"), + Map.entry(StandardField.MONTH, "pub-dates"), + Map.entry(StandardField.JOURNAL, "full-title"), + Map.entry(StandardField.JOURNALTITLE, "full-title"), + Map.entry(StandardField.BOOKTITLE, "secondary-title"), + Map.entry(StandardField.EDITION, "edition"), + Map.entry(StandardField.SERIES, "tertiary-title"), + Map.entry(StandardField.VOLUME, "volume"), + Map.entry(StandardField.NUMBER, "number"), + Map.entry(StandardField.ISSUE, "issue"), + Map.entry(StandardField.PAGES, "pages"), + Map.entry(StandardField.PUBLISHER, "publisher"), + Map.entry(StandardField.ADDRESS, "pub-location"), + Map.entry(StandardField.CHAPTER, "section"), + Map.entry(StandardField.HOWPUBLISHED, "work-type"), + Map.entry(StandardField.INSTITUTION, "publisher"), + Map.entry(StandardField.ORGANIZATION, "publisher"), + Map.entry(StandardField.SCHOOL, "publisher"), + Map.entry(StandardField.ISBN, "isbn"), + Map.entry(StandardField.ISSN, "isbn"), + Map.entry(StandardField.DOI, "electronic-resource-num"), + Map.entry(StandardField.URL, "web-urls"), + Map.entry(StandardField.FILE, "pdf-urls"), + Map.entry(StandardField.ABSTRACT, "abstract"), + Map.entry(StandardField.KEYWORDS, "keywords") + ); private final ImportFormatPreferences preferences; private final XMLInputFactory xmlInputFactory; public EndnoteXmlImporter(ImportFormatPreferences preferences) { this.preferences = preferences; xmlInputFactory = XMLInputFactory.newInstance(); - // prevent xxe (https://rules.sonarsource.com/java/RSPEC-2755) - // not suported by aalto-xml - // xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); - // required for reading Unicode characters such as ö - xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); - } - - private static String join(List list, String string) { - return Joiner.on(string).join(list); } @Override @@ -94,7 +120,6 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { if (str.toLowerCase(Locale.ENGLISH).contains("")) { return true; } - i++; } return false; @@ -111,11 +136,9 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { while (reader.hasNext()) { reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - if ("record".equals(elementName)) { - parseRecord(reader, bibItems, elementName); - } + if (isStartElement(reader, "record")) { + BibEntry entry = parseRecord(reader); + bibItems.add(entry); } } } catch (XMLStreamException e) { @@ -125,386 +148,81 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { return new ParserResult(bibItems); } - private void parseRecord(XMLStreamReader reader, List bibItems, String startElement) - throws XMLStreamException { - - Map fields = new HashMap<>(); - EntryType entryType = StandardEntryType.Article; - - KeywordList keywordList = new KeywordList(); - List linkedFiles = new ArrayList<>(); + private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { + BibEntry entry = new BibEntry(); while (reader.hasNext()) { reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "ref-type" -> { - String type = reader.getAttributeValue(null, "name"); - entryType = convertRefNameToType(type); - } - case "contributors" -> { - handleAuthorList(reader, fields, elementName); - } - case "titles" -> { - handleTitles(reader, fields, elementName); - } - case "pages" -> { - parseStyleContent(reader, fields, StandardField.PAGES, elementName); - } - case "volume" -> { - parseStyleContent(reader, fields, StandardField.VOLUME, elementName); - } - case "number" -> { - parseStyleContent(reader, fields, StandardField.NUMBER, elementName); - } - case "secondary-title" -> { - parseStyleContent(reader, fields, StandardField.SERIES, elementName); - } - case "tertiary-title" -> { - parseStyleContent(reader, fields, StandardField.BOOKTITLE, elementName); - } - case "dates" -> { - parseYear(reader, fields); - } - case "notes" -> { - parseStyleContent(reader, fields, StandardField.NOTE, elementName); - } - case "urls" -> { - handleUrlList(reader, fields, linkedFiles); - } - case "keywords" -> { - handleKeywordsList(reader, keywordList, elementName); - } - case "abstract" -> { - parseStyleContent(reader, fields, StandardField.ABSTRACT, elementName); - } - case "isbn" -> { - parseStyleContent(reader, fields, StandardField.ISBN, elementName); - } - case "electronic-resource-num" -> { - parseStyleContent(reader, fields, StandardField.DOI, elementName); - } - case "publisher" -> { - parseStyleContent(reader, fields, StandardField.PUBLISHER, elementName); - } - case "label" -> { - parseStyleContent(reader, fields, new UnknownField("endnote-label"), elementName); - } - case "month" -> { - parseStyleContent(reader, fields, StandardField.MONTH, elementName); - } - case "day" -> { - parseStyleContent(reader, fields, StandardField.DAY, elementName); - } - case "address" -> { - parseStyleContent(reader, fields, StandardField.ADDRESS, elementName); - } - case "pagetotal" -> { - parseStyleContent(reader, fields, new UnknownField("pagetotal"), elementName); - } - } - } - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { + if (isEndElement(reader, "record")) { break; } - } - - BibEntry entry = new BibEntry(entryType); - entry.putKeywords(keywordList, preferences.bibEntryPreferences().getKeywordSeparator()); - - entry.setField(fields); - entry.setFiles(linkedFiles); - bibItems.add(entry); - } - private static EntryType convertRefNameToType(String refName) { - return switch (refName.toLowerCase().trim()) { - case "artwork", "generic" -> StandardEntryType.Misc; - case "electronic article" -> IEEETranEntryType.Electronic; - case "book section" -> StandardEntryType.InBook; - case "book" -> StandardEntryType.Book; - case "report" -> StandardEntryType.Report; - case "conference paper" -> StandardEntryType.InProceedings; - case "conference" -> StandardEntryType.Conference; - case "conference proceedings" -> StandardEntryType.Proceedings; - default -> StandardEntryType.Article; - }; - } - - private void handleAuthorList(XMLStreamReader reader, Map fields, String startElement) throws XMLStreamException { - List authorNames = new ArrayList<>(); - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { + if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "author" -> { - parseAuthor(reader, authorNames); + case "ref-type" -> { + String refType = reader.getAttributeValue(null, "name"); + EntryType entryType = ENTRY_TYPE_MAPPING.entrySet().stream() + .filter(e -> e.getValue().equals(refType)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(StandardEntryType.Misc); + entry.setType(entryType); } - } - } - - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { - break; - } - } - fields.put(StandardField.AUTHOR, join(authorNames, " and ")); - } - - private void parseAuthor(XMLStreamReader reader, List authorNames) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "style" -> { - reader.next(); - if (isCharacterXMLEvent(reader)) { - authorNames.add(reader.getText()); + case "contributors" -> { + parseContributors(reader, entry); + } + default -> { + Field field = FIELD_MAPPING.entrySet().stream() + .filter(e -> e.getValue().equals(elementName)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); + if (field != null) { + entry.setField(field, reader.getElementText()); } } } } - - if (isEndXMLEvent(reader) && "author".equals(reader.getName().getLocalPart())) { - break; - } } - } - private void parseStyleContent(XMLStreamReader reader, Map fields, Field field, String elementName) throws XMLStreamException { - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String tag = reader.getName().getLocalPart(); - if ("style".equals(tag)) { - reader.next(); - if (isCharacterXMLEvent(reader)) { - if ("abstract".equals(elementName) || "electronic-resource-num".equals(elementName) || "notes".equals(elementName)) { - putIfValueNotNull(fields, field, reader.getText().trim()); - } else if ("isbn".equals(elementName) || "secondary-title".equals(elementName)) { - putIfValueNotNull(fields, field, clean(reader.getText())); - } else { - putIfValueNotNull(fields, field, reader.getText()); - } - } - } - } - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(elementName)) { - break; - } - } + return entry; } - private void parseYear(XMLStreamReader reader, Map fields) throws XMLStreamException { + private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { while (reader.hasNext()) { reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "style" -> { - reader.next(); - if (isCharacterXMLEvent(reader)) { - putIfValueNotNull(fields, StandardField.YEAR, reader.getText()); - } - } - } - } - - if (isEndXMLEvent(reader) && "year".equals(reader.getName().getLocalPart())) { + if (isEndElement(reader, "contributors")) { break; } - } - } - private void handleKeywordsList(XMLStreamReader reader, KeywordList keywordList, String startElement) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { + if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "keyword" -> { - parseKeyword(reader, keywordList); + case "authors" -> { + entry.setField(StandardField.AUTHOR, reader.getElementText()); } - } - } - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { - break; - } - } - } - - private void parseKeyword(XMLStreamReader reader, KeywordList keywordList) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "style" -> { - reader.next(); - if (isCharacterXMLEvent(reader)) { - if (reader.getText() != null) { - keywordList.add(reader.getText()); - } - } - } - } - } - - if (isEndXMLEvent(reader) && "keyword".equals(reader.getName().getLocalPart())) { - break; - } - } - } - - private void handleTitles(XMLStreamReader reader, Map fields, String startElement) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "title" -> { - List titleStyleContent = new ArrayList<>(); - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String tag = reader.getName().getLocalPart(); - if ("style".equals(tag)) { - reader.next(); - if (isCharacterXMLEvent(reader)) { - if (reader.getText() != null) { - titleStyleContent.add((reader.getText())); - } - } - } - } - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(elementName)) { - break; - } - } - putIfValueNotNull(fields, StandardField.TITLE, clean(join(titleStyleContent, ""))); - } - case "secondary-title" -> { - parseStyleContent(reader, fields, StandardField.JOURNAL, elementName); + case "secondary-authors" -> { + entry.setField(StandardField.EDITOR, reader.getElementText()); } } } - - if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { - break; - } } } - private void handleUrlList(XMLStreamReader reader, Map fields, List linkedFiles) throws XMLStreamException { - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "related-urls" -> { - parseRelatedUrls(reader, fields); - } - case "pdf-urls" -> { - parsePdfUrls(reader, fields, linkedFiles); - } - } - } - - if (isEndXMLEvent(reader) && "urls".equals(reader.getName().getLocalPart())) { - break; - } - } + private boolean isStartElement(XMLStreamReader reader, String elementName) { + return isStartElement(reader) && reader.getName().getLocalPart().equals(elementName); } - private void parseRelatedUrls(XMLStreamReader reader, Map fields) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - if ("style".equals(elementName)) { - reader.next(); - if (isCharacterXMLEvent(reader)) { - putIfValueNotNull(fields, StandardField.URL, reader.getText()); - } - } - } else if (isCharacterXMLEvent(reader)) { - String value = clean(reader.getText()); - if (value.length() > 0) { - putIfValueNotNull(fields, StandardField.URL, clean(value)); - } - } - - if (isEndXMLEvent(reader) && "related-urls".equals(reader.getName().getLocalPart())) { - break; - } - } - } - - private void parsePdfUrls(XMLStreamReader reader, Map fields, List linkedFiles) throws XMLStreamException { - - while (reader.hasNext()) { - reader.next(); - if (isStartXMLEvent(reader)) { - String elementName = reader.getName().getLocalPart(); - if ("url".equals(elementName)) { - reader.next(); - if (isStartXMLEvent(reader)) { - String tagName = reader.getName().getLocalPart(); - if ("style".equals(tagName)) { - reader.next(); - if (isCharacterXMLEvent(reader)) { - try { - linkedFiles.add(new LinkedFile(new URL(reader.getText()), "PDF")); - } catch (MalformedURLException e) { - LOGGER.info("Unable to parse {}", reader.getText()); - } - } - } - } - } - } - if (isCharacterXMLEvent(reader)) { - try { - linkedFiles.add(new LinkedFile(new URL(reader.getText()), "PDF")); - } catch (MalformedURLException e) { - LOGGER.info("Unable to parse {}", reader.getText()); - } - } - if (isEndXMLEvent(reader) && "pdf-urls".equals(reader.getName().getLocalPart())) { - break; - } - } - } - - private String clean(String input) { - return StringUtil.unifyLineBreaks(input, " ") - .trim() - .replaceAll(" +", " "); - } - - private void putIfValueNotNull(Map fields, Field field, String value) { - if (value != null) { - fields.put(field, value); - } - } - - private boolean isCharacterXMLEvent(XMLStreamReader reader) { - return reader.getEventType() == XMLEvent.CHARACTERS; + private boolean isStartElement(XMLStreamReader reader) { + return reader.getEventType() == XMLEvent.START_ELEMENT; } - private boolean isStartXMLEvent(XMLStreamReader reader) { - return reader.getEventType() == XMLEvent.START_ELEMENT; + private boolean isEndElement(XMLStreamReader reader, String elementName) { + return isEndElement(reader) && reader.getName().getLocalPart().equals(elementName); } - private boolean isEndXMLEvent(XMLStreamReader reader) { + private boolean isEndElement(XMLStreamReader reader) { return reader.getEventType() == XMLEvent.END_ELEMENT; } @@ -519,8 +237,3 @@ public List parseEntries(InputStream inputStream) throws ParseExceptio return Collections.emptyList(); } } - - - - - diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 8f8dbcfa8d4..07dbac93bf4 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -20,37 +20,45 @@ public class EndnoteXmlExporterTest { private Exporter exporter; private final BibDatabaseContext databaseContext = new BibDatabaseContext(); - private BibEntry entry; + private BibEntry conferenceEntry; + private BibEntry bookEntry; @BeforeEach public void setUp() { exporter = new EndnoteXmlExporter(); - entry = new BibEntry(StandardEntryType.Conference); - entry.setCitationKey("Dai2018"); - entry.setField(StandardField.AUTHOR, "Dai, H. K."); - entry.setField(StandardField.TITLE, "Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence"); - entry.setField(StandardField.BOOKTITLE, "Proceedings of the 9th International Symposium on Information and Communication Technology"); - entry.setField(StandardField.YEAR, "2018"); - entry.setField(StandardField.MONTH, "12"); - entry.setField(StandardField.DAY, "6"); - entry.setField(StandardField.SERIES, "SoICT '18"); - entry.setField(StandardField.PAGES, "130--136"); - entry.setField(StandardField.ADDRESS, "New York, NY, USA"); - entry.setField(StandardField.PUBLISHER, "Association for Computing Machinery"); - entry.setField(StandardField.PAGETOTAL, "7"); - entry.setField(StandardField.DOI, "10.1145/3287921.3287982"); - entry.setField(StandardField.ISBN, "9781450365390"); - entry.setField(StandardField.ABSTRACT, "An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets."); - entry.setField(StandardField.URL, "https://doi.org/10.1145/3287921.3287982"); + conferenceEntry = new BibEntry(StandardEntryType.Conference); + conferenceEntry.setCitationKey("Dai2018"); + conferenceEntry.setField(StandardField.AUTHOR, "Dai, H. K."); + conferenceEntry.setField(StandardField.TITLE, "Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence"); + conferenceEntry.setField(StandardField.BOOKTITLE, "Proceedings of the 9th International Symposium on Information and Communication Technology"); + conferenceEntry.setField(StandardField.YEAR, "2018"); + conferenceEntry.setField(StandardField.MONTH, "12"); + conferenceEntry.setField(StandardField.SERIES, "SoICT '18"); + conferenceEntry.setField(StandardField.PAGES, "130--136"); + conferenceEntry.setField(StandardField.ADDRESS, "New York, NY, USA"); + conferenceEntry.setField(StandardField.PUBLISHER, "Association for Computing Machinery"); + conferenceEntry.setField(StandardField.DOI, "10.1145/3287921.3287982"); + conferenceEntry.setField(StandardField.ISBN, "9781450365390"); + conferenceEntry.setField(StandardField.ABSTRACT, "An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets."); + conferenceEntry.setField(StandardField.KEYWORDS, "Web-site traversal pattern, episode-rule mining, first local maximization"); + + bookEntry = new BibEntry(StandardEntryType.Book); + bookEntry.setCitationKey("Bhattacharyya2013"); + bookEntry.setField(StandardField.EDITOR, "Bhattacharyya, R. and McCormick, M. E."); + bookEntry.setField(StandardField.PUBLISHER, "Elsevier Science"); + bookEntry.setField(StandardField.TITLE, "Wave Energy Conversion"); + bookEntry.setField(StandardField.YEAR, "2013"); + bookEntry.setField(StandardField.ISBN, "9780080442129"); + bookEntry.setField(StandardField.FILE, "/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf"); + bookEntry.setField(StandardField.KEYWORDS, "waves, agua"); } @Test - public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { - Path file = tempDir.resolve("ThisIsARandomlyNamedFile"); - Files.createFile(file); + public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("ConferenceEntry.xml"); - exporter.export(databaseContext, file, Collections.singletonList(entry)); + exporter.export(databaseContext, file, Collections.singletonList(conferenceEntry)); List lines = Files.readAllLines(file); String expectedXml = String.join(System.lineSeparator(), @@ -58,79 +66,104 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { "", " ", " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " + entry.getId() + "", - " ", - " ", - " ", - " ", + " 10", " ", - " ", - " ", - " ", - " ", - " ", + " Dai, H. K.", " ", - " ", - " ", - " <style face=\"normal\" font=\"default\" size=\"100%\">Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence</style>", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "

", - " ", - "
", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", + " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " SoICT '18", + " 130--136", + " 2018", + " 12", + " Association for Computing Machinery", + " New York, NY, USA", + " 9781450365390", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 10.1145/3287921.3287982", + " Web-site traversal pattern", + " episode-rule mining", + " first local maximization", + " ", + " ", + "" + ); + assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); + } + + @Test + public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("BookEntry.xml"); + + exporter.export(databaseContext, file, Collections.singletonList(bookEntry)); + + List lines = Files.readAllLines(file); + String expectedXml = String.join(System.lineSeparator(), + "", + "", + " ", + " ", + " 1", + " ", + " Bhattacharyya, R. and McCormick, M. E.", + " ", + " Wave Energy Conversion", + " 2013", + " Elsevier Science", + " 9780080442129", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", + " waves", + " agua", + " ", + " ", + "" + ); + assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); + } + + @Test + public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { + Path file = tempDir.resolve("MultipleEntries.xml"); + + exporter.export(databaseContext, file, List.of(conferenceEntry, bookEntry)); + + List lines = Files.readAllLines(file); + String expectedXml = String.join(System.lineSeparator(), + "", + "", + " ", + " ", + " 10", + " ", + " Dai, H. K.", + " ", + " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " SoICT '18", + " 130--136", + " 2018", + " 12", + " Association for Computing Machinery", + " New York, NY, USA", + " 9781450365390", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 10.1145/3287921.3287982", + " Web-site traversal pattern", + " episode-rule mining", + " first local maximization", + " ", + " ", + " 1", + " ", + " Bhattacharyya, R. and McCormick, M. E.", + " ", + " Wave Energy Conversion", + " 2013", + " Elsevier Science", + " 9780080442129", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", + " waves", + " agua", " ", " ", "" @@ -141,7 +174,6 @@ public void exportForSingleEntry(@TempDir Path tempDir) throws Exception { @Test public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { Path file = tempDir.resolve("EmptyFile"); - Files.createFile(file); exporter.export(databaseContext, file, Collections.emptyList()); @@ -149,24 +181,22 @@ public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { } @Test - public void exportForNullDBThrowsException(@TempDir Path tempDir) throws Exception { + public void exportForNullDBThrowsException(@TempDir Path tempDir) { Path file = tempDir.resolve("NullDB"); - Files.createFile(file); assertThrows(NullPointerException.class, () -> - exporter.export(null, file, Collections.singletonList(entry))); + exporter.export(null, file, Collections.singletonList(conferenceEntry))); } @Test public void exportForNullExportPathThrowsException(@TempDir Path tempDir) { assertThrows(NullPointerException.class, () -> - exporter.export(databaseContext, null, Collections.singletonList(entry))); + exporter.export(databaseContext, null, Collections.singletonList(conferenceEntry))); } @Test - public void exportForNullEntryListThrowsException(@TempDir Path tempDir) throws Exception { + public void exportForNullEntryListThrowsException(@TempDir Path tempDir) { Path file = tempDir.resolve("EntryNull"); - Files.createFile(file); assertThrows(NullPointerException.class, () -> exporter.export(databaseContext, file, null)); From 4b00fd707f02f230da199585c768d11f01213402 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 05:08:31 +0530 Subject: [PATCH 23/78] Fix exporter test --- .../org/jabref/logic/exporter/EndnoteXmlExporterTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 07dbac93bf4..b2c55b27b83 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -66,7 +66,7 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti "", " ", " ", - " 10", + " 11", " ", " Dai, H. K.", " ", @@ -103,7 +103,7 @@ public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { "", " ", " ", - " 1", + " 2", " ", " Bhattacharyya, R. and McCormick, M. E.", " ", @@ -133,7 +133,7 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { "", " ", " ", - " 10", + " 11", " ", " Dai, H. K.", " ", @@ -153,7 +153,7 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " first local maximization", " ", " ", - " 1", + " 2", " ", " Bhattacharyya, R. and McCormick, M. E.", " ", From 71c18e33eec7deb878ba32d27a2910e0b8178137 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 05:26:14 +0530 Subject: [PATCH 24/78] Preserve order of entry type mappings --- .../org/jabref/logic/exporter/EndnoteXmlExporter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index f0e5469e14c..10fdd20c217 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -3,9 +3,11 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -28,7 +30,7 @@ import org.w3c.dom.Element; public class EndnoteXmlExporter extends Exporter { - private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( + private static final Map ENTRY_TYPE_MAPPING = new LinkedHashMap<>(Map.ofEntries( Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), Map.entry(StandardEntryType.InBook, "Book Section"), @@ -44,7 +46,9 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Online, "Web Page"), Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), Map.entry(StandardEntryType.Misc, "Generic") - ); + )); + + private static final Map EXPORT_REF_NUMBER = ENTRY_TYPE_MAPPING.keySet() .stream() .collect(Collectors.toMap(entryType -> entryType, entryType -> Integer.toString(ENTRY_TYPE_MAPPING.keySet().stream().toList().indexOf(entryType) + 1), (e1, e2) -> e1, LinkedHashMap::new)); private static final Map FIELD_MAPPING = Map.ofEntries( Map.entry(StandardField.TITLE, "title"), @@ -107,7 +111,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List // Map entry type EntryType entryType = entry.getType(); - String refType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, "Generic"); + String refType = EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"); Element refTypeElement = document.createElement("ref-type"); refTypeElement.setAttribute("name", refType); refTypeElement.setTextContent(String.valueOf(new ArrayList<>(ENTRY_TYPE_MAPPING.values()).indexOf(refType))); From d9361f7e91a315bd6dfa3badd27380feb0d99c2a Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 07:07:39 +0530 Subject: [PATCH 25/78] minor refactor --- .../org/jabref/logic/exporter/EndnoteXmlExporter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 10fdd20c217..8e17e928810 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -2,7 +2,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -48,7 +47,8 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardEntryType.Misc, "Generic") )); - private static final Map EXPORT_REF_NUMBER = ENTRY_TYPE_MAPPING.keySet() .stream() .collect(Collectors.toMap(entryType -> entryType, entryType -> Integer.toString(ENTRY_TYPE_MAPPING.keySet().stream().toList().indexOf(entryType) + 1), (e1, e2) -> e1, LinkedHashMap::new)); + private static final Map EXPORT_REF_NUMBER = ENTRY_TYPE_MAPPING.keySet().stream().collect( + Collectors.toMap(entryType -> entryType, entryType -> Integer.toString(ENTRY_TYPE_MAPPING.keySet().stream().toList().indexOf(entryType) + 1), (e1, e2) -> e1, LinkedHashMap::new)); private static final Map FIELD_MAPPING = Map.ofEntries( Map.entry(StandardField.TITLE, "title"), @@ -111,10 +111,10 @@ public void export(BibDatabaseContext databaseContext, Path file, List // Map entry type EntryType entryType = entry.getType(); - String refType = EXPORT_REF_NUMBER.getOrDefault(entry.getType(), "Generic"); + String refType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, "Generic"); Element refTypeElement = document.createElement("ref-type"); refTypeElement.setAttribute("name", refType); - refTypeElement.setTextContent(String.valueOf(new ArrayList<>(ENTRY_TYPE_MAPPING.values()).indexOf(refType))); + refTypeElement.setTextContent(String.valueOf(EXPORT_REF_NUMBER.getOrDefault(entryType, "Generic"))); recordElement.appendChild(refTypeElement); // Map authors and editors From 05f797e5fa2c89dc60572c1bbad905cebd66961e Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 14:41:03 +0530 Subject: [PATCH 26/78] rewriteRun --- src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 8e17e928810..f2b87f3aa02 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -114,7 +114,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List String refType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, "Generic"); Element refTypeElement = document.createElement("ref-type"); refTypeElement.setAttribute("name", refType); - refTypeElement.setTextContent(String.valueOf(EXPORT_REF_NUMBER.getOrDefault(entryType, "Generic"))); + refTypeElement.setTextContent(EXPORT_REF_NUMBER.getOrDefault(entryType, "Generic")); recordElement.appendChild(refTypeElement); // Map authors and editors From 3dead2438989374c661c8b83e1b3880bd03956fa Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:11:19 +0530 Subject: [PATCH 27/78] Fix ordering of entry types --- .../logic/exporter/EndnoteXmlExporter.java | 81 ++++++++++++++----- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index f2b87f3aa02..c8ec1d745f5 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -2,7 +2,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -29,26 +28,66 @@ import org.w3c.dom.Element; public class EndnoteXmlExporter extends Exporter { - private static final Map ENTRY_TYPE_MAPPING = new LinkedHashMap<>(Map.ofEntries( - Map.entry(StandardEntryType.Article, "Journal Article"), - Map.entry(StandardEntryType.Book, "Book"), - Map.entry(StandardEntryType.InBook, "Book Section"), - Map.entry(StandardEntryType.InCollection, "Book Section"), - Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), - Map.entry(StandardEntryType.MastersThesis, "Thesis"), - Map.entry(StandardEntryType.PhdThesis, "Thesis"), - Map.entry(StandardEntryType.TechReport, "Report"), - Map.entry(StandardEntryType.Unpublished, "Manuscript"), - Map.entry(StandardEntryType.InProceedings, "Conference Paper"), - Map.entry(StandardEntryType.Conference, "Conference"), - Map.entry(IEEETranEntryType.Patent, "Patent"), - Map.entry(StandardEntryType.Online, "Web Page"), - Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), - Map.entry(StandardEntryType.Misc, "Generic") - )); - - private static final Map EXPORT_REF_NUMBER = ENTRY_TYPE_MAPPING.keySet().stream().collect( - Collectors.toMap(entryType -> entryType, entryType -> Integer.toString(ENTRY_TYPE_MAPPING.keySet().stream().toList().indexOf(entryType) + 1), (e1, e2) -> e1, LinkedHashMap::new)); + private static final List ORDERED_ENTRY_TYPES = List.of( + StandardEntryType.Article, + StandardEntryType.Book, + StandardEntryType.InBook, + StandardEntryType.InCollection, + StandardEntryType.Proceedings, + StandardEntryType.MastersThesis, + StandardEntryType.PhdThesis, + StandardEntryType.TechReport, + StandardEntryType.Unpublished, + StandardEntryType.InProceedings, + StandardEntryType.Conference, + IEEETranEntryType.Patent, + StandardEntryType.Online, + IEEETranEntryType.Electronic, + StandardEntryType.Misc + ); + + private static final Map ENTRY_TYPE_MAPPING = ORDERED_ENTRY_TYPES.stream() + .collect(Collectors.toMap( + entryType -> entryType, + entryType -> { + switch (entryType) { + case StandardEntryType.Article: + return "Journal Article"; + case StandardEntryType.Book: + return "Book"; + case StandardEntryType.InBook, StandardEntryType.InCollection: + return "Book Section"; + case StandardEntryType.Proceedings: + return "Conference Proceedings"; + case StandardEntryType.MastersThesis, StandardEntryType.PhdThesis: + return "Thesis"; + case StandardEntryType.TechReport: + return "Report"; + case StandardEntryType.Unpublished: + return "Manuscript"; + case StandardEntryType.InProceedings: + return "Conference Paper"; + case StandardEntryType.Conference: + return "Conference"; + case IEEETranEntryType.Patent: + return "Patent"; + case StandardEntryType.Online: + return "Web Page"; + case IEEETranEntryType.Electronic: + return "Electronic Article"; + case StandardEntryType.Misc: + return "Generic"; + default: + throw new IllegalArgumentException("Unsupported entry type: " + entryType); + } + } + )); + + private static final Map EXPORT_REF_NUMBER = ORDERED_ENTRY_TYPES.stream() + .collect(Collectors.toMap( + entryType -> entryType, + entryType -> Integer.toString(ORDERED_ENTRY_TYPES.indexOf(entryType) + 1) + )); private static final Map FIELD_MAPPING = Map.ofEntries( Map.entry(StandardField.TITLE, "title"), From 899a12da94d00ebde43be9a58e59d21422b8308c Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:23:22 +0530 Subject: [PATCH 28/78] Test run success, TBD --- .../logic/exporter/EndnoteXmlExporter.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index c8ec1d745f5..d3a67ad457d 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -29,21 +29,21 @@ public class EndnoteXmlExporter extends Exporter { private static final List ORDERED_ENTRY_TYPES = List.of( - StandardEntryType.Article, - StandardEntryType.Book, - StandardEntryType.InBook, - StandardEntryType.InCollection, - StandardEntryType.Proceedings, - StandardEntryType.MastersThesis, - StandardEntryType.PhdThesis, - StandardEntryType.TechReport, - StandardEntryType.Unpublished, - StandardEntryType.InProceedings, - StandardEntryType.Conference, - IEEETranEntryType.Patent, - StandardEntryType.Online, - IEEETranEntryType.Electronic, - StandardEntryType.Misc + StandardEntryType.Article, // Journal Article -1 + StandardEntryType.Book, // Book -2 + StandardEntryType.InBook, // Book Section -3 + StandardEntryType.InCollection, // Book Section -4 + StandardEntryType.Proceedings, // Conference Proceedings -5 + StandardEntryType.MastersThesis, // Thesis -6 + StandardEntryType.PhdThesis, // Thesis -7 + StandardEntryType.TechReport, // Report -8 + StandardEntryType.Unpublished, // Manuscript -9 + StandardEntryType.InProceedings, // Conference Paper -10 + StandardEntryType.Conference, // Conference -11 + IEEETranEntryType.Patent, // Patent -12 + StandardEntryType.Online, // Web Page -13 + IEEETranEntryType.Electronic, // Electronic Article -14 + StandardEntryType.Misc // Generic -15 ); private static final Map ENTRY_TYPE_MAPPING = ORDERED_ENTRY_TYPES.stream() From 73a498485ffcd055de457327b8426c79e559a9d7 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:32:24 +0530 Subject: [PATCH 29/78] Fix exporter test --- .../exporter/EndnoteXmlExporterTest.java | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index b2c55b27b83..fcf2eac5832 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -70,20 +70,18 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti " ", " Dai, H. K.", " ", + " New York, NY, USA", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 130--136", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", " Proceedings of the 9th International Symposium on Information and Communication Technology", - " SoICT '18", - " 130--136", + " 10.1145/3287921.3287982", " 2018", " 12", + " SoICT '18", " Association for Computing Machinery", - " New York, NY, USA", " 9781450365390", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 10.1145/3287921.3287982", - " Web-site traversal pattern", - " episode-rule mining", - " first local maximization", + " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", "" @@ -107,13 +105,12 @@ public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { " ", " Bhattacharyya, R. and McCormick, M. E.", " ", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", " 2013", " Elsevier Science", " 9780080442129", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", - " waves", - " agua", + " waves, agua", " ", " ", "" @@ -137,33 +134,30 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " ", " Dai, H. K.", " ", + " New York, NY, USA", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 130--136", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", " Proceedings of the 9th International Symposium on Information and Communication Technology", - " SoICT '18", - " 130--136", + " 10.1145/3287921.3287982", " 2018", " 12", + " SoICT '18", " Association for Computing Machinery", - " New York, NY, USA", " 9781450365390", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 10.1145/3287921.3287982", - " Web-site traversal pattern", - " episode-rule mining", - " first local maximization", + " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", " 2", " ", " Bhattacharyya, R. and McCormick, M. E.", " ", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", " 2013", " Elsevier Science", " 9780080442129", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", - " waves", - " agua", + " waves, agua", " ", " ", "" From 9df4fdbf60805c7456f6bfe9baa1d0fc46b0c87c Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:41:09 +0530 Subject: [PATCH 30/78] Fix exporter test-2 --- .../exporter/EndnoteXmlExporterTest.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index fcf2eac5832..bde98ade8ef 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -70,18 +70,18 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti " ", " Dai, H. K.", " ", - " New York, NY, USA", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 130--136", - " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " Proceedings of the 9th International Symposium on Information and Communication Technology", - " 10.1145/3287921.3287982", - " 2018", " 12", + " 10.1145/3287921.3287982", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", " SoICT '18", " Association for Computing Machinery", + " New York, NY, USA", " 9781450365390", " Web-site traversal pattern, episode-rule mining, first local maximization", + " 130--136", + " 2018", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", " ", " ", "" @@ -107,10 +107,10 @@ public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { "
", " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", - " 2013", " Elsevier Science", " 9780080442129", " waves, agua", + " 2013", " ", " ", "" @@ -134,18 +134,18 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " ", " Dai, H. K.", " ", - " New York, NY, USA", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 130--136", - " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " Proceedings of the 9th International Symposium on Information and Communication Technology", - " 10.1145/3287921.3287982", - " 2018", " 12", + " 10.1145/3287921.3287982", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", " SoICT '18", " Association for Computing Machinery", + " New York, NY, USA", " 9781450365390", " Web-site traversal pattern, episode-rule mining, first local maximization", + " 130--136", + " 2018", + " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", " ", " ", " 2", @@ -154,10 +154,10 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { "
", " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", - " 2013", " Elsevier Science", " 9780080442129", " waves, agua", + " 2013", " ", " ", "" @@ -167,11 +167,12 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { @Test public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { - Path file = tempDir.resolve("EmptyFile"); + Path file = tempDir.resolve("EmptyFile.xml"); exporter.export(databaseContext, file, Collections.emptyList()); - assertEquals(Collections.emptyList(), Files.readAllLines(file)); + assertEquals("\n\n \n", + Files.readString(file)); } @Test From fdf13573d0c60038fb1a1af0c1dbd27e2f6b37bb Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:43:49 +0530 Subject: [PATCH 31/78] Fix exporter test-3 --- .../org/jabref/logic/exporter/EndnoteXmlExporterTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index bde98ade8ef..28f078b2558 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -79,8 +79,8 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti " New York, NY, USA", " 9781450365390", " Web-site traversal pattern, episode-rule mining, first local maximization", - " 130--136", " 2018", + " 130--136", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", " ", " ", @@ -143,8 +143,8 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " New York, NY, USA", " 9781450365390", " Web-site traversal pattern, episode-rule mining, first local maximization", - " 130--136", " 2018", + " 130--136", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", " ", " ", From 1b290896422ae32dbefb7afed9ee1f69db66a165 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 15:54:32 +0530 Subject: [PATCH 32/78] Fix exporter test-4 --- .../exporter/EndnoteXmlExporterTest.java | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 28f078b2558..7d67073f8b7 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -70,18 +70,18 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti " ", " Dai, H. K.", " ", - " 12", - " 10.1145/3287921.3287982", - " Proceedings of the 9th International Symposium on Information and Communication Technology", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " SoICT '18", + " 12", " Association for Computing Machinery", " New York, NY, USA", - " 9781450365390", - " Web-site traversal pattern, episode-rule mining, first local maximization", - " 2018", " 130--136", + " 10.1145/3287921.3287982", + " SoICT '18", + " 9781450365390", + " Proceedings of the 9th International Symposium on Information and Communication Technology", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 2018", + " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", "" @@ -105,12 +105,12 @@ public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { " ", " Bhattacharyya, R. and McCormick, M. E.", " ", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", " Elsevier Science", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " 9780080442129", - " waves, agua", " 2013", + " waves, agua", " ", " ", "" @@ -134,30 +134,30 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " ", " Dai, H. K.", " ", - " 12", - " 10.1145/3287921.3287982", - " Proceedings of the 9th International Symposium on Information and Communication Technology", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " SoICT '18", + " 12", " Association for Computing Machinery", " New York, NY, USA", - " 9781450365390", - " Web-site traversal pattern, episode-rule mining, first local maximization", - " 2018", " 130--136", + " 10.1145/3287921.3287982", + " SoICT '18", + " 9781450365390", + " Proceedings of the 9th International Symposium on Information and Communication Technology", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", + " 2018", + " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", " 2", " ", " Bhattacharyya, R. and McCormick, M. E.", " ", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " Wave Energy Conversion", " Elsevier Science", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " 9780080442129", - " waves, agua", " 2013", + " waves, agua", " ", " ", "" @@ -171,8 +171,14 @@ public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { exporter.export(databaseContext, file, Collections.emptyList()); - assertEquals("\n\n \n", - Files.readString(file)); + List lines = Files.readAllLines(file); + String expectedXml = String.join(System.lineSeparator(), + "", + "", + " ", + "" + ); + assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); } @Test From b9bc72f805289bab6cf5d8b4c22fd3ec5f9f39f0 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 20:01:07 +0530 Subject: [PATCH 33/78] Fix order of fields in exporter, adapt test(1) --- .../logic/exporter/EndnoteXmlExporter.java | 99 +++++++------------ .../exporter/EndnoteXmlExporterTest.java | 32 +++--- 2 files changed, 52 insertions(+), 79 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index d3a67ad457d..4b7ae0b2150 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -28,68 +28,29 @@ import org.w3c.dom.Element; public class EndnoteXmlExporter extends Exporter { - private static final List ORDERED_ENTRY_TYPES = List.of( - StandardEntryType.Article, // Journal Article -1 - StandardEntryType.Book, // Book -2 - StandardEntryType.InBook, // Book Section -3 - StandardEntryType.InCollection, // Book Section -4 - StandardEntryType.Proceedings, // Conference Proceedings -5 - StandardEntryType.MastersThesis, // Thesis -6 - StandardEntryType.PhdThesis, // Thesis -7 - StandardEntryType.TechReport, // Report -8 - StandardEntryType.Unpublished, // Manuscript -9 - StandardEntryType.InProceedings, // Conference Paper -10 - StandardEntryType.Conference, // Conference -11 - IEEETranEntryType.Patent, // Patent -12 - StandardEntryType.Online, // Web Page -13 - IEEETranEntryType.Electronic, // Electronic Article -14 - StandardEntryType.Misc // Generic -15 + private static final List> ENTRY_TYPE_MAPPING_LIST = List.of( + Map.entry(StandardEntryType.Article, "Journal Article"), + Map.entry(StandardEntryType.Book, "Book"), + Map.entry(StandardEntryType.InBook, "Book Section"), + Map.entry(StandardEntryType.InCollection, "Book Section"), + Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), + Map.entry(StandardEntryType.MastersThesis, "Thesis"), + Map.entry(StandardEntryType.PhdThesis, "Thesis"), + Map.entry(StandardEntryType.TechReport, "Report"), + Map.entry(StandardEntryType.Unpublished, "Manuscript"), + Map.entry(StandardEntryType.InProceedings, "Conference Paper"), + Map.entry(StandardEntryType.Conference, "Conference"), + Map.entry(IEEETranEntryType.Patent, "Patent"), + Map.entry(StandardEntryType.Online, "Web Page"), + Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), + Map.entry(StandardEntryType.Misc, "Generic") ); - private static final Map ENTRY_TYPE_MAPPING = ORDERED_ENTRY_TYPES.stream() - .collect(Collectors.toMap( - entryType -> entryType, - entryType -> { - switch (entryType) { - case StandardEntryType.Article: - return "Journal Article"; - case StandardEntryType.Book: - return "Book"; - case StandardEntryType.InBook, StandardEntryType.InCollection: - return "Book Section"; - case StandardEntryType.Proceedings: - return "Conference Proceedings"; - case StandardEntryType.MastersThesis, StandardEntryType.PhdThesis: - return "Thesis"; - case StandardEntryType.TechReport: - return "Report"; - case StandardEntryType.Unpublished: - return "Manuscript"; - case StandardEntryType.InProceedings: - return "Conference Paper"; - case StandardEntryType.Conference: - return "Conference"; - case IEEETranEntryType.Patent: - return "Patent"; - case StandardEntryType.Online: - return "Web Page"; - case IEEETranEntryType.Electronic: - return "Electronic Article"; - case StandardEntryType.Misc: - return "Generic"; - default: - throw new IllegalArgumentException("Unsupported entry type: " + entryType); - } - } - )); - - private static final Map EXPORT_REF_NUMBER = ORDERED_ENTRY_TYPES.stream() - .collect(Collectors.toMap( - entryType -> entryType, - entryType -> Integer.toString(ORDERED_ENTRY_TYPES.indexOf(entryType) + 1) - )); - - private static final Map FIELD_MAPPING = Map.ofEntries( + private static final List> EXPORT_REF_NUMBER_LIST = ENTRY_TYPE_MAPPING_LIST.stream() + .map(entry -> Map.entry(entry.getKey(), Integer.toString(ENTRY_TYPE_MAPPING_LIST.indexOf(entry) + 1))) + .collect(Collectors.toList()); + + private static final List> FIELD_MAPPING_LIST = List.of( Map.entry(StandardField.TITLE, "title"), Map.entry(StandardField.AUTHOR, "authors"), Map.entry(StandardField.EDITOR, "secondary-authors"), @@ -148,12 +109,24 @@ public void export(BibDatabaseContext databaseContext, Path file, List Element recordElement = document.createElement("record"); recordsElement.appendChild(recordElement); + // Map entry type // Map entry type EntryType entryType = entry.getType(); - String refType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, "Generic"); + String refType = ENTRY_TYPE_MAPPING_LIST.stream() + .filter(mapping -> mapping.getKey().equals(entryType)) + .map(Map.Entry::getValue) + .findFirst() + .orElse("Generic"); + + String refNumber = EXPORT_REF_NUMBER_LIST.stream() + .filter(mapping -> mapping.getKey().equals(entryType)) + .map(Map.Entry::getValue) + .findFirst() + .orElse("15"); + Element refTypeElement = document.createElement("ref-type"); refTypeElement.setAttribute("name", refType); - refTypeElement.setTextContent(EXPORT_REF_NUMBER.getOrDefault(entryType, "Generic")); + refTypeElement.setTextContent(refNumber); recordElement.appendChild(refTypeElement); // Map authors and editors @@ -174,7 +147,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List }); // Map fields - for (Map.Entry fieldMapping : FIELD_MAPPING.entrySet()) { + for (Map.Entry fieldMapping : FIELD_MAPPING_LIST) { Field field = fieldMapping.getKey(); String xmlElement = fieldMapping.getValue(); diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 7d67073f8b7..bc8f317c995 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -66,21 +66,21 @@ public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Excepti "", " ", " ", - " 11", + " 10", " ", " Dai, H. K.", " ", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", + " 2018", " 12", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " SoICT '18", + " 130--136", " Association for Computing Machinery", " New York, NY, USA", - " 130--136", - " 10.1145/3287921.3287982", - " SoICT '18", " 9781450365390", - " Proceedings of the 9th International Symposium on Information and Communication Technology", + " 10.1145/3287921.3287982", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 2018", " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", @@ -106,10 +106,10 @@ public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { " Bhattacharyya, R. and McCormick, M. E.", "
", " Wave Energy Conversion", + " 2013", " Elsevier Science", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " 9780080442129", - " 2013", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " waves, agua", " ", " ", @@ -130,21 +130,21 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { "", " ", " ", - " 11", + " 10", " ", " Dai, H. K.", " ", " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", + " 2018", " 12", + " Proceedings of the 9th International Symposium on Information and Communication Technology", + " SoICT '18", + " 130--136", " Association for Computing Machinery", " New York, NY, USA", - " 130--136", - " 10.1145/3287921.3287982", - " SoICT '18", " 9781450365390", - " Proceedings of the 9th International Symposium on Information and Communication Technology", + " 10.1145/3287921.3287982", " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 2018", " Web-site traversal pattern, episode-rule mining, first local maximization", " ", " ", @@ -153,10 +153,10 @@ public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { " Bhattacharyya, R. and McCormick, M. E.", "
", " Wave Energy Conversion", + " 2013", " Elsevier Science", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " 9780080442129", - " 2013", + " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", " waves, agua", " ", " ", From 0cfb995b50314d7e033e017dbf3da64dd1b31136 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 14 Apr 2024 16:49:37 +0200 Subject: [PATCH 34/78] Extract test resources Add roundrip test move mapping to a new method --- .../logic/exporter/EndnoteXmlExporter.java | 68 +++---- .../exporter/EndnoteXmlExporterTest.java | 178 +++--------------- .../exporter/EndnoteXmlExporterTestFiles.java | 100 ++++++++++ .../EndnoteXmlExportTestMultipleEntries.bib | 30 +++ .../EndnoteXmlExportTestMultipleEntries.xml | 35 ++++ .../EndnoteXmlExportTestSingleBookEntry.bib | 13 ++ .../EndnoteXmlExportTestSingleBookEntry.xml | 17 ++ 7 files changed, 257 insertions(+), 184 deletions(-) create mode 100644 src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java create mode 100644 src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib create mode 100644 src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml create mode 100644 src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib create mode 100644 src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index d3a67ad457d..49c9829167b 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -49,40 +49,44 @@ public class EndnoteXmlExporter extends Exporter { private static final Map ENTRY_TYPE_MAPPING = ORDERED_ENTRY_TYPES.stream() .collect(Collectors.toMap( entryType -> entryType, - entryType -> { - switch (entryType) { - case StandardEntryType.Article: - return "Journal Article"; - case StandardEntryType.Book: - return "Book"; - case StandardEntryType.InBook, StandardEntryType.InCollection: - return "Book Section"; - case StandardEntryType.Proceedings: - return "Conference Proceedings"; - case StandardEntryType.MastersThesis, StandardEntryType.PhdThesis: - return "Thesis"; - case StandardEntryType.TechReport: - return "Report"; - case StandardEntryType.Unpublished: - return "Manuscript"; - case StandardEntryType.InProceedings: - return "Conference Paper"; - case StandardEntryType.Conference: - return "Conference"; - case IEEETranEntryType.Patent: - return "Patent"; - case StandardEntryType.Online: - return "Web Page"; - case IEEETranEntryType.Electronic: - return "Electronic Article"; - case StandardEntryType.Misc: - return "Generic"; - default: - throw new IllegalArgumentException("Unsupported entry type: " + entryType); - } - } + EndnoteXmlExporter::getEndnoteEntryType )); + private static String getEndnoteEntryType(EntryType entryType) { + return switch (entryType) { + case StandardEntryType.Article -> + "Journal Article"; + case StandardEntryType.Book -> + "Book"; + case StandardEntryType.InBook, + StandardEntryType.InCollection -> + "Book Section"; + case StandardEntryType.Proceedings -> + "Conference Proceedings"; + case StandardEntryType.MastersThesis, + StandardEntryType.PhdThesis -> + "Thesis"; + case StandardEntryType.TechReport -> + "Report"; + case StandardEntryType.Unpublished -> + "Manuscript"; + case StandardEntryType.InProceedings -> + "Conference Paper"; + case StandardEntryType.Conference -> + "Conference"; + case IEEETranEntryType.Patent -> + "Patent"; + case StandardEntryType.Online -> + "Web Page"; + case IEEETranEntryType.Electronic -> + "Electronic Article"; + case StandardEntryType.Misc -> + "Generic"; + default -> + throw new IllegalArgumentException("Unsupported entry type: " + entryType); + }; + } + private static final Map EXPORT_REF_NUMBER = ORDERED_ENTRY_TYPES.stream() .collect(Collectors.toMap( entryType -> entryType, diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index 7d67073f8b7..b1af4b09567 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -3,166 +3,48 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; -import java.util.List; +import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.preferences.BibEntryPreferences; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.mockito.Answers; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class EndnoteXmlExporterTest { + private Exporter exporter; - private final BibDatabaseContext databaseContext = new BibDatabaseContext(); - private BibEntry conferenceEntry; + private BibDatabaseContext databaseContext; private BibEntry bookEntry; @BeforeEach - public void setUp() { - exporter = new EndnoteXmlExporter(); - - conferenceEntry = new BibEntry(StandardEntryType.Conference); - conferenceEntry.setCitationKey("Dai2018"); - conferenceEntry.setField(StandardField.AUTHOR, "Dai, H. K."); - conferenceEntry.setField(StandardField.TITLE, "Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence"); - conferenceEntry.setField(StandardField.BOOKTITLE, "Proceedings of the 9th International Symposium on Information and Communication Technology"); - conferenceEntry.setField(StandardField.YEAR, "2018"); - conferenceEntry.setField(StandardField.MONTH, "12"); - conferenceEntry.setField(StandardField.SERIES, "SoICT '18"); - conferenceEntry.setField(StandardField.PAGES, "130--136"); - conferenceEntry.setField(StandardField.ADDRESS, "New York, NY, USA"); - conferenceEntry.setField(StandardField.PUBLISHER, "Association for Computing Machinery"); - conferenceEntry.setField(StandardField.DOI, "10.1145/3287921.3287982"); - conferenceEntry.setField(StandardField.ISBN, "9781450365390"); - conferenceEntry.setField(StandardField.ABSTRACT, "An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets."); - conferenceEntry.setField(StandardField.KEYWORDS, "Web-site traversal pattern, episode-rule mining, first local maximization"); - - bookEntry = new BibEntry(StandardEntryType.Book); - bookEntry.setCitationKey("Bhattacharyya2013"); - bookEntry.setField(StandardField.EDITOR, "Bhattacharyya, R. and McCormick, M. E."); - bookEntry.setField(StandardField.PUBLISHER, "Elsevier Science"); - bookEntry.setField(StandardField.TITLE, "Wave Energy Conversion"); - bookEntry.setField(StandardField.YEAR, "2013"); - bookEntry.setField(StandardField.ISBN, "9780080442129"); - bookEntry.setField(StandardField.FILE, "/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf"); - bookEntry.setField(StandardField.KEYWORDS, "waves, agua"); - } - - @Test - public void exportForSingleConferenceEntry(@TempDir Path tempDir) throws Exception { - Path file = tempDir.resolve("ConferenceEntry.xml"); - - exporter.export(databaseContext, file, Collections.singletonList(conferenceEntry)); - - List lines = Files.readAllLines(file); - String expectedXml = String.join(System.lineSeparator(), - "", - "", - " ", - " ", - " 11", - " ", - " Dai, H. K.", - " ", - " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " 12", - " Association for Computing Machinery", - " New York, NY, USA", - " 130--136", - " 10.1145/3287921.3287982", - " SoICT '18", - " 9781450365390", - " Proceedings of the 9th International Symposium on Information and Communication Technology", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 2018", - " Web-site traversal pattern, episode-rule mining, first local maximization", - " ", - " ", - "" - ); - assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); - } + public void setUp(@TempDir Path testFolder) throws Exception { + ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); + when(importFormatPreferences.bibEntryPreferences()).thenReturn(mock(BibEntryPreferences.class)); + when(importFormatPreferences.bibEntryPreferences().getKeywordSeparator()).thenReturn(','); - @Test - public void exportForSingleBookEntry(@TempDir Path tempDir) throws Exception { - Path file = tempDir.resolve("BookEntry.xml"); - - exporter.export(databaseContext, file, Collections.singletonList(bookEntry)); - - List lines = Files.readAllLines(file); - String expectedXml = String.join(System.lineSeparator(), - "", - "", - " ", - " ", - " 2", - " ", - " Bhattacharyya, R. and McCormick, M. E.", - " ", - " Wave Energy Conversion", - " Elsevier Science", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", - " 9780080442129", - " 2013", - " waves, agua", - " ", - " ", - "" - ); - assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); - } + databaseContext = new BibDatabaseContext(); + exporter = new EndnoteXmlExporter(); - @Test - public void exportForMultipleEntries(@TempDir Path tempDir) throws Exception { - Path file = tempDir.resolve("MultipleEntries.xml"); - - exporter.export(databaseContext, file, List.of(conferenceEntry, bookEntry)); - - List lines = Files.readAllLines(file); - String expectedXml = String.join(System.lineSeparator(), - "", - "", - " ", - " ", - " 11", - " ", - " Dai, H. K.", - " ", - " Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence", - " 12", - " Association for Computing Machinery", - " New York, NY, USA", - " 130--136", - " 10.1145/3287921.3287982", - " SoICT '18", - " 9781450365390", - " Proceedings of the 9th International Symposium on Information and Communication Technology", - " An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.", - " 2018", - " Web-site traversal pattern, episode-rule mining, first local maximization", - " ", - " ", - " 2", - " ", - " Bhattacharyya, R. and McCormick, M. E.", - " ", - " Wave Energy Conversion", - " Elsevier Science", - " /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf", - " 9780080442129", - " 2013", - " waves, agua", - " ", - " ", - "" - ); - assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); + bookEntry = new BibEntry(StandardEntryType.Book) + .withCitationKey("Bhattacharyya2013") + .withField(StandardField.EDITOR, "Bhattacharyya, R. and McCormick, M. E.") + .withField(StandardField.PUBLISHER, "Elsevier Science") + .withField(StandardField.TITLE, "Wave Energy Conversion") + .withField(StandardField.YEAR, "2013") + .withField(StandardField.ISBN, "9780080442129") + .withField(StandardField.FILE, "/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf") + .withField(StandardField.KEYWORDS, "waves, agua"); } @Test @@ -170,15 +52,7 @@ public void exportForEmptyEntryList(@TempDir Path tempDir) throws Exception { Path file = tempDir.resolve("EmptyFile.xml"); exporter.export(databaseContext, file, Collections.emptyList()); - - List lines = Files.readAllLines(file); - String expectedXml = String.join(System.lineSeparator(), - "", - "", - " ", - "" - ); - assertEquals(expectedXml, String.join(System.lineSeparator(), lines)); + assertFalse(Files.exists(file)); } @Test @@ -186,13 +60,13 @@ public void exportForNullDBThrowsException(@TempDir Path tempDir) { Path file = tempDir.resolve("NullDB"); assertThrows(NullPointerException.class, () -> - exporter.export(null, file, Collections.singletonList(conferenceEntry))); + exporter.export(null, file, Collections.singletonList(bookEntry))); } @Test public void exportForNullExportPathThrowsException(@TempDir Path tempDir) { assertThrows(NullPointerException.class, () -> - exporter.export(databaseContext, null, Collections.singletonList(conferenceEntry))); + exporter.export(databaseContext, null, Collections.singletonList(bookEntry))); } @Test diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java new file mode 100644 index 00000000000..7b544d4637b --- /dev/null +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java @@ -0,0 +1,100 @@ +package org.jabref.logic.exporter; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Stream; + +import org.jabref.logic.bibtex.BibEntryAssert; +import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.fileformat.BibtexImporter; +import org.jabref.logic.importer.fileformat.EndnoteXmlImporter; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.util.DummyFileUpdateMonitor; +import org.jabref.preferences.BibEntryPreferences; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Answers; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.ElementSelectors; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; + +public class EndnoteXmlExporterTestFiles { + + private Exporter exporter; + private BibDatabaseContext databaseContext; + private Path exportedFile; + private Path importFile; + private BibtexImporter bibtexImporter; + private EndnoteXmlImporter endnoteXmlImporter; + + @BeforeEach + public void setUp(@TempDir Path testFolder) throws Exception { + ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); + when(importFormatPreferences.bibEntryPreferences()).thenReturn(mock(BibEntryPreferences.class)); + when(importFormatPreferences.bibEntryPreferences().getKeywordSeparator()).thenReturn(','); + + databaseContext = new BibDatabaseContext(); + exporter = new EndnoteXmlExporter(); + endnoteXmlImporter = new EndnoteXmlImporter(importFormatPreferences); + bibtexImporter = new BibtexImporter(importFormatPreferences, new DummyFileUpdateMonitor()); + + Path path = testFolder.resolve("ARandomlyNamedFile.tmp"); + Files.createFile(path); + exportedFile = path.toAbsolutePath(); + } + + static Stream fileNames() throws IOException, URISyntaxException { + // we have to point it to one existing file, otherwise it will return the default class path + Path resourceDir = Path.of(EndnoteXmlExporterTestFiles.class.getResource("EndnoteXmlExportTestSingleBookEntry.bib").toURI()).getParent(); + try (Stream stream = Files.list(resourceDir)) { + return stream.map(n -> n.getFileName().toString()) + .filter(n -> n.endsWith(".bib")) + .filter(n -> n.startsWith("EndnoteXml")) + // mapping required, because we get "source already consumed or closed" otherwise + .toList().stream(); + } + } + + @ParameterizedTest + @MethodSource("fileNames") + public final void performExport(String filename) throws Exception { + importFile = Path.of(EndnoteXmlExporterTestFiles.class.getResource(filename).toURI()); + String xmlFileName = filename.replace(".bib", ".xml"); + List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); + Path expectedFile = Path.of(ModsExportFormatFilesTest.class.getResource(xmlFileName).toURI()); + + exporter.export(databaseContext, exportedFile, entries); + + String expected = String.join("\n", Files.readAllLines(expectedFile)); + String actual = String.join("\n", Files.readAllLines(exportedFile)); + + // The order of the XML elements changes + // The order does not really matter, so we ignore it. + // Source: https://stackoverflow.com/a/16540679/873282 + assertThat(expected, isSimilarTo(actual) + .ignoreWhitespace() + .normalizeWhitespace() + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + } + + @ParameterizedTest + @MethodSource("fileNames") + public final void exportAsEndnoteAndThenImportAsEndnote(String filename) throws Exception { + importFile = Path.of(EndnoteXmlExporterTestFiles.class.getResource(filename).toURI()); + List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); + + exporter.export(databaseContext, exportedFile, entries); + BibEntryAssert.assertEquals(entries, exportedFile, endnoteXmlImporter); + } +} diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib new file mode 100644 index 00000000000..6c8150f6262 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib @@ -0,0 +1,30 @@ +% Encoding: UTF-8 + +@conference{Dai2018, + abstract = {An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.}, + address = {New York, NY, USA}, + author = {Dai, H. K.}, + booktitle = {Proceedings of the 9th International Symposium on Information and Communication Technology}, + doi = {10.1145/3287921.3287982}, + isbn = {9781450365390}, + keywords = {Web-site traversal pattern, episode-rule mining, first local maximization}, + month = {12}, + pages = {130--136}, + publisher = {Association for Computing Machinery}, + series = {SoICT '18}, + title = {Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence}, + year = {2018}, +} + +@book{Bhattacharyya2013, + editor = {Bhattacharyya, R. and McCormick, M. E.}, + file = {/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf}, + isbn = {9780080442129}, + keywords = {waves, agua}, + publisher = {Elsevier Science}, + title = {Wave Energy Conversion}, + year = {2013}, +} + +@Comment{jabref-meta: databaseType:bibtex;} + diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml new file mode 100644 index 00000000000..220cc68db8d --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml @@ -0,0 +1,35 @@ + + + + + 11 + + Dai, H. K. + + Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence + 12 + Association for Computing Machinery + New York, NY, USA + 130--136 + 10.1145/3287921.3287982 + SoICT '18 + 9781450365390 + Proceedings of the 9th International Symposium on Information and Communication Technology + An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets. + 2018 + Web-site traversal pattern, episode-rule mining, first local maximization + + + 2 + + Bhattacharyya, R. and McCormick, M. E. + + Wave Energy Conversion + Elsevier Science + /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf + 9780080442129 + 2013 + waves, agua + + + diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib new file mode 100644 index 00000000000..d9198c49d37 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib @@ -0,0 +1,13 @@ +% Encoding: UTF-8 + +@book{Bhattacharyya2013, + editor = {Bhattacharyya, R. and McCormick, M. E.}, + file = {/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf}, + isbn = {9780080442129}, + keywords = {waves, agua}, + publisher = {Elsevier Science}, + title = {Wave Energy Conversion}, + year = {2013}, +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml new file mode 100644 index 00000000000..b0504678184 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml @@ -0,0 +1,17 @@ + + + + + 2 + + Bhattacharyya, R. and McCormick, M. E. + + Wave Energy Conversion + Elsevier Science + /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf + 9780080442129 + 2013 + waves, agua + + + From 1ad21894a4815ec085ba745bdf0f7314c914e757 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 14 Apr 2024 21:51:17 +0530 Subject: [PATCH 35/78] Exporter Beta, Importer TODO! --- .../logic/exporter/EndnoteXmlExporter.java | 150 +++++++++--- .../fileformat/EndnoteXmlImporter.java | 224 ++++++++++++------ 2 files changed, 277 insertions(+), 97 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 4b7ae0b2150..3e1dec62f84 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -48,37 +47,37 @@ public class EndnoteXmlExporter extends Exporter { private static final List> EXPORT_REF_NUMBER_LIST = ENTRY_TYPE_MAPPING_LIST.stream() .map(entry -> Map.entry(entry.getKey(), Integer.toString(ENTRY_TYPE_MAPPING_LIST.indexOf(entry) + 1))) - .collect(Collectors.toList()); + .toList(); private static final List> FIELD_MAPPING_LIST = List.of( Map.entry(StandardField.TITLE, "title"), Map.entry(StandardField.AUTHOR, "authors"), Map.entry(StandardField.EDITOR, "secondary-authors"), - Map.entry(StandardField.YEAR, "year"), - Map.entry(StandardField.MONTH, "pub-dates"), + Map.entry(StandardField.PAGES, "pages"), + Map.entry(StandardField.VOLUME, "volume"), + Map.entry(StandardField.KEYWORDS, "keywords"), + // Map.entry(StandardField.YEAR, "year"), + // Map.entry(StandardField.MONTH, "pub-dates"), + Map.entry(StandardField.PUBLISHER, "publisher"), + Map.entry(StandardField.ISBN, "isbn"), + Map.entry(StandardField.DOI, "electronic-resource-num"), + Map.entry(StandardField.ABSTRACT, "abstract"), + Map.entry(StandardField.URL, "web-urls"), + Map.entry(StandardField.FILE, "pdf-urls"), Map.entry(StandardField.JOURNAL, "full-title"), Map.entry(StandardField.JOURNALTITLE, "full-title"), Map.entry(StandardField.BOOKTITLE, "secondary-title"), Map.entry(StandardField.EDITION, "edition"), Map.entry(StandardField.SERIES, "tertiary-title"), - Map.entry(StandardField.VOLUME, "volume"), Map.entry(StandardField.NUMBER, "number"), Map.entry(StandardField.ISSUE, "issue"), - Map.entry(StandardField.PAGES, "pages"), - Map.entry(StandardField.PUBLISHER, "publisher"), Map.entry(StandardField.ADDRESS, "pub-location"), Map.entry(StandardField.CHAPTER, "section"), Map.entry(StandardField.HOWPUBLISHED, "work-type"), Map.entry(StandardField.INSTITUTION, "publisher"), Map.entry(StandardField.ORGANIZATION, "publisher"), Map.entry(StandardField.SCHOOL, "publisher"), - Map.entry(StandardField.ISBN, "isbn"), - Map.entry(StandardField.ISSN, "isbn"), - Map.entry(StandardField.DOI, "electronic-resource-num"), - Map.entry(StandardField.URL, "web-urls"), - Map.entry(StandardField.FILE, "pdf-urls"), - Map.entry(StandardField.ABSTRACT, "abstract"), - Map.entry(StandardField.KEYWORDS, "keywords") + Map.entry(StandardField.ISSN, "isbn") ); public EndnoteXmlExporter() { @@ -109,7 +108,6 @@ public void export(BibDatabaseContext databaseContext, Path file, List Element recordElement = document.createElement("record"); recordsElement.appendChild(recordElement); - // Map entry type // Map entry type EntryType entryType = entry.getType(); String refType = ENTRY_TYPE_MAPPING_LIST.stream() @@ -129,29 +127,87 @@ public void export(BibDatabaseContext databaseContext, Path file, List refTypeElement.setTextContent(refNumber); recordElement.appendChild(refTypeElement); - // Map authors and editors + // Map database and source-app + Element databaseElement = document.createElement("database"); + databaseElement.setAttribute("name", "MyLibrary"); + databaseElement.setTextContent("MyLibrary"); + recordElement.appendChild(databaseElement); + + Element sourceAppElement = document.createElement("source-app"); + sourceAppElement.setAttribute("name", "JabRef"); + sourceAppElement.setTextContent("JabRef"); + recordElement.appendChild(sourceAppElement); + + // Map contributors (authors and editors) + Element contributorsElement = document.createElement("contributors"); entry.getField(StandardField.AUTHOR).ifPresent(authors -> { - Element authorsElement = document.createElement("contributors"); - Element authorsNameElement = document.createElement("authors"); - authorsNameElement.setTextContent(authors); - authorsElement.appendChild(authorsNameElement); - recordElement.appendChild(authorsElement); + Element authorsElement = document.createElement("authors"); + String[] authorArray = authors.split("\\s+and\\s+"); + for (String author : authorArray) { + Element authorElement = document.createElement("author"); + authorElement.setTextContent(author); + authorsElement.appendChild(authorElement); + } + contributorsElement.appendChild(authorsElement); }); entry.getField(StandardField.EDITOR).ifPresent(editors -> { - Element contributorsElement = document.createElement("contributors"); - Element editorsElement = document.createElement("secondary-authors"); - editorsElement.setTextContent(editors); - contributorsElement.appendChild(editorsElement); + Element secondaryAuthorsElement = document.createElement("secondary-authors"); + secondaryAuthorsElement.setTextContent(editors); + contributorsElement.appendChild(secondaryAuthorsElement); + }); + + if (contributorsElement.hasChildNodes()) { recordElement.appendChild(contributorsElement); + } + + // Map titles + Element titlesElement = document.createElement("titles"); + entry.getField(StandardField.TITLE).ifPresent(title -> { + Element titleElement = document.createElement("title"); + titleElement.setTextContent(title); + titlesElement.appendChild(titleElement); + }); + + entry.getField(StandardField.JOURNAL).ifPresent(journal -> { + Element secondaryTitleElement = document.createElement("secondary-title"); + secondaryTitleElement.setTextContent(journal); + titlesElement.appendChild(secondaryTitleElement); + }); + + if (titlesElement.hasChildNodes()) { + recordElement.appendChild(titlesElement); + } + + // Map periodical and full-title + entry.getField(StandardField.JOURNALTITLE).ifPresent(journalTitle -> { + Element periodicalElement = document.createElement("periodical"); + Element fullTitleElement = document.createElement("full-title"); + fullTitleElement.setTextContent(journalTitle); + periodicalElement.appendChild(fullTitleElement); + recordElement.appendChild(periodicalElement); + }); + + // Map keywords + entry.getField(StandardField.KEYWORDS).ifPresent(keywords -> { + Element keywordsElement = document.createElement("keywords"); + String[] keywordArray = keywords.split(",\\s*"); + for (String keyword : keywordArray) { + Element keywordElement = document.createElement("keyword"); + keywordElement.setTextContent(keyword); + keywordsElement.appendChild(keywordElement); + } + recordElement.appendChild(keywordsElement); }); - // Map fields + // Map other fields for (Map.Entry fieldMapping : FIELD_MAPPING_LIST) { Field field = fieldMapping.getKey(); String xmlElement = fieldMapping.getValue(); - if (field != StandardField.AUTHOR && field != StandardField.EDITOR) { + if (field != StandardField.AUTHOR && field != StandardField.EDITOR && + field != StandardField.TITLE && field != StandardField.JOURNAL && + field != StandardField.JOURNALTITLE && field != StandardField.KEYWORDS && field != StandardField.YEAR && field != StandardField.DATE) { entry.getField(field).ifPresent(value -> { Element fieldElement = document.createElement(xmlElement); fieldElement.setTextContent(value); @@ -159,6 +215,46 @@ public void export(BibDatabaseContext databaseContext, Path file, List }); } } + + // Map dates + Element datesElement = document.createElement("dates"); + entry.getField(StandardField.YEAR).ifPresent(year -> { + Element yearElement = document.createElement("year"); + yearElement.setTextContent(year); + datesElement.appendChild(yearElement); + }); + entry.getField(StandardField.DATE).ifPresent(date -> { + Element pubDatesElement = document.createElement("pub-dates"); + Element dateElement = document.createElement("date"); + dateElement.setTextContent(date); + pubDatesElement.appendChild(dateElement); + datesElement.appendChild(pubDatesElement); + }); + if (datesElement.hasChildNodes()) { + recordElement.appendChild(datesElement); + } + + // Map URLs + Element urlsElement = document.createElement("urls"); + entry.getField(StandardField.FILE).ifPresent(fileField -> { + Element pdfUrlsElement = document.createElement("pdf-urls"); + Element urlElement = document.createElement("url"); + urlElement.setTextContent(fileField); + pdfUrlsElement.appendChild(urlElement); + urlsElement.appendChild(pdfUrlsElement); + }); + + entry.getField(StandardField.URL).ifPresent(url -> { + Element webUrlsElement = document.createElement("web-urls"); + Element urlElement = document.createElement("url"); + urlElement.setTextContent(url); + webUrlsElement.appendChild(urlElement); + urlsElement.appendChild(webUrlsElement); + }); + + if (urlsElement.hasChildNodes()) { + recordElement.appendChild(urlsElement); + } } TransformerFactory transformerFactory = TransformerFactory.newInstance(); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index e84d0cbe105..257425819b8 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -4,11 +4,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -24,8 +26,11 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.KeywordList; +import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -36,54 +41,48 @@ public class EndnoteXmlImporter extends Importer implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(EndnoteXmlImporter.class); - private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( - Map.entry(StandardEntryType.Article, "Journal Article"), - Map.entry(StandardEntryType.Book, "Book"), - Map.entry(StandardEntryType.InBook, "Book Section"), - Map.entry(StandardEntryType.InCollection, "Book Section"), - Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), - Map.entry(StandardEntryType.MastersThesis, "Thesis"), - Map.entry(StandardEntryType.PhdThesis, "Thesis"), - Map.entry(StandardEntryType.TechReport, "Report"), - Map.entry(StandardEntryType.Unpublished, "Manuscript"), - Map.entry(StandardEntryType.InProceedings, "Conference Paper"), - Map.entry(StandardEntryType.Conference, "Conference"), - Map.entry(IEEETranEntryType.Patent, "Patent"), - Map.entry(StandardEntryType.Online, "Web Page"), - Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), - Map.entry(StandardEntryType.Misc, "Generic") + private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( + Map.entry("Journal Article", StandardEntryType.Article), + Map.entry("Book", StandardEntryType.Book), + Map.entry("Book Section", StandardEntryType.InBook), + Map.entry("Conference Proceedings", StandardEntryType.Proceedings), + Map.entry("Thesis", StandardEntryType.Thesis), + Map.entry("Report", StandardEntryType.Report), + Map.entry("Manuscript", StandardEntryType.Unpublished), + Map.entry("Conference Paper", StandardEntryType.InProceedings), + Map.entry("Conference", StandardEntryType.Conference), + Map.entry("Patent", IEEETranEntryType.Patent), + Map.entry("Web Page", StandardEntryType.Online), + Map.entry("Electronic Article", IEEETranEntryType.Electronic), + Map.entry("Generic", StandardEntryType.Misc) ); - private static final Map FIELD_MAPPING = Map.ofEntries( - Map.entry(StandardField.TITLE, "title"), - Map.entry(StandardField.AUTHOR, "authors"), - Map.entry(StandardField.EDITOR, "secondary-authors"), - Map.entry(StandardField.YEAR, "year"), - Map.entry(StandardField.MONTH, "pub-dates"), - Map.entry(StandardField.JOURNAL, "full-title"), - Map.entry(StandardField.JOURNALTITLE, "full-title"), - Map.entry(StandardField.BOOKTITLE, "secondary-title"), - Map.entry(StandardField.EDITION, "edition"), - Map.entry(StandardField.SERIES, "tertiary-title"), - Map.entry(StandardField.VOLUME, "volume"), - Map.entry(StandardField.NUMBER, "number"), - Map.entry(StandardField.ISSUE, "issue"), - Map.entry(StandardField.PAGES, "pages"), - Map.entry(StandardField.PUBLISHER, "publisher"), - Map.entry(StandardField.ADDRESS, "pub-location"), - Map.entry(StandardField.CHAPTER, "section"), - Map.entry(StandardField.HOWPUBLISHED, "work-type"), - Map.entry(StandardField.INSTITUTION, "publisher"), - Map.entry(StandardField.ORGANIZATION, "publisher"), - Map.entry(StandardField.SCHOOL, "publisher"), - Map.entry(StandardField.ISBN, "isbn"), - Map.entry(StandardField.ISSN, "isbn"), - Map.entry(StandardField.DOI, "electronic-resource-num"), - Map.entry(StandardField.URL, "web-urls"), - Map.entry(StandardField.FILE, "pdf-urls"), - Map.entry(StandardField.ABSTRACT, "abstract"), - Map.entry(StandardField.KEYWORDS, "keywords") + private static final Map FIELD_MAPPING = Map.ofEntries( + Map.entry("title", StandardField.TITLE), + Map.entry("authors", StandardField.AUTHOR), + Map.entry("secondary-authors", StandardField.EDITOR), + Map.entry("pages", StandardField.PAGES), + Map.entry("volume", StandardField.VOLUME), + Map.entry("keywords", StandardField.KEYWORDS), + Map.entry("year", StandardField.YEAR), + Map.entry("pub-dates", StandardField.DATE), + Map.entry("publisher", StandardField.PUBLISHER), + Map.entry("isbn", StandardField.ISBN), + Map.entry("electronic-resource-num", StandardField.DOI), + Map.entry("abstract", StandardField.ABSTRACT), + Map.entry("web-urls", StandardField.URL), + Map.entry("pdf-urls", StandardField.FILE), + Map.entry("full-title", StandardField.JOURNAL), + Map.entry("secondary-title", StandardField.BOOKTITLE), + Map.entry("edition", StandardField.EDITION), + Map.entry("tertiary-title", StandardField.SERIES), + Map.entry("number", StandardField.NUMBER), + Map.entry("issue", StandardField.ISSUE), + Map.entry("pub-location", StandardField.ADDRESS), + Map.entry("section", StandardField.CHAPTER), + Map.entry("work-type", StandardField.HOWPUBLISHED) ); + private final ImportFormatPreferences preferences; private final XMLInputFactory xmlInputFactory; @@ -114,13 +113,11 @@ public String getDescription() { @Override public boolean isRecognizedFormat(BufferedReader reader) throws IOException { - String str; - int i = 0; - while (((str = reader.readLine()) != null) && (i < 50)) { - if (str.toLowerCase(Locale.ENGLISH).contains("")) { + String line; + while ((line = reader.readLine()) != null) { + if (line.trim().startsWith("") && line.trim().contains("")) { return true; } - i++; } return false; } @@ -142,7 +139,7 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { } } } catch (XMLStreamException e) { - LOGGER.debug("could not parse document", e); + LOGGER.debug("Could not parse document", e); return ParserResult.fromError(e); } return new ParserResult(bibItems); @@ -150,6 +147,9 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { BibEntry entry = new BibEntry(); + Map fields = new HashMap<>(); + KeywordList keywordList = new KeywordList(); + List linkedFiles = new ArrayList<>(); while (reader.hasNext()) { reader.next(); @@ -162,34 +162,42 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { switch (elementName) { case "ref-type" -> { String refType = reader.getAttributeValue(null, "name"); - EntryType entryType = ENTRY_TYPE_MAPPING.entrySet().stream() - .filter(e -> e.getValue().equals(refType)) - .map(Map.Entry::getKey) - .findFirst() - .orElse(StandardEntryType.Misc); - entry.setType(entryType); + EntryType entryType = ENTRY_TYPE_MAPPING.get(refType); + if (entryType != null) { + entry.setType(entryType); + } } case "contributors" -> { - parseContributors(reader, entry); + parseContributors(reader, fields); + } + case "titles" -> { + parseTitles(reader, fields); + } + case "keywords" -> { + parseKeywords(reader, keywordList); + } + case "urls" -> { + parseUrls(reader, fields, linkedFiles); } default -> { - Field field = FIELD_MAPPING.entrySet().stream() - .filter(e -> e.getValue().equals(elementName)) - .map(Map.Entry::getKey) - .findFirst() - .orElse(null); + Field field = FIELD_MAPPING.get(elementName); if (field != null) { - entry.setField(field, reader.getElementText()); + fields.put(field, reader.getElementText()); + } else { + fields.put(new UnknownField(elementName), reader.getElementText()); } } } } } + entry.setField(fields); + entry.putKeywords(keywordList, preferences.bibEntryPreferences().getKeywordSeparator()); + entry.setFiles(linkedFiles); return entry; } - private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { + private void parseContributors(XMLStreamReader reader, Map fields) throws XMLStreamException { while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "contributors")) { @@ -200,10 +208,87 @@ private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XM String elementName = reader.getName().getLocalPart(); switch (elementName) { case "authors" -> { - entry.setField(StandardField.AUTHOR, reader.getElementText()); + fields.put(StandardField.AUTHOR, parseAuthors(reader)); } case "secondary-authors" -> { - entry.setField(StandardField.EDITOR, reader.getElementText()); + fields.put(StandardField.EDITOR, parseAuthors(reader)); + } + } + } + } + } + + private String parseAuthors(XMLStreamReader reader) throws XMLStreamException { + StringBuilder authors = new StringBuilder(); + while (reader.hasNext()) { + reader.next(); + if (isStartElement(reader, "author")) { + authors.append(reader.getElementText()); + authors.append(" and "); + } else if (isEndElement(reader) && reader.getName().getLocalPart().equals("authors")) { + break; + } + } + if (authors.length() > 0) { + authors.delete(authors.length() - 5, authors.length()); // Remove trailing " and " + } + return authors.toString(); + } + + private void parseTitles(XMLStreamReader reader, Map fields) throws XMLStreamException { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "titles")) { + break; + } + + if (isStartElement(reader)) { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "title" -> { + fields.put(StandardField.TITLE, reader.getElementText()); + } + case "secondary-title" -> { + fields.put(StandardField.JOURNAL, reader.getElementText()); + } + } + } + } + } + + private void parseKeywords(XMLStreamReader reader, KeywordList keywordList) throws XMLStreamException { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "keywords")) { + break; + } + + if (isStartElement(reader, "keyword")) { + keywordList.add(reader.getElementText()); + } + } + } + + private void parseUrls(XMLStreamReader reader, Map fields, List linkedFiles) throws XMLStreamException { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "urls")) { + break; + } + + if (isStartElement(reader)) { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "web-urls" -> { + fields.put(StandardField.URL, reader.getElementText()); + } + case "pdf-urls" -> { + String urlText = reader.getElementText(); + try { + linkedFiles.add(new LinkedFile(new URL(urlText), "PDF")); + } catch (MalformedURLException e) { + LOGGER.info("Unable to parse URL: {}", urlText); + } } } } @@ -229,8 +314,7 @@ private boolean isEndElement(XMLStreamReader reader) { @Override public List parseEntries(InputStream inputStream) throws ParseException { try { - return importDatabase( - new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); + return importDatabase(new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); } catch (IOException e) { LOGGER.error(e.getLocalizedMessage(), e); } From 125e8a9070fa2e778d8e427b0eae72662bf386b9 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 15 Apr 2024 08:19:49 +0530 Subject: [PATCH 36/78] Exporter and Importer - final --- .../logic/exporter/EndnoteXmlExporter.java | 63 ++-- .../fileformat/EndnoteXmlImporter.java | 279 ++++++++++++------ 2 files changed, 220 insertions(+), 122 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 3e1dec62f84..5c6e31d52af 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -56,28 +56,25 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardField.PAGES, "pages"), Map.entry(StandardField.VOLUME, "volume"), Map.entry(StandardField.KEYWORDS, "keywords"), - // Map.entry(StandardField.YEAR, "year"), - // Map.entry(StandardField.MONTH, "pub-dates"), Map.entry(StandardField.PUBLISHER, "publisher"), Map.entry(StandardField.ISBN, "isbn"), Map.entry(StandardField.DOI, "electronic-resource-num"), Map.entry(StandardField.ABSTRACT, "abstract"), Map.entry(StandardField.URL, "web-urls"), Map.entry(StandardField.FILE, "pdf-urls"), - Map.entry(StandardField.JOURNAL, "full-title"), Map.entry(StandardField.JOURNALTITLE, "full-title"), Map.entry(StandardField.BOOKTITLE, "secondary-title"), Map.entry(StandardField.EDITION, "edition"), Map.entry(StandardField.SERIES, "tertiary-title"), Map.entry(StandardField.NUMBER, "number"), Map.entry(StandardField.ISSUE, "issue"), - Map.entry(StandardField.ADDRESS, "pub-location"), + Map.entry(StandardField.LOCATION, "pub-location"), Map.entry(StandardField.CHAPTER, "section"), Map.entry(StandardField.HOWPUBLISHED, "work-type"), - Map.entry(StandardField.INSTITUTION, "publisher"), - Map.entry(StandardField.ORGANIZATION, "publisher"), - Map.entry(StandardField.SCHOOL, "publisher"), - Map.entry(StandardField.ISSN, "isbn") + Map.entry(StandardField.PUBLISHER, "publisher"), + Map.entry(StandardField.ISSN, "issn"), + Map.entry(StandardField.ADDRESS, "auth-address"), + Map.entry(StandardField.PAGETOTAL, "page-total") ); public EndnoteXmlExporter() { @@ -140,6 +137,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List // Map contributors (authors and editors) Element contributorsElement = document.createElement("contributors"); + entry.getField(StandardField.AUTHOR).ifPresent(authors -> { Element authorsElement = document.createElement("authors"); String[] authorArray = authors.split("\\s+and\\s+"); @@ -153,7 +151,12 @@ public void export(BibDatabaseContext databaseContext, Path file, List entry.getField(StandardField.EDITOR).ifPresent(editors -> { Element secondaryAuthorsElement = document.createElement("secondary-authors"); - secondaryAuthorsElement.setTextContent(editors); + String[] editorArray = editors.split("\\s+and\\s+"); + for (String editor : editorArray) { + Element editorElement = document.createElement("author"); + editorElement.setTextContent(editor); + secondaryAuthorsElement.appendChild(editorElement); + } contributorsElement.appendChild(secondaryAuthorsElement); }); @@ -200,22 +203,6 @@ public void export(BibDatabaseContext databaseContext, Path file, List recordElement.appendChild(keywordsElement); }); - // Map other fields - for (Map.Entry fieldMapping : FIELD_MAPPING_LIST) { - Field field = fieldMapping.getKey(); - String xmlElement = fieldMapping.getValue(); - - if (field != StandardField.AUTHOR && field != StandardField.EDITOR && - field != StandardField.TITLE && field != StandardField.JOURNAL && - field != StandardField.JOURNALTITLE && field != StandardField.KEYWORDS && field != StandardField.YEAR && field != StandardField.DATE) { - entry.getField(field).ifPresent(value -> { - Element fieldElement = document.createElement(xmlElement); - fieldElement.setTextContent(value); - recordElement.appendChild(fieldElement); - }); - } - } - // Map dates Element datesElement = document.createElement("dates"); entry.getField(StandardField.YEAR).ifPresent(year -> { @@ -223,6 +210,16 @@ public void export(BibDatabaseContext databaseContext, Path file, List yearElement.setTextContent(year); datesElement.appendChild(yearElement); }); + entry.getField(StandardField.MONTH).ifPresent(month -> { + Element yearElement = document.createElement("month"); + yearElement.setTextContent(month); + datesElement.appendChild(yearElement); + }); + entry.getField(StandardField.DAY).ifPresent(day -> { + Element yearElement = document.createElement("day"); + yearElement.setTextContent(day); + datesElement.appendChild(yearElement); + }); entry.getField(StandardField.DATE).ifPresent(date -> { Element pubDatesElement = document.createElement("pub-dates"); Element dateElement = document.createElement("date"); @@ -255,6 +252,22 @@ public void export(BibDatabaseContext databaseContext, Path file, List if (urlsElement.hasChildNodes()) { recordElement.appendChild(urlsElement); } + + // Map other fields + for (Map.Entry fieldMapping : FIELD_MAPPING_LIST) { + Field field = fieldMapping.getKey(); + String xmlElement = fieldMapping.getValue(); + + if (field != StandardField.AUTHOR && field != StandardField.EDITOR && + field != StandardField.TITLE && field != StandardField.JOURNAL && + field != StandardField.JOURNALTITLE && field != StandardField.KEYWORDS && field != StandardField.YEAR && field != StandardField.MONTH && field != StandardField.DAY && field != StandardField.DATE && field != StandardField.FILE && field != StandardField.URL) { + entry.getField(field).ifPresent(value -> { + Element fieldElement = document.createElement(xmlElement); + fieldElement.setTextContent(value); + recordElement.appendChild(fieldElement); + }); + } + } } TransformerFactory transformerFactory = TransformerFactory.newInstance(); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 257425819b8..51af27e55e6 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -4,13 +4,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -26,11 +24,8 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.KeywordList; -import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; -import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -41,48 +36,50 @@ public class EndnoteXmlImporter extends Importer implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(EndnoteXmlImporter.class); - private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( - Map.entry("Journal Article", StandardEntryType.Article), - Map.entry("Book", StandardEntryType.Book), - Map.entry("Book Section", StandardEntryType.InBook), - Map.entry("Conference Proceedings", StandardEntryType.Proceedings), - Map.entry("Thesis", StandardEntryType.Thesis), - Map.entry("Report", StandardEntryType.Report), - Map.entry("Manuscript", StandardEntryType.Unpublished), - Map.entry("Conference Paper", StandardEntryType.InProceedings), - Map.entry("Conference", StandardEntryType.Conference), - Map.entry("Patent", IEEETranEntryType.Patent), - Map.entry("Web Page", StandardEntryType.Online), - Map.entry("Electronic Article", IEEETranEntryType.Electronic), - Map.entry("Generic", StandardEntryType.Misc) + private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( + Map.entry(StandardEntryType.Article, "Journal Article"), + Map.entry(StandardEntryType.Book, "Book"), + Map.entry(StandardEntryType.InBook, "Book Section"), + Map.entry(StandardEntryType.InCollection, "Book Section"), + Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), + Map.entry(StandardEntryType.MastersThesis, "Thesis"), + Map.entry(StandardEntryType.PhdThesis, "Thesis"), + Map.entry(StandardEntryType.TechReport, "Report"), + Map.entry(StandardEntryType.Unpublished, "Manuscript"), + Map.entry(StandardEntryType.InProceedings, "Conference Paper"), + Map.entry(StandardEntryType.Conference, "Conference"), + Map.entry(IEEETranEntryType.Patent, "Patent"), + Map.entry(StandardEntryType.Online, "Web Page"), + Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), + Map.entry(StandardEntryType.Misc, "Generic") ); - private static final Map FIELD_MAPPING = Map.ofEntries( - Map.entry("title", StandardField.TITLE), - Map.entry("authors", StandardField.AUTHOR), - Map.entry("secondary-authors", StandardField.EDITOR), - Map.entry("pages", StandardField.PAGES), - Map.entry("volume", StandardField.VOLUME), - Map.entry("keywords", StandardField.KEYWORDS), - Map.entry("year", StandardField.YEAR), - Map.entry("pub-dates", StandardField.DATE), - Map.entry("publisher", StandardField.PUBLISHER), - Map.entry("isbn", StandardField.ISBN), - Map.entry("electronic-resource-num", StandardField.DOI), - Map.entry("abstract", StandardField.ABSTRACT), - Map.entry("web-urls", StandardField.URL), - Map.entry("pdf-urls", StandardField.FILE), - Map.entry("full-title", StandardField.JOURNAL), - Map.entry("secondary-title", StandardField.BOOKTITLE), - Map.entry("edition", StandardField.EDITION), - Map.entry("tertiary-title", StandardField.SERIES), - Map.entry("number", StandardField.NUMBER), - Map.entry("issue", StandardField.ISSUE), - Map.entry("pub-location", StandardField.ADDRESS), - Map.entry("section", StandardField.CHAPTER), - Map.entry("work-type", StandardField.HOWPUBLISHED) + private static final Map FIELD_MAPPING = Map.ofEntries( + Map.entry(StandardField.TITLE, "title"), + Map.entry(StandardField.AUTHOR, "authors"), + Map.entry(StandardField.EDITOR, "secondary-authors"), + Map.entry(StandardField.JOURNALTITLE, "full-title"), + Map.entry(StandardField.BOOKTITLE, "secondary-title"), + Map.entry(StandardField.EDITION, "edition"), + Map.entry(StandardField.SERIES, "tertiary-title"), + Map.entry(StandardField.VOLUME, "volume"), + Map.entry(StandardField.NUMBER, "number"), + Map.entry(StandardField.ISSUE, "issue"), + Map.entry(StandardField.PAGES, "pages"), + Map.entry(StandardField.LOCATION, "pub-location"), + Map.entry(StandardField.CHAPTER, "section"), + Map.entry(StandardField.HOWPUBLISHED, "work-type"), + Map.entry(StandardField.PUBLISHER, "publisher"), + Map.entry(StandardField.ISBN, "isbn"), + Map.entry(StandardField.ISSN, "issn"), + Map.entry(StandardField.DOI, "electronic-resource-num"), + Map.entry(StandardField.URL, "web-urls"), + Map.entry(StandardField.FILE, "pdf-urls"), + Map.entry(StandardField.ABSTRACT, "abstract"), + Map.entry(StandardField.KEYWORDS, "keywords"), + Map.entry(StandardField.ADDRESS, "auth-address"), + Map.entry(StandardField.PAGETOTAL, "page-total") ); - private final ImportFormatPreferences preferences; private final XMLInputFactory xmlInputFactory; @@ -113,11 +110,13 @@ public String getDescription() { @Override public boolean isRecognizedFormat(BufferedReader reader) throws IOException { - String line; - while ((line = reader.readLine()) != null) { - if (line.trim().startsWith("") && line.trim().contains("")) { + String str; + int i = 0; + while (((str = reader.readLine()) != null) && (i < 50)) { + if (str.toLowerCase(Locale.ENGLISH).contains("")) { return true; } + i++; } return false; } @@ -139,7 +138,7 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { } } } catch (XMLStreamException e) { - LOGGER.debug("Could not parse document", e); + LOGGER.debug("could not parse document", e); return ParserResult.fromError(e); } return new ParserResult(bibItems); @@ -147,9 +146,6 @@ public ParserResult importDatabase(BufferedReader input) throws IOException { private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { BibEntry entry = new BibEntry(); - Map fields = new HashMap<>(); - KeywordList keywordList = new KeywordList(); - List linkedFiles = new ArrayList<>(); while (reader.hasNext()) { reader.next(); @@ -162,42 +158,50 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { switch (elementName) { case "ref-type" -> { String refType = reader.getAttributeValue(null, "name"); - EntryType entryType = ENTRY_TYPE_MAPPING.get(refType); - if (entryType != null) { - entry.setType(entryType); - } + EntryType entryType = ENTRY_TYPE_MAPPING.entrySet().stream() + .filter(e -> e.getValue().equals(refType)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(StandardEntryType.Misc); + entry.setType(entryType); } case "contributors" -> { - parseContributors(reader, fields); + parseContributors(reader, entry); } case "titles" -> { - parseTitles(reader, fields); + parseTitles(reader, entry); + } + case "periodical" -> { + parsePeriodical(reader, entry); } case "keywords" -> { - parseKeywords(reader, keywordList); + parseKeywords(reader, entry); } case "urls" -> { - parseUrls(reader, fields, linkedFiles); + parseUrls(reader, entry); + } + case "dates" -> { + parseDates(reader, entry); } default -> { - Field field = FIELD_MAPPING.get(elementName); + Field field = FIELD_MAPPING.entrySet().stream() + .filter(e -> e.getValue().equals(elementName)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); if (field != null) { - fields.put(field, reader.getElementText()); - } else { - fields.put(new UnknownField(elementName), reader.getElementText()); + entry.setField(field, reader.getElementText()); } } } } } - entry.setField(fields); - entry.putKeywords(keywordList, preferences.bibEntryPreferences().getKeywordSeparator()); - entry.setFiles(linkedFiles); return entry; } - private void parseContributors(XMLStreamReader reader, Map fields) throws XMLStreamException { + private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { + StringBuilder authors = new StringBuilder(); while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "contributors")) { @@ -208,55 +212,83 @@ private void parseContributors(XMLStreamReader reader, Map fields String elementName = reader.getName().getLocalPart(); switch (elementName) { case "authors" -> { - fields.put(StandardField.AUTHOR, parseAuthors(reader)); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "authors")) { + break; + } + if (isStartElement(reader, "author")) { + String author = reader.getElementText(); + if (!authors.isEmpty()) { + authors.append(" and "); + } + authors.append(author); + } + } + entry.setField(StandardField.AUTHOR, authors.toString()); } case "secondary-authors" -> { - fields.put(StandardField.EDITOR, parseAuthors(reader)); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "secondary-authors")) { + break; + } + if (isStartElement(reader, "author")) { + String editor = reader.getElementText(); + if (!authors.isEmpty()) { + authors.append(" and "); + } + authors.append(editor); + } + } + entry.setField(StandardField.EDITOR, authors.toString()); } } } } } - private String parseAuthors(XMLStreamReader reader) throws XMLStreamException { - StringBuilder authors = new StringBuilder(); + private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { while (reader.hasNext()) { reader.next(); - if (isStartElement(reader, "author")) { - authors.append(reader.getElementText()); - authors.append(" and "); - } else if (isEndElement(reader) && reader.getName().getLocalPart().equals("authors")) { + if (isEndElement(reader, "titles")) { break; } + + if (isStartElement(reader)) { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "title" -> { + entry.setField(StandardField.TITLE, reader.getElementText()); + } + case "secondary-title" -> { + entry.setField(StandardField.JOURNAL, reader.getElementText()); + } + } + } } - if (authors.length() > 0) { - authors.delete(authors.length() - 5, authors.length()); // Remove trailing " and " - } - return authors.toString(); } - private void parseTitles(XMLStreamReader reader, Map fields) throws XMLStreamException { + private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { while (reader.hasNext()) { reader.next(); - if (isEndElement(reader, "titles")) { + if (isEndElement(reader, "periodical")) { break; } if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "title" -> { - fields.put(StandardField.TITLE, reader.getElementText()); - } - case "secondary-title" -> { - fields.put(StandardField.JOURNAL, reader.getElementText()); + case "full-title" -> { + entry.setField(StandardField.JOURNALTITLE, reader.getElementText()); } } } } } - private void parseKeywords(XMLStreamReader reader, KeywordList keywordList) throws XMLStreamException { + private void parseKeywords(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { + StringBuilder keywords = new StringBuilder(); while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "keywords")) { @@ -264,12 +296,17 @@ private void parseKeywords(XMLStreamReader reader, KeywordList keywordList) thro } if (isStartElement(reader, "keyword")) { - keywordList.add(reader.getElementText()); + String keyword = reader.getElementText(); + if (keywords.length() > 0) { + keywords.append(", "); + } + keywords.append(keyword); } } + entry.setField(StandardField.KEYWORDS, keywords.toString()); } - private void parseUrls(XMLStreamReader reader, Map fields, List linkedFiles) throws XMLStreamException { + private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "urls")) { @@ -280,14 +317,25 @@ private void parseUrls(XMLStreamReader reader, Map fields, List { - fields.put(StandardField.URL, reader.getElementText()); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "web-urls")) { + break; + } + if (isStartElement(reader, "url")) { + entry.setField(StandardField.URL, reader.getElementText()); + } + } } case "pdf-urls" -> { - String urlText = reader.getElementText(); - try { - linkedFiles.add(new LinkedFile(new URL(urlText), "PDF")); - } catch (MalformedURLException e) { - LOGGER.info("Unable to parse URL: {}", urlText); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "pdf-urls")) { + break; + } + if (isStartElement(reader, "url")) { + entry.setField(StandardField.FILE, reader.getElementText()); + } } } } @@ -295,6 +343,42 @@ private void parseUrls(XMLStreamReader reader, Map fields, List { + entry.setField(StandardField.YEAR, reader.getElementText()); + } + case "month" -> { + entry.setField(StandardField.MONTH, reader.getElementText()); + } + case "day" -> { + entry.setField(StandardField.DAY, reader.getElementText()); + } + case "pub-dates" -> { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "pub-dates")) { + break; + } + if (isStartElement(reader, "date")) { + String date = reader.getElementText(); + entry.setField(StandardField.DATE, date); + } + } + } + } + } + } + } + private boolean isStartElement(XMLStreamReader reader, String elementName) { return isStartElement(reader) && reader.getName().getLocalPart().equals(elementName); } @@ -314,7 +398,8 @@ private boolean isEndElement(XMLStreamReader reader) { @Override public List parseEntries(InputStream inputStream) throws ParseException { try { - return importDatabase(new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); + return importDatabase( + new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); } catch (IOException e) { LOGGER.error(e.getLocalizedMessage(), e); } From 4ffe0e7b8125ea235c7e2e3c33ca704a113c6040 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 16 Apr 2024 23:01:35 +0530 Subject: [PATCH 37/78] Parse style children content (Fixes Importer tests) --- .../logic/exporter/EndnoteXmlExporter.java | 7 +- .../fileformat/EndnoteXmlImporter.java | 151 +++++++----- .../all/EndnoteXmlImporterTestArticle.xml | 131 ++++++++++ .../all/EndnoteXmlImporterTestArticle2.xml | 184 ++++++++++++++ ...dnoteXmlImporterTestLabelAndMultiTitle.xml | 227 ++++++++++++++++++ .../all/EndnoteXmlImporterTestReport.xml | 41 ++++ ...dnoteXmlImporterTest_EmptyKeywordStyle.xml | 84 +++++++ ...EndnoteXmlImporterTest_WithoutUrlStyle.xml | 129 ++++++++++ ...ndnoteXmlImporterTest_WithoutUrlStyle2.xml | 184 ++++++++++++++ 9 files changed, 1080 insertions(+), 58 deletions(-) create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml create mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 5c6e31d52af..24aebc4a1c0 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -71,10 +71,13 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardField.LOCATION, "pub-location"), Map.entry(StandardField.CHAPTER, "section"), Map.entry(StandardField.HOWPUBLISHED, "work-type"), - Map.entry(StandardField.PUBLISHER, "publisher"), Map.entry(StandardField.ISSN, "issn"), Map.entry(StandardField.ADDRESS, "auth-address"), - Map.entry(StandardField.PAGETOTAL, "page-total") + Map.entry(StandardField.PAGETOTAL, "page-total"), + Map.entry(StandardField.NOTE, "notes"), + Map.entry(StandardField.LABEL, "label"), + Map.entry(StandardField.LANGUAGE, "language"), + Map.entry(StandardField.KEY, "foreign-keys") ); public EndnoteXmlExporter() { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 51af27e55e6..4483dc7bd11 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -24,6 +24,7 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.KeywordList; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryType; @@ -77,8 +78,12 @@ public class EndnoteXmlImporter extends Importer implements Parser { Map.entry(StandardField.FILE, "pdf-urls"), Map.entry(StandardField.ABSTRACT, "abstract"), Map.entry(StandardField.KEYWORDS, "keywords"), - Map.entry(StandardField.ADDRESS, "auth-address"), - Map.entry(StandardField.PAGETOTAL, "page-total") + Map.entry(StandardField.PAGETOTAL, "page-total"), + Map.entry(StandardField.NOTE, "notes"), + Map.entry(StandardField.LABEL, "label"), + Map.entry(StandardField.LANGUAGE, "language"), + Map.entry(StandardField.KEY, "foreign-keys"), + Map.entry(StandardField.ADDRESS, "auth-address") ); private final ImportFormatPreferences preferences; private final XMLInputFactory xmlInputFactory; @@ -164,24 +169,37 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { .findFirst() .orElse(StandardEntryType.Misc); entry.setType(entryType); + System.out.println("Successful ENTRYTYPE SET"); } case "contributors" -> { + System.out.println("CONTRIBS ENTERED"); parseContributors(reader, entry); + System.out.println("Successful CONTRIBS SET"); } case "titles" -> { parseTitles(reader, entry); + System.out.println("Successful TITLES SET"); } case "periodical" -> { parsePeriodical(reader, entry); + System.out.println("Successful PERIODICAL SET"); } case "keywords" -> { parseKeywords(reader, entry); + System.out.println("Successful KEYW SET"); } case "urls" -> { parseUrls(reader, entry); + System.out.println("Successful URLS SET"); } case "dates" -> { parseDates(reader, entry); + System.out.println("Successful DATES SET"); + } + case "accession-num" -> { + StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); + entry.setField(StandardField.NUMBER, accessionNumber.toString()); + System.out.println("Successful ACCESSION SET"); } default -> { Field field = FIELD_MAPPING.entrySet().stream() @@ -190,7 +208,9 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { .findFirst() .orElse(null); if (field != null) { - entry.setField(field, reader.getElementText()); + StringBuilder value = parseElementContent(reader, elementName); + entry.setField(field, value.toString()); + System.out.println("SETTING" + field); } } } @@ -202,48 +222,50 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { StringBuilder authors = new StringBuilder(); + StringBuilder editors = new StringBuilder(); + while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "contributors")) { break; } - if (isStartElement(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "authors" -> { - while (reader.hasNext()) { - reader.next(); - if (isEndElement(reader, "authors")) { - break; - } - if (isStartElement(reader, "author")) { - String author = reader.getElementText(); - if (!authors.isEmpty()) { - authors.append(" and "); - } - authors.append(author); + if (isStartElement(reader, "authors")) { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "authors")) { + break; + } + if (isStartElement(reader, "author")) { + StringBuilder author = parseElementContent(reader, "author"); + if (!author.isEmpty()) { + if (!authors.isEmpty()) { + authors.append(" and "); } + authors.append(author); } - entry.setField(StandardField.AUTHOR, authors.toString()); } - case "secondary-authors" -> { - while (reader.hasNext()) { - reader.next(); - if (isEndElement(reader, "secondary-authors")) { - break; - } - if (isStartElement(reader, "author")) { - String editor = reader.getElementText(); - if (!authors.isEmpty()) { - authors.append(" and "); - } - authors.append(editor); + } + entry.setField(StandardField.AUTHOR, authors.toString()); + } + + if (isStartElement(reader, "secondary-authors")) { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "secondary-authors")) { + break; + } + if (isStartElement(reader, "author")) { + StringBuilder editor = parseElementContent(reader, "author"); + if (!editor.isEmpty()) { + if (!editors.isEmpty()) { + editors.append(" and "); } + editors.append(editor); } - entry.setField(StandardField.EDITOR, authors.toString()); } } + entry.setField(StandardField.EDITOR, editors.toString()); } } } @@ -258,11 +280,13 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "title" -> { - entry.setField(StandardField.TITLE, reader.getElementText()); + case "title", "alt-title" -> { + StringBuilder title = parseElementContent(reader, elementName); + entry.setField(StandardField.TITLE, title.toString()); } case "secondary-title" -> { - entry.setField(StandardField.JOURNAL, reader.getElementText()); + StringBuilder secondaryTitle = parseElementContent(reader, "secondary-title"); + entry.setField(StandardField.JOURNAL, secondaryTitle.toString()); } } } @@ -279,8 +303,9 @@ private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLS if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "full-title" -> { - entry.setField(StandardField.JOURNALTITLE, reader.getElementText()); + case "full-title", "abbr-2", "abbr-1", "abbr-3" -> { + StringBuilder journalTitle = parseElementContent(reader, elementName); + entry.setField(StandardField.JOURNALTITLE, journalTitle.toString()); } } } @@ -288,7 +313,7 @@ private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLS } private void parseKeywords(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { - StringBuilder keywords = new StringBuilder(); + KeywordList keywordList = new KeywordList(); while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "keywords")) { @@ -296,14 +321,15 @@ private void parseKeywords(XMLStreamReader reader, BibEntry entry) throws XMLStr } if (isStartElement(reader, "keyword")) { - String keyword = reader.getElementText(); - if (keywords.length() > 0) { - keywords.append(", "); + StringBuilder keyword = parseElementContent(reader, "keyword"); + if (!keyword.isEmpty()) { + keywordList.add(keyword.toString()); } - keywords.append(keyword); } } - entry.setField(StandardField.KEYWORDS, keywords.toString()); + if (!keywordList.isEmpty()) { + entry.putKeywords(keywordList, preferences.bibEntryPreferences().getKeywordSeparator()); + } } private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { @@ -323,7 +349,8 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - entry.setField(StandardField.URL, reader.getElementText()); + StringBuilder url = parseElementContent(reader, "url"); + entry.setField(StandardField.URL, url.toString()); } } } @@ -334,7 +361,8 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - entry.setField(StandardField.FILE, reader.getElementText()); + StringBuilder file = parseElementContent(reader, "url"); + entry.setField(StandardField.FILE, file.toString()); } } } @@ -353,14 +381,9 @@ private void parseDates(XMLStreamReader reader, BibEntry entry) throws XMLStream if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "year" -> { - entry.setField(StandardField.YEAR, reader.getElementText()); - } - case "month" -> { - entry.setField(StandardField.MONTH, reader.getElementText()); - } - case "day" -> { - entry.setField(StandardField.DAY, reader.getElementText()); + case "year", "month", "day" -> { + StringBuilder date = parseElementContent(reader, elementName); + entry.setField(StandardField.valueOf(elementName.toUpperCase()), date.toString()); } case "pub-dates" -> { while (reader.hasNext()) { @@ -369,15 +392,31 @@ private void parseDates(XMLStreamReader reader, BibEntry entry) throws XMLStream break; } if (isStartElement(reader, "date")) { - String date = reader.getElementText(); - entry.setField(StandardField.DATE, date); - } + StringBuilder pubDate = parseElementContent(reader, "date"); + entry.setField(StandardField.DATE, pubDate.toString()); } } } } } } + } + + private StringBuilder parseElementContent(XMLStreamReader reader, String elementName) throws XMLStreamException { + StringBuilder content = new StringBuilder(); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, elementName)) { + break; + } + if (isStartElement(reader, "style")) { + content = new StringBuilder(reader.getElementText()); + } else if (reader.getEventType() == XMLEvent.CHARACTERS) { + content.append(reader.getText().trim()); + } + } + return content; + } private boolean isStartElement(XMLStreamReader reader, String elementName) { return isStartElement(reader) && reader.getName().getLocalPart().equals(elementName); diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml new file mode 100644 index 00000000000..c3a8bb5de98 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml @@ -0,0 +1,131 @@ + + + + + Library1.bdb + Bookends + 2954 + 17 + + + + + + + + + + + + + + + + + + + <style face="normal" size="100%">Trends in the lifetime risk of developing cancer in Great Britain: + comparison of risk for those born from 1930 to 1960 + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml new file mode 100644 index 00000000000..e2ff36845c1 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml @@ -0,0 +1,184 @@ + + + + + EndNote + Ecology.enl + + EndNote + 13264 + + 13264 + + 17 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">An ecological basis for reforestation of + submariginal lands in the Central Hardwood Region + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EndNote + Ecology.enl + + EndNote + 13265 + + 13265 + + 6 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml new file mode 100644 index 00000000000..130a7e155b0 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml @@ -0,0 +1,227 @@ + + + + + EndNote + Ecology.enl + EndNote + 13264 + + 13264 + + 17 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">An ecological basis for reforestation of submariginal lands in the Central Hardwood Region</style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EndNote + Ecology.enl + EndNote + 13265 + + 13265 + + 6 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area</style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test.enl + EndNote + 650 + + 650 + + 17 + + + + + + + + + + + + + + + + <style face="normal" font="default" size="100%">A demographic study of the south polar skua</style> + <style face="italic" font="default" size="100%"> Catharacta maccormicki</style> + <style face="normal" font="default" size="100%"> at Cape Crozier</style> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml new file mode 100644 index 00000000000..e677dc14a6a --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml @@ -0,0 +1,41 @@ + + + + + birdsurvival-Converted.enl + EndNote + 1289 + + 1289 + + 27 + + + + + + + + + + <style face="normal" font="default" size="100%">Purple Martin (Progne subis): a technical conservation assessment</style> + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml new file mode 100644 index 00000000000..6ad699ba51b --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml @@ -0,0 +1,84 @@ + + + + + LASER Acu.1281 mapping conv .bdb + Bookends + 55549 + 17 + + + + + + + + + + + + + <style face="normal" size="100%">Painless Laser Acupuncture for Smoking Cessation.</style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml new file mode 100644 index 00000000000..768ba5af391 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml @@ -0,0 +1,129 @@ + + + + + Library1.bdb + Bookends + 2954 + 17 + + + + + + + + + + + + + + + + + + + <style face="normal" size="100%">Trends in the lifetime risk of developing cancer in Great Britain: + comparison of risk for those born from 1930 to 1960 + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf + + + + + + + + + + + + + + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml new file mode 100644 index 00000000000..1050edd3f0f --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml @@ -0,0 +1,184 @@ + + + + + EndNote + Ecology.enl + + EndNote + 13264 + + 13264 + + 17 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">An ecological basis for reforestation of + submariginal lands in the Central Hardwood Region + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <Go to ISI>://000200148800007 + + + + + + + + + EndNote + Ecology.enl + + EndNote + 13265 + + 13265 + + 6 + + + + + + + + + + + + + <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area + </style> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <Go to ISI>://000200148800014 + + + + + + + + + From 39603a7e070c2bdb9190964357135b00f9ae2969 Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 16 Apr 2024 23:02:44 +0530 Subject: [PATCH 38/78] Remove grouped temporary test files --- .../all/EndnoteXmlImporterTestArticle.xml | 131 ---------- .../all/EndnoteXmlImporterTestArticle2.xml | 184 -------------- ...dnoteXmlImporterTestLabelAndMultiTitle.xml | 227 ------------------ .../all/EndnoteXmlImporterTestReport.xml | 41 ---- ...dnoteXmlImporterTest_EmptyKeywordStyle.xml | 84 ------- ...EndnoteXmlImporterTest_WithoutUrlStyle.xml | 129 ---------- ...ndnoteXmlImporterTest_WithoutUrlStyle2.xml | 184 -------------- 7 files changed, 980 deletions(-) delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml delete mode 100644 src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml deleted file mode 100644 index c3a8bb5de98..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - Library1.bdb - Bookends - 2954 - 17 - - - - - - - - - - - - - - - - - - - <style face="normal" size="100%">Trends in the lifetime risk of developing cancer in Great Britain: - comparison of risk for those born from 1930 to 1960 - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml deleted file mode 100644 index e2ff36845c1..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestArticle2.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - EndNote - Ecology.enl - - EndNote - 13264 - - 13264 - - 17 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">An ecological basis for reforestation of - submariginal lands in the Central Hardwood Region - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EndNote - Ecology.enl - - EndNote - 13265 - - 13265 - - 6 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml deleted file mode 100644 index 130a7e155b0..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestLabelAndMultiTitle.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - - - EndNote - Ecology.enl - EndNote - 13264 - - 13264 - - 17 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">An ecological basis for reforestation of submariginal lands in the Central Hardwood Region</style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EndNote - Ecology.enl - EndNote - 13265 - - 13265 - - 6 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area</style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - test.enl - EndNote - 650 - - 650 - - 17 - - - - - - - - - - - - - - - - <style face="normal" font="default" size="100%">A demographic study of the south polar skua</style> - <style face="italic" font="default" size="100%"> Catharacta maccormicki</style> - <style face="normal" font="default" size="100%"> at Cape Crozier</style> - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml deleted file mode 100644 index e677dc14a6a..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTestReport.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - birdsurvival-Converted.enl - EndNote - 1289 - - 1289 - - 27 - - - - - - - - - - <style face="normal" font="default" size="100%">Purple Martin (Progne subis): a technical conservation assessment</style> - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml deleted file mode 100644 index 6ad699ba51b..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_EmptyKeywordStyle.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - LASER Acu.1281 mapping conv .bdb - Bookends - 55549 - 17 - - - - - - - - - - - - - <style face="normal" size="100%">Painless Laser Acupuncture for Smoking Cessation.</style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml deleted file mode 100644 index 768ba5af391..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Library1.bdb - Bookends - 2954 - 17 - - - - - - - - - - - - - - - - - - - <style face="normal" size="100%">Trends in the lifetime risk of developing cancer in Great Britain: - comparison of risk for those born from 1930 to 1960 - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf - - - - - - - - - - - - - - - diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml deleted file mode 100644 index 1050edd3f0f..00000000000 --- a/src/test/resources/org/jabref/logic/importer/fileformat/all/EndnoteXmlImporterTest_WithoutUrlStyle2.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - EndNote - Ecology.enl - - EndNote - 13264 - - 13264 - - 17 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">An ecological basis for reforestation of - submariginal lands in the Central Hardwood Region - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <Go to ISI>://000200148800007 - - - - - - - - - EndNote - Ecology.enl - - EndNote - 13265 - - 13265 - - 6 - - - - - - - - - - - - - <style face="normal" font="default" size="100%">A survey of soil temperatures in the Chicago area - </style> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <Go to ISI>://000200148800014 - - - - - - - - - From 6f152b1e19c642e7a5ae06ab86e2cc70daa183ae Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 16 Apr 2024 23:06:59 +0530 Subject: [PATCH 39/78] Removed debug printlns --- .../logic/importer/fileformat/EndnoteXmlImporter.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 4483dc7bd11..8fa8ac6fb5f 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -169,37 +169,28 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { .findFirst() .orElse(StandardEntryType.Misc); entry.setType(entryType); - System.out.println("Successful ENTRYTYPE SET"); } case "contributors" -> { - System.out.println("CONTRIBS ENTERED"); parseContributors(reader, entry); - System.out.println("Successful CONTRIBS SET"); } case "titles" -> { parseTitles(reader, entry); - System.out.println("Successful TITLES SET"); } case "periodical" -> { parsePeriodical(reader, entry); - System.out.println("Successful PERIODICAL SET"); } case "keywords" -> { parseKeywords(reader, entry); - System.out.println("Successful KEYW SET"); } case "urls" -> { parseUrls(reader, entry); - System.out.println("Successful URLS SET"); } case "dates" -> { parseDates(reader, entry); - System.out.println("Successful DATES SET"); } case "accession-num" -> { StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); entry.setField(StandardField.NUMBER, accessionNumber.toString()); - System.out.println("Successful ACCESSION SET"); } default -> { Field field = FIELD_MAPPING.entrySet().stream() @@ -210,7 +201,6 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { if (field != null) { StringBuilder value = parseElementContent(reader, elementName); entry.setField(field, value.toString()); - System.out.println("SETTING" + field); } } } From d26978d6f91b7de402e2e95548854251481ee63c Mon Sep 17 00:00:00 2001 From: subhramit Date: Tue, 16 Apr 2024 23:21:26 +0530 Subject: [PATCH 40/78] Fix exporter tests --- .../EndnoteXmlExportTestMultipleEntries.xml | 58 ++++++++++++++----- .../EndnoteXmlExportTestSingleBookEntry.xml | 26 +++++++-- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml index 220cc68db8d..8998539bfb9 100644 --- a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml @@ -3,33 +3,61 @@ 11 + MyLibrary + JabRef - Dai, H. K. + + Dai, H. K. + - Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence - 12 - Association for Computing Machinery - New York, NY, USA + + Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence + + + Web-site traversal pattern + episode-rule mining + first local maximization + + + 2018 + 12 + 130--136 - 10.1145/3287921.3287982 - SoICT '18 + Association for Computing Machinery 9781450365390 - Proceedings of the 9th International Symposium on Information and Communication Technology + 10.1145/3287921.3287982 An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets. - 2018 - Web-site traversal pattern, episode-rule mining, first local maximization + Proceedings of the 9th International Symposium on Information and Communication Technology + SoICT '18 + New York, NY, USA 2 + MyLibrary + JabRef - Bhattacharyya, R. and McCormick, M. E. + + Bhattacharyya, R. + McCormick, M. E. + - Wave Energy Conversion + + Wave Energy Conversion + + + waves + agua + + + 2013 + + + + /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf + + Elsevier Science - /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf 9780080442129 - 2013 - waves, agua diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml index b0504678184..7a22b58b1ed 100644 --- a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.xml @@ -3,15 +3,31 @@ 2 + MyLibrary + JabRef - Bhattacharyya, R. and McCormick, M. E. + + Bhattacharyya, R. + McCormick, M. E. + - Wave Energy Conversion + + Wave Energy Conversion + + + waves + agua + + + 2013 + + + + /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf + + Elsevier Science - /home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf 9780080442129 - 2013 - waves, agua From 5dbd152a0c495a1b5ffd7304a8f0ba3a1519558e Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 00:04:47 +0530 Subject: [PATCH 41/78] Rename test file --- ...terTestFiles.java => EndnoteXmlExporterFilesTest.java} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename src/test/java/org/jabref/logic/exporter/{EndnoteXmlExporterTestFiles.java => EndnoteXmlExporterFilesTest.java} (94%) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java similarity index 94% rename from src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java rename to src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java index 7b544d4637b..5bf7589e9b5 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTestFiles.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java @@ -29,7 +29,7 @@ import static org.mockito.Mockito.when; import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; -public class EndnoteXmlExporterTestFiles { +public class EndnoteXmlExporterFilesTest { private Exporter exporter; private BibDatabaseContext databaseContext; @@ -56,7 +56,7 @@ public void setUp(@TempDir Path testFolder) throws Exception { static Stream fileNames() throws IOException, URISyntaxException { // we have to point it to one existing file, otherwise it will return the default class path - Path resourceDir = Path.of(EndnoteXmlExporterTestFiles.class.getResource("EndnoteXmlExportTestSingleBookEntry.bib").toURI()).getParent(); + Path resourceDir = Path.of(EndnoteXmlExporterFilesTest.class.getResource("EndnoteXmlExportTestSingleBookEntry.bib").toURI()).getParent(); try (Stream stream = Files.list(resourceDir)) { return stream.map(n -> n.getFileName().toString()) .filter(n -> n.endsWith(".bib")) @@ -69,7 +69,7 @@ static Stream fileNames() throws IOException, URISyntaxException { @ParameterizedTest @MethodSource("fileNames") public final void performExport(String filename) throws Exception { - importFile = Path.of(EndnoteXmlExporterTestFiles.class.getResource(filename).toURI()); + importFile = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); String xmlFileName = filename.replace(".bib", ".xml"); List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); Path expectedFile = Path.of(ModsExportFormatFilesTest.class.getResource(xmlFileName).toURI()); @@ -91,7 +91,7 @@ public final void performExport(String filename) throws Exception { @ParameterizedTest @MethodSource("fileNames") public final void exportAsEndnoteAndThenImportAsEndnote(String filename) throws Exception { - importFile = Path.of(EndnoteXmlExporterTestFiles.class.getResource(filename).toURI()); + importFile = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); exporter.export(databaseContext, exportedFile, entries); From d7b9cc6283ae489064ed60c376714c09343b8065 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 00:32:31 +0530 Subject: [PATCH 42/78] Fix parsing of 'related-urls' --- .../importer/fileformat/EndnoteXmlImporter.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 8fa8ac6fb5f..4106af67f12 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -356,6 +356,18 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } } } + case "related-urls" -> { + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, "related-urls")) { + break; + } + if (isStartElement(reader, "url")) { + StringBuilder file = parseElementContent(reader, "url"); + entry.setField(StandardField.URL, file.toString()); + } + } + } } } } From 5447845f729c948d71a1064088993fa803ebf0f3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 01:10:58 +0530 Subject: [PATCH 43/78] Remove citation keys from exporter test bib --- .../logic/exporter/EndnoteXmlExportTestMultipleEntries.bib | 4 ++-- .../logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib index 6c8150f6262..963813f43e6 100644 --- a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.bib @@ -1,6 +1,6 @@ % Encoding: UTF-8 -@conference{Dai2018, +@conference{, abstract = {An episode rule of associating two episodes represents a temporal implication of the antecedent episode to the consequent episode. Episode-rule mining is a task of extracting useful patterns/episodes from large event databases. We present an episode-rule mining algorithm for finding frequent and confident serial-episode rules via first local-maximum confidence in yielding ideal window widths, if exist, in event sequences based on minimal occurrences constrained by a constant maximum gap. Results from our preliminary empirical study confirm the applicability of the episode-rule mining algorithm for Web-site traversal-pattern discovery, and show that the first local maximization yielding ideal window widths exists in real data but rarely in synthetic random data sets.}, address = {New York, NY, USA}, author = {Dai, H. K.}, @@ -16,7 +16,7 @@ @conference{Dai2018 year = {2018}, } -@book{Bhattacharyya2013, +@book{, editor = {Bhattacharyya, R. and McCormick, M. E.}, file = {/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf}, isbn = {9780080442129}, diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib index d9198c49d37..374c04c234e 100644 --- a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestSingleBookEntry.bib @@ -1,6 +1,6 @@ % Encoding: UTF-8 -@book{Bhattacharyya2013, +@book{, editor = {Bhattacharyya, R. and McCormick, M. E.}, file = {/home/mfg/acad/ext/arts/waves/water/[R._Bhattacharyya_and_M.E._McCormick_(Eds.)]_Wave_(z-lib.org).pdf}, isbn = {9780080442129}, From f8b671d675200e1fdcab5da736a0c502165ac44f Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 01:30:54 +0530 Subject: [PATCH 44/78] Fix newlines in 'notes' field of importer test files --- .../importer/fileformat/EndnoteXmlImporterTestArticle.xml | 3 +-- .../importer/fileformat/EndnoteXmlImporterTestArticle2.xml | 6 ++---- .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.xml | 3 +-- .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.xml | 6 ++---- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.xml index c3a8bb5de98..6f70289a154 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.xml +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.xml @@ -100,8 +100,7 @@ - + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.xml index e2ff36845c1..56a7936e07f 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.xml +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.xml @@ -77,8 +77,7 @@ - + @@ -166,8 +165,7 @@ - + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.xml b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.xml index 768ba5af391..e2cccc24a8e 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.xml +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.xml @@ -100,8 +100,7 @@ - + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.xml b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.xml index 1050edd3f0f..4dd31030ab1 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.xml +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.xml @@ -77,8 +77,7 @@ - + @@ -166,8 +165,7 @@ - + From 9b361794ea0240af22f010da79d766e2d814fffe Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 03:13:40 +0530 Subject: [PATCH 45/78] Fix Title and Number overwrite --- .../importer/fileformat/EndnoteXmlImporter.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 4106af67f12..1e0b20fd1db 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -188,10 +188,10 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "dates" -> { parseDates(reader, entry); } - case "accession-num" -> { - StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); - entry.setField(StandardField.NUMBER, accessionNumber.toString()); - } +// case "accession-num" -> { +// StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); +// entry.setField(StandardField.NUMBER, accessionNumber.toString()); +// } default -> { Field field = FIELD_MAPPING.entrySet().stream() .filter(e -> e.getValue().equals(elementName)) @@ -270,8 +270,8 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea if (isStartElement(reader)) { String elementName = reader.getName().getLocalPart(); switch (elementName) { - case "title", "alt-title" -> { - StringBuilder title = parseElementContent(reader, elementName); + case "title" -> { + StringBuilder title = parseElementContent(reader, "title"); entry.setField(StandardField.TITLE, title.toString()); } case "secondary-title" -> { From aa7edcfddbd67981d4bd70c12d82849ca4348c5d Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 03:18:50 +0530 Subject: [PATCH 46/78] Fix overwrite of title and number without losing info --- .../jabref/logic/exporter/EndnoteXmlExporter.java | 4 +++- .../importer/fileformat/EndnoteXmlImporter.java | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 24aebc4a1c0..69595bf7583 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -19,6 +19,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -77,7 +78,8 @@ public class EndnoteXmlExporter extends Exporter { Map.entry(StandardField.NOTE, "notes"), Map.entry(StandardField.LABEL, "label"), Map.entry(StandardField.LANGUAGE, "language"), - Map.entry(StandardField.KEY, "foreign-keys") + Map.entry(StandardField.KEY, "foreign-keys"), + Map.entry(new UnknownField("accession-num"), "accession-num") ); public EndnoteXmlExporter() { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 1e0b20fd1db..67b815b9d99 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -27,6 +27,7 @@ import org.jabref.model.entry.KeywordList; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -188,10 +189,10 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "dates" -> { parseDates(reader, entry); } -// case "accession-num" -> { -// StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); -// entry.setField(StandardField.NUMBER, accessionNumber.toString()); -// } + case "accession-num" -> { + StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); + entry.setField(new UnknownField("accession-num"), accessionNumber.toString()); + } default -> { Field field = FIELD_MAPPING.entrySet().stream() .filter(e -> e.getValue().equals(elementName)) @@ -278,6 +279,10 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea StringBuilder secondaryTitle = parseElementContent(reader, "secondary-title"); entry.setField(StandardField.JOURNAL, secondaryTitle.toString()); } + case "alt-title" -> { + StringBuilder title = parseElementContent(reader, "alt-title"); + entry.setField(new UnknownField("alt-title"), title.toString()); + } } } } From 8e1e7dd14c84f37cc8f00aef2e5ca00d27c71d93 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 04:48:44 +0530 Subject: [PATCH 47/78] Fix handling of multi-part titles & unclean titles --- .../fileformat/EndnoteXmlImporter.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 67b815b9d99..1fda99fc637 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -272,16 +272,16 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea String elementName = reader.getName().getLocalPart(); switch (elementName) { case "title" -> { - StringBuilder title = parseElementContent(reader, "title"); - entry.setField(StandardField.TITLE, title.toString()); + String title = parseElementContent(reader, "title").toString().trim().replaceAll("\\s+", " "); + entry.setField(StandardField.TITLE, title); } case "secondary-title" -> { - StringBuilder secondaryTitle = parseElementContent(reader, "secondary-title"); - entry.setField(StandardField.JOURNAL, secondaryTitle.toString()); + String secondaryTitle = parseElementContent(reader, "secondary-title").toString().trim().replaceAll("\\s+", " "); + entry.setField(StandardField.JOURNAL, secondaryTitle); } case "alt-title" -> { - StringBuilder title = parseElementContent(reader, "alt-title"); - entry.setField(new UnknownField("alt-title"), title.toString()); + String altTitle = parseElementContent(reader, "alt-title").toString().trim().replaceAll("\\s+", " "); + entry.setField(new UnknownField("alt-title"), altTitle); } } } @@ -345,7 +345,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } if (isStartElement(reader, "url")) { StringBuilder url = parseElementContent(reader, "url"); - entry.setField(StandardField.URL, url.toString()); + entry.setField(StandardField.URL, clean(url.toString())); } } } @@ -357,7 +357,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } if (isStartElement(reader, "url")) { StringBuilder file = parseElementContent(reader, "url"); - entry.setField(StandardField.FILE, file.toString()); + entry.setField(StandardField.FILE, clean(file.toString())); } } } @@ -369,7 +369,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } if (isStartElement(reader, "url")) { StringBuilder file = parseElementContent(reader, "url"); - entry.setField(StandardField.URL, file.toString()); + entry.setField(StandardField.URL, clean(file.toString())); } } } @@ -417,12 +417,16 @@ private StringBuilder parseElementContent(XMLStreamReader reader, String element break; } if (isStartElement(reader, "style")) { - content = new StringBuilder(reader.getElementText()); + content.append(reader.getElementText()).append(" "); } else if (reader.getEventType() == XMLEvent.CHARACTERS) { - content.append(reader.getText().trim()); + content.append(reader.getText()); } } - return content; + return new StringBuilder(content.toString().trim().replaceAll("\\s+", " ")); + } + + private String clean(String input) { + return input.trim().replaceAll(" +", " "); } private boolean isStartElement(XMLStreamReader reader, String elementName) { From 51961f421393111e1d556549028a5e96252c21d3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 05:02:25 +0530 Subject: [PATCH 48/78] Ad PDF suffix --- .../importer/fileformat/EndnoteXmlImporter.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 1fda99fc637..dd373f3167a 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -344,8 +344,8 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - StringBuilder url = parseElementContent(reader, "url"); - entry.setField(StandardField.URL, clean(url.toString())); + String url = parseElementContent(reader, "url").toString().trim(); + entry.setField(StandardField.URL, url); } } } @@ -356,8 +356,8 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - StringBuilder file = parseElementContent(reader, "url"); - entry.setField(StandardField.FILE, clean(file.toString())); + String file = parseElementContent(reader, "url").toString().trim(); + entry.setField(StandardField.FILE, ":" + file + ":PDF"); } } } @@ -368,8 +368,8 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - StringBuilder file = parseElementContent(reader, "url"); - entry.setField(StandardField.URL, clean(file.toString())); + String url = parseElementContent(reader, "url").toString().trim(); + entry.setField(StandardField.URL, url); } } } @@ -422,7 +422,7 @@ private StringBuilder parseElementContent(XMLStreamReader reader, String element content.append(reader.getText()); } } - return new StringBuilder(content.toString().trim().replaceAll("\\s+", " ")); + return new StringBuilder(content.toString().trim().replaceAll("\\s+", " ").trim()); } private String clean(String input) { From 69f7f303447dbe4bc1e2a431973db7f8ddd9094a Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 06:03:23 +0530 Subject: [PATCH 49/78] Fix Importer tests --- .../fileformat/EndnoteXmlImporter.java | 21 +++--- .../EndnoteXmlImporterTestArticle.bib | 30 +++++---- .../EndnoteXmlImporterTestArticle2.bib | 40 ++++++------ ...dnoteXmlImporterTestLabelAndMultiTitle.bib | 64 +++++++++++-------- .../EndnoteXmlImporterTestReport.bib | 1 - ...dnoteXmlImporterTest_EmptyKeywordStyle.bib | 27 ++++---- ...EndnoteXmlImporterTest_WithoutUrlStyle.bib | 30 +++++---- ...ndnoteXmlImporterTest_WithoutUrlStyle2.bib | 50 +++++++++------ 8 files changed, 141 insertions(+), 122 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index dd373f3167a..650c3345b23 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -27,7 +27,6 @@ import org.jabref.model.entry.KeywordList; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; -import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -81,9 +80,9 @@ public class EndnoteXmlImporter extends Importer implements Parser { Map.entry(StandardField.KEYWORDS, "keywords"), Map.entry(StandardField.PAGETOTAL, "page-total"), Map.entry(StandardField.NOTE, "notes"), - Map.entry(StandardField.LABEL, "label"), + // Map.entry(StandardField.LABEL, "label"), Map.entry(StandardField.LANGUAGE, "language"), - Map.entry(StandardField.KEY, "foreign-keys"), + // Map.entry(StandardField.KEY, "foreign-keys"), Map.entry(StandardField.ADDRESS, "auth-address") ); private final ImportFormatPreferences preferences; @@ -189,10 +188,10 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "dates" -> { parseDates(reader, entry); } - case "accession-num" -> { - StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); - entry.setField(new UnknownField("accession-num"), accessionNumber.toString()); - } +// case "accession-num" -> { +// StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); +// entry.setField(new UnknownField("accession-num"), accessionNumber.toString()); +// } default -> { Field field = FIELD_MAPPING.entrySet().stream() .filter(e -> e.getValue().equals(elementName)) @@ -279,10 +278,10 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea String secondaryTitle = parseElementContent(reader, "secondary-title").toString().trim().replaceAll("\\s+", " "); entry.setField(StandardField.JOURNAL, secondaryTitle); } - case "alt-title" -> { - String altTitle = parseElementContent(reader, "alt-title").toString().trim().replaceAll("\\s+", " "); - entry.setField(new UnknownField("alt-title"), altTitle); - } +// case "alt-title" -> { +// String altTitle = parseElementContent(reader, "alt-title").toString().trim().replaceAll("\\s+", " "); +// entry.setField(new UnknownField("alt-title"), altTitle); +// } } } } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib index f93199db1af..396dfcc32aa 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib @@ -1,16 +1,18 @@ @article{, - abstract = {test abstract}, - author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, - doi = {10.1038/bjc.2014.606}, - file = {:file\://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, - isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, - keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, - number = {5}, - pages = {943-7}, - title = {Trends in the lifetime risk of developing cancer in Great Britain: comparison of risk for those born from 1930 to 1960}, - volume = {112}, - year = {2015}, - journal = {Br J Cancer}, - note = {some notes}, - url = {http://www.ncbi.nlm.nih.gov/pubmed/25647015}, + abstract = {test abstract}, + address = {Queen Mary University of London, Centre for Cancer Prevention, Wolfson Institute of Preventive Medicine, Charterhouse Square, London EC1M 6BQ, UK. Cancer Research UK, Head of Statistical Information, Angel Building, 407 St John Street, London EC1V 4AD, UK.}, + author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, + date = {Mar 3}, + doi = {10.1038/bjc.2014.606}, + file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, + isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, + journal = {Br J Cancer}, + keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, + note = {some notes}, + number = {5}, + pages = {943-7}, + title = {Trends in the lifetime risk of developing cancer in Great Britain: comparison of risk for those born from 1930 to 1960}, + url = {http://www.ncbi.nlm.nih.gov/pubmed/25647015}, + volume = {112}, + year = {2015} } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index a7293b79f14..cb748662496 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -1,24 +1,24 @@ @article{, - author = {Chapman, A. G.}, - isbn = {0012-9658}, - number = {1}, - pages = {93-105}, - title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, - volume = {18}, - year = {1937}, - journal = {Ecology}, - note = {some notes}, - url = {://000200148800007} + author = {Chapman, A. G.}, + isbn = {0012-9658}, + journal = {Ecology}, + note = {some notes}, + number = {1}, + pages = {93-105}, + title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, + url = {://000200148800007}, + volume = {18}, + year = {1937} } @book{, - author = {Strohecker, H. F.}, - isbn = {0012-9658}, - number = {1}, - journal = {Ecology}, - note = {some other notes}, - pages = {162-168}, - title = {A survey of soil temperatures in the Chicago area}, - volume = {18}, - url = {://000200148800014}, - year = {1937} + author = {Strohecker, H. F.}, + isbn = {0012-9658}, + journal = {Ecology}, + note = {some other notes}, + number = {1}, + pages = {162-168}, + title = {A survey of soil temperatures in the Chicago area}, + url = {://000200148800014}, + volume = {18}, + year = {1937} } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index d07d2d77638..f92c737f0c2 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -1,33 +1,41 @@ @article{, - author = {Chapman, A. G.}, - isbn = {0012-9658}, - number = {1}, - pages = {93-105}, - title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, - volume = {18}, - year = {1937}, - journal = {Ecology}, - note = {some notes}, - url = {://000200148800007} + address = {Cent States Forest Expt Stn, Columbus, OH USA}, + author = {Chapman, A. G.}, + date = {Jan}, + isbn = {0012-9658}, + journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, + note = {some notes}, + number = {1}, + pages = {93-105}, + title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, + url = {://000200148800007}, + volume = {18}, + year = {1937} } @book{, - author = {Strohecker, H. F.}, - isbn = {0012-9658}, - number = {1}, - journal = {Ecology}, - note = {some other notes}, - pages = {162-168}, - title = {A survey of soil temperatures in the Chicago area}, - volume = {18}, - url = {://000200148800014}, - year = {1937}, + address = {Univ Chicago, Chicago, IL USA}, + author = {Strohecker, H. F.}, + date = {Jan}, + isbn = {0012-9658}, + journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, + note = {some other notes}, + number = {1}, + pages = {162-168}, + title = {A survey of soil temperatures in the Chicago area}, + url = {://000200148800014}, + volume = {18}, + year = {1937} } @article{, - author = {Ainley, D.G. and Ribic, C.A. and Wodd, R.C.}, - endnote-label = {B4}, - journal = {Journal of Animal Ecology}, - pages = {1-20}, - title = {A demographic study of the south polar skua Catharacta maccormicki at Cape Crozier}, - volume = {59}, - year = {1990}, -} + author = {Ainley, D.G. and Ribic, C.A. and Wodd, R.C.}, + journal = {Journal of Animal Ecology}, + journaltitle = {Journal of Animal Ecology}, + pages = {1-20}, + title = {A demographic study of the south polar skua Catharacta maccormicki at Cape Crozier}, + volume = {59}, + year = {1990} +} \ No newline at end of file diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib index f8e46826c01..39270f26c5d 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib @@ -1,6 +1,5 @@ @report{, author = {Wiggins, D. A.}, - endnote-label = {B1040}, pages = {Available: http://www.fs.fed.us/r2/projects/scp/assessments/purplemartin.pdf}, publisher = {USDA Forest Service, Rocky Mountain Region}, title = {Purple Martin (Progne subis): a technical conservation assessment}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_EmptyKeywordStyle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_EmptyKeywordStyle.bib index 8f3f4d58339..d88e8fd9422 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_EmptyKeywordStyle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_EmptyKeywordStyle.bib @@ -1,17 +1,18 @@ % Encoding: UTF-8 @Article{, - author = {Lim, RCH}, - title = {Painless Laser Acupuncture for Smoking Cessation.}, - doi = {10.1089/acu.2018.1295}, - endnote-label = {29937971}, - note = {FFT available, not read on 7/2/18}, - number = {3}, - pages = {159-162}, - url = {https://www.ncbi.nlm.nih.gov/pubmed/29937971}, - volume = {30}, - isbn = {1933-6586}, - journal = {Med Acupunct}, - keywords = {anxiety; craving; dependency; destress; health restoration}, - year = {2018}, + address = {Laser Acupuncture Centre, Singapore.}, + author = {Lim, RCH}, + date = {Jun 01}, + doi = {10.1089/acu.2018.1295}, + isbn = {1933-6586}, + journal = {Med Acupunct}, + keywords = {anxiety; craving; dependency; destress; health restoration}, + note = {FFT available, not read on 7/2/18}, + number = {3}, + pages = {159-162}, + title = {Painless Laser Acupuncture for Smoking Cessation.}, + url = {https://www.ncbi.nlm.nih.gov/pubmed/29937971}, + volume = {30}, + year = {2018}, } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib index f93199db1af..396dfcc32aa 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib @@ -1,16 +1,18 @@ @article{, - abstract = {test abstract}, - author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, - doi = {10.1038/bjc.2014.606}, - file = {:file\://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, - isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, - keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, - number = {5}, - pages = {943-7}, - title = {Trends in the lifetime risk of developing cancer in Great Britain: comparison of risk for those born from 1930 to 1960}, - volume = {112}, - year = {2015}, - journal = {Br J Cancer}, - note = {some notes}, - url = {http://www.ncbi.nlm.nih.gov/pubmed/25647015}, + abstract = {test abstract}, + address = {Queen Mary University of London, Centre for Cancer Prevention, Wolfson Institute of Preventive Medicine, Charterhouse Square, London EC1M 6BQ, UK. Cancer Research UK, Head of Statistical Information, Angel Building, 407 St John Street, London EC1V 4AD, UK.}, + author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, + date = {Mar 3}, + doi = {10.1038/bjc.2014.606}, + file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, + isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, + journal = {Br J Cancer}, + keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, + note = {some notes}, + number = {5}, + pages = {943-7}, + title = {Trends in the lifetime risk of developing cancer in Great Britain: comparison of risk for those born from 1930 to 1960}, + url = {http://www.ncbi.nlm.nih.gov/pubmed/25647015}, + volume = {112}, + year = {2015} } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index a7293b79f14..316175e1382 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -1,24 +1,32 @@ @article{, - author = {Chapman, A. G.}, - isbn = {0012-9658}, - number = {1}, - pages = {93-105}, - title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, - volume = {18}, - year = {1937}, - journal = {Ecology}, - note = {some notes}, - url = {://000200148800007} + address = {Cent States Forest Expt Stn, Columbus, OH USA}, + author = {Chapman, A. G.}, + date = {Jan}, + isbn = {0012-9658}, + journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, + note = {some notes}, + number = {1}, + pages = {93-105}, + title = {An ecological basis for reforestation of submariginal lands in the Central Hardwood Region}, + url = {://000200148800007}, + volume = {18}, + year = {1937} } @book{, - author = {Strohecker, H. F.}, - isbn = {0012-9658}, - number = {1}, - journal = {Ecology}, - note = {some other notes}, - pages = {162-168}, - title = {A survey of soil temperatures in the Chicago area}, - volume = {18}, - url = {://000200148800014}, - year = {1937} -} + address = {Univ Chicago, Chicago, IL USA}, + author = {Strohecker, H. F.}, + date = {Jan}, + isbn = {0012-9658}, + journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, + note = {some other notes}, + number = {1}, + pages = {162-168}, + title = {A survey of soil temperatures in the Chicago area}, + url = {://000200148800014}, + volume = {18}, + year = {1937} +} \ No newline at end of file From 1eff5b9d0f104c25f8dd22a4532a70836ca5ada3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 06:15:17 +0530 Subject: [PATCH 50/78] Fix Importer tests-2 --- .../fileformat/EndnoteXmlImporterTestArticle2.bib | 8 ++++++++ .../importer/fileformat/EndnoteXmlImporterTestReport.bib | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index cb748662496..190f5f078ae 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -1,7 +1,11 @@ @article{, + address = {Cent States Forest Expt Stn, Columbus, OH USA}, author = {Chapman, A. G.}, + date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, note = {some notes}, number = {1}, pages = {93-105}, @@ -11,9 +15,13 @@ @article{ year = {1937} } @book{, + address = {Univ Chicago, Chicago, IL USA}, author = {Strohecker, H. F.}, + date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, + journaltitle = {Ecology}, + language = {English}, note = {some other notes}, number = {1}, pages = {162-168}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib index 39270f26c5d..aebaaae8bba 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestReport.bib @@ -1,4 +1,4 @@ -@report{, +@techreport{, author = {Wiggins, D. A.}, pages = {Available: http://www.fs.fed.us/r2/projects/scp/assessments/purplemartin.pdf}, publisher = {USDA Forest Service, Rocky Mountain Region}, From 0b8fec42c64d76e9d3dfb915cebfda634a3c9b97 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 06:25:21 +0530 Subject: [PATCH 51/78] Fix Exporter and Importer tests - trailing :PDF --- .../jabref/logic/importer/fileformat/EndnoteXmlImporter.java | 2 +- .../logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib | 2 +- .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 650c3345b23..cea9265b799 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -356,7 +356,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } if (isStartElement(reader, "url")) { String file = parseElementContent(reader, "url").toString().trim(); - entry.setField(StandardField.FILE, ":" + file + ":PDF"); + entry.setField(StandardField.FILE, ":" + file); } } } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib index 396dfcc32aa..b6047ddeb5a 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib @@ -4,7 +4,7 @@ @article{ author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, date = {Mar 3}, doi = {10.1038/bjc.2014.606}, - file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, + file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, journal = {Br J Cancer}, keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib index 396dfcc32aa..b6047ddeb5a 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib @@ -4,7 +4,7 @@ @article{ author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, date = {Mar 3}, doi = {10.1038/bjc.2014.606}, - file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf:PDF}, + file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, journal = {Br J Cancer}, keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, From bd87bc3d6d51e5f67c9a30db402b418f0e62fbb3 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 06:31:16 +0530 Subject: [PATCH 52/78] Fix Round-trip test: preceeding ':' in pdf files --- .../jabref/logic/importer/fileformat/EndnoteXmlImporter.java | 2 +- .../logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib | 2 +- .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index cea9265b799..a6d0f0bc7a0 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -356,7 +356,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE } if (isStartElement(reader, "url")) { String file = parseElementContent(reader, "url").toString().trim(); - entry.setField(StandardField.FILE, ":" + file); + entry.setField(StandardField.FILE, file); } } } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib index b6047ddeb5a..2a6e553cf7a 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle.bib @@ -4,7 +4,7 @@ @article{ author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, date = {Mar 3}, doi = {10.1038/bjc.2014.606}, - file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, + file = {file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, journal = {Br J Cancer}, keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib index b6047ddeb5a..2a6e553cf7a 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle.bib @@ -4,7 +4,7 @@ @article{ author = {Ahmad, AS and Ormiston-Smith, N and Sasieni, PD}, date = {Mar 3}, doi = {10.1038/bjc.2014.606}, - file = {:file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, + file = {file://localhost/Users/user/Documents/Bookends/Attachments/Ahmad%20et%20al%202015.pdf}, isbn = {1532-1827 (Electronic) 0007-0920 (Linking)}, journal = {Br J Cancer}, keywords = {Age Factors; Aged; Aged, 80 and over; Female; Great Britain/epidemiology; Humans; Male; Middle Aged; Models, Statistical; Neoplasms/*epidemiology; Risk Assessment; Risk Factors; Sex Characteristics}, From cf37b6e6b4cbdd2d4f2a077a39ae8ddad1b74502 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 06:59:36 +0530 Subject: [PATCH 53/78] Fix typo in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b82b2c8f431..852817f0828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added -- We added support for offline extracting refereferences from PDFs following the IEEE format. [#11156](https://github.com/JabRef/jabref/pull/11156) +- We added support for offline extracting references from PDFs following the IEEE format. [#11156](https://github.com/JabRef/jabref/pull/11156) - We added a new keyboard shortcut ctrl + , to open the preferences. [#11154](https://github.com/JabRef/jabref/pull/11154) - We added value selection (such as for month) for content selectors in custom entry types. [#11109](https://github.com/JabRef/jabref/issues/11109) - We added a duplicate checker for the Citation Relations tab. [#10414](https://github.com/JabRef/jabref/issues/10414) From 1732b72c8b69bfa851b5537e9897504bd0338415 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 07:06:06 +0530 Subject: [PATCH 54/78] More relevant changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 852817f0828..4f828216907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added a duplicate checker for the Citation Relations tab. [#10414](https://github.com/JabRef/jabref/issues/10414) - We added tooltip on main table cells that shows cell content or cell content and entry preview if set in preferences. [10925](https://github.com/JabRef/jabref/issues/10925) - We added the ability to add a keyword/crossref when typing the separator character (e.g., comma) in the keywords/crossref fields. [#11178](https://github.com/JabRef/jabref/issues/11178) -- We added an exporter for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) +- We added an exporter and improved the importer for Endnote XML format. [#11137](https://github.com/JabRef/jabref/issues/11137) ### Changed From 74ea7e4a86bf0b14f2274448348d5dbefbf13f68 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 09:07:14 +0200 Subject: [PATCH 55/78] Use HashMap Java data type --- .../logic/exporter/EndnoteXmlExporter.java | 132 +++++++++--------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 69595bf7583..39101a4af36 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -2,6 +2,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -28,59 +29,65 @@ import org.w3c.dom.Element; public class EndnoteXmlExporter extends Exporter { - private static final List> ENTRY_TYPE_MAPPING_LIST = List.of( - Map.entry(StandardEntryType.Article, "Journal Article"), - Map.entry(StandardEntryType.Book, "Book"), - Map.entry(StandardEntryType.InBook, "Book Section"), - Map.entry(StandardEntryType.InCollection, "Book Section"), - Map.entry(StandardEntryType.Proceedings, "Conference Proceedings"), - Map.entry(StandardEntryType.MastersThesis, "Thesis"), - Map.entry(StandardEntryType.PhdThesis, "Thesis"), - Map.entry(StandardEntryType.TechReport, "Report"), - Map.entry(StandardEntryType.Unpublished, "Manuscript"), - Map.entry(StandardEntryType.InProceedings, "Conference Paper"), - Map.entry(StandardEntryType.Conference, "Conference"), - Map.entry(IEEETranEntryType.Patent, "Patent"), - Map.entry(StandardEntryType.Online, "Web Page"), - Map.entry(IEEETranEntryType.Electronic, "Electronic Article"), - Map.entry(StandardEntryType.Misc, "Generic") - ); - - private static final List> EXPORT_REF_NUMBER_LIST = ENTRY_TYPE_MAPPING_LIST.stream() - .map(entry -> Map.entry(entry.getKey(), Integer.toString(ENTRY_TYPE_MAPPING_LIST.indexOf(entry) + 1))) - .toList(); - - private static final List> FIELD_MAPPING_LIST = List.of( - Map.entry(StandardField.TITLE, "title"), - Map.entry(StandardField.AUTHOR, "authors"), - Map.entry(StandardField.EDITOR, "secondary-authors"), - Map.entry(StandardField.PAGES, "pages"), - Map.entry(StandardField.VOLUME, "volume"), - Map.entry(StandardField.KEYWORDS, "keywords"), - Map.entry(StandardField.PUBLISHER, "publisher"), - Map.entry(StandardField.ISBN, "isbn"), - Map.entry(StandardField.DOI, "electronic-resource-num"), - Map.entry(StandardField.ABSTRACT, "abstract"), - Map.entry(StandardField.URL, "web-urls"), - Map.entry(StandardField.FILE, "pdf-urls"), - Map.entry(StandardField.JOURNALTITLE, "full-title"), - Map.entry(StandardField.BOOKTITLE, "secondary-title"), - Map.entry(StandardField.EDITION, "edition"), - Map.entry(StandardField.SERIES, "tertiary-title"), - Map.entry(StandardField.NUMBER, "number"), - Map.entry(StandardField.ISSUE, "issue"), - Map.entry(StandardField.LOCATION, "pub-location"), - Map.entry(StandardField.CHAPTER, "section"), - Map.entry(StandardField.HOWPUBLISHED, "work-type"), - Map.entry(StandardField.ISSN, "issn"), - Map.entry(StandardField.ADDRESS, "auth-address"), - Map.entry(StandardField.PAGETOTAL, "page-total"), - Map.entry(StandardField.NOTE, "notes"), - Map.entry(StandardField.LABEL, "label"), - Map.entry(StandardField.LANGUAGE, "language"), - Map.entry(StandardField.KEY, "foreign-keys"), - Map.entry(new UnknownField("accession-num"), "accession-num") - ); + + private record EndNoteType(String name, Integer number) { + } + + private static final Map ENTRY_TYPE_MAPPING = new HashMap<>(); + + static { + ENTRY_TYPE_MAPPING.put(StandardEntryType.Article, new EndNoteType("Journal Article", 1)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Book, new EndNoteType("Book", 2)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.InBook, new EndNoteType("Book Section", 3)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.InCollection, new EndNoteType("Book Section", 4)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Proceedings, new EndNoteType("Conference Proceedings", 5)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.MastersThesis, new EndNoteType("Thesis", 6)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.PhdThesis, new EndNoteType("Thesis", 7)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.TechReport, new EndNoteType("Report", 8)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Unpublished, new EndNoteType("Manuscript", 9)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.InProceedings, new EndNoteType("Conference Paper", 10)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Conference, new EndNoteType("Conference", 11)); + ENTRY_TYPE_MAPPING.put(IEEETranEntryType.Patent, new EndNoteType("Patent", 12)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Online, new EndNoteType("Web Page", 13)); + ENTRY_TYPE_MAPPING.put(IEEETranEntryType.Electronic, new EndNoteType("Electronic Article", 14)); + ENTRY_TYPE_MAPPING.put(StandardEntryType.Misc, new EndNoteType("Generic", 15)); + } + + private static final Map FIELD_MAPPING = new HashMap<>(); + + static { + FIELD_MAPPING.put(StandardField.TITLE, "title"); + FIELD_MAPPING.put(StandardField.AUTHOR, "authors"); + FIELD_MAPPING.put(StandardField.EDITOR, "secondary-authors"); + FIELD_MAPPING.put(StandardField.PAGES, "pages"); + FIELD_MAPPING.put(StandardField.VOLUME, "volume"); + FIELD_MAPPING.put(StandardField.KEYWORDS, "keywords"); + FIELD_MAPPING.put(StandardField.PUBLISHER, "publisher"); + FIELD_MAPPING.put(StandardField.ISBN, "isbn"); + FIELD_MAPPING.put(StandardField.DOI, "electronic-resource-num"); + FIELD_MAPPING.put(StandardField.ABSTRACT, "abstract"); + FIELD_MAPPING.put(StandardField.URL, "web-urls"); + FIELD_MAPPING.put(StandardField.FILE, "pdf-urls"); + FIELD_MAPPING.put(StandardField.JOURNALTITLE, "full-title"); + FIELD_MAPPING.put(StandardField.BOOKTITLE, "secondary-title"); + FIELD_MAPPING.put(StandardField.EDITION, "edition"); + FIELD_MAPPING.put(StandardField.SERIES, "tertiary-title"); + FIELD_MAPPING.put(StandardField.NUMBER, "number"); + FIELD_MAPPING.put(StandardField.ISSUE, "issue"); + FIELD_MAPPING.put(StandardField.LOCATION, "pub-location"); + FIELD_MAPPING.put(StandardField.CHAPTER, "section"); + FIELD_MAPPING.put(StandardField.HOWPUBLISHED, "work-type"); + FIELD_MAPPING.put(StandardField.ISSN, "issn"); + FIELD_MAPPING.put(StandardField.ADDRESS, "auth-address"); + FIELD_MAPPING.put(StandardField.PAGETOTAL, "page-total"); + FIELD_MAPPING.put(StandardField.NOTE, "notes"); + FIELD_MAPPING.put(StandardField.LABEL, "label"); + FIELD_MAPPING.put(StandardField.LANGUAGE, "language"); + FIELD_MAPPING.put(StandardField.KEY, "foreign-keys"); + FIELD_MAPPING.put(new UnknownField("accession-num"), "accession-num"); + } + + private static final EndNoteType DEFAULT_TYPE = new EndNoteType("Generic", 15); public EndnoteXmlExporter() { super("endnote", "EndNote XML", StandardFileType.XML); @@ -112,21 +119,10 @@ public void export(BibDatabaseContext databaseContext, Path file, List // Map entry type EntryType entryType = entry.getType(); - String refType = ENTRY_TYPE_MAPPING_LIST.stream() - .filter(mapping -> mapping.getKey().equals(entryType)) - .map(Map.Entry::getValue) - .findFirst() - .orElse("Generic"); - - String refNumber = EXPORT_REF_NUMBER_LIST.stream() - .filter(mapping -> mapping.getKey().equals(entryType)) - .map(Map.Entry::getValue) - .findFirst() - .orElse("15"); - + EndNoteType endNoteType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, DEFAULT_TYPE); Element refTypeElement = document.createElement("ref-type"); - refTypeElement.setAttribute("name", refType); - refTypeElement.setTextContent(refNumber); + refTypeElement.setAttribute("name", endNoteType.name()); + refTypeElement.setTextContent(endNoteType.number().toString()); recordElement.appendChild(refTypeElement); // Map database and source-app @@ -259,7 +255,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List } // Map other fields - for (Map.Entry fieldMapping : FIELD_MAPPING_LIST) { + for (Map.Entry fieldMapping : FIELD_MAPPING.entrySet()) { Field field = fieldMapping.getKey(); String xmlElement = fieldMapping.getValue(); From a78ffc45e39b3817242fed354712e2daaebf6708 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 09:46:49 +0200 Subject: [PATCH 56/78] Extract methods --- .../logic/exporter/EndnoteXmlExporter.java | 360 +++++++++--------- 1 file changed, 181 insertions(+), 179 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 39101a4af36..13dbc45ec8c 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -30,6 +30,8 @@ public class EndnoteXmlExporter extends Exporter { + private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + private record EndNoteType(String name, Integer number) { } @@ -53,38 +55,34 @@ private record EndNoteType(String name, Integer number) { ENTRY_TYPE_MAPPING.put(StandardEntryType.Misc, new EndNoteType("Generic", 15)); } - private static final Map FIELD_MAPPING = new HashMap<>(); + // Contains the mapping of all fields not explicitly handled by mapX methods + private static final Map STANDARD_FIELD_MAPPING = new HashMap<>(); static { - FIELD_MAPPING.put(StandardField.TITLE, "title"); - FIELD_MAPPING.put(StandardField.AUTHOR, "authors"); - FIELD_MAPPING.put(StandardField.EDITOR, "secondary-authors"); - FIELD_MAPPING.put(StandardField.PAGES, "pages"); - FIELD_MAPPING.put(StandardField.VOLUME, "volume"); - FIELD_MAPPING.put(StandardField.KEYWORDS, "keywords"); - FIELD_MAPPING.put(StandardField.PUBLISHER, "publisher"); - FIELD_MAPPING.put(StandardField.ISBN, "isbn"); - FIELD_MAPPING.put(StandardField.DOI, "electronic-resource-num"); - FIELD_MAPPING.put(StandardField.ABSTRACT, "abstract"); - FIELD_MAPPING.put(StandardField.URL, "web-urls"); - FIELD_MAPPING.put(StandardField.FILE, "pdf-urls"); - FIELD_MAPPING.put(StandardField.JOURNALTITLE, "full-title"); - FIELD_MAPPING.put(StandardField.BOOKTITLE, "secondary-title"); - FIELD_MAPPING.put(StandardField.EDITION, "edition"); - FIELD_MAPPING.put(StandardField.SERIES, "tertiary-title"); - FIELD_MAPPING.put(StandardField.NUMBER, "number"); - FIELD_MAPPING.put(StandardField.ISSUE, "issue"); - FIELD_MAPPING.put(StandardField.LOCATION, "pub-location"); - FIELD_MAPPING.put(StandardField.CHAPTER, "section"); - FIELD_MAPPING.put(StandardField.HOWPUBLISHED, "work-type"); - FIELD_MAPPING.put(StandardField.ISSN, "issn"); - FIELD_MAPPING.put(StandardField.ADDRESS, "auth-address"); - FIELD_MAPPING.put(StandardField.PAGETOTAL, "page-total"); - FIELD_MAPPING.put(StandardField.NOTE, "notes"); - FIELD_MAPPING.put(StandardField.LABEL, "label"); - FIELD_MAPPING.put(StandardField.LANGUAGE, "language"); - FIELD_MAPPING.put(StandardField.KEY, "foreign-keys"); - FIELD_MAPPING.put(new UnknownField("accession-num"), "accession-num"); + STANDARD_FIELD_MAPPING.put(StandardField.PAGES, "pages"); + STANDARD_FIELD_MAPPING.put(StandardField.VOLUME, "volume"); + STANDARD_FIELD_MAPPING.put(StandardField.PUBLISHER, "publisher"); + STANDARD_FIELD_MAPPING.put(StandardField.ISBN, "isbn"); + STANDARD_FIELD_MAPPING.put(StandardField.DOI, "electronic-resource-num"); + STANDARD_FIELD_MAPPING.put(StandardField.ABSTRACT, "abstract"); + STANDARD_FIELD_MAPPING.put(StandardField.URL, "web-urls"); + STANDARD_FIELD_MAPPING.put(StandardField.FILE, "pdf-urls"); + STANDARD_FIELD_MAPPING.put(StandardField.BOOKTITLE, "secondary-title"); + STANDARD_FIELD_MAPPING.put(StandardField.EDITION, "edition"); + STANDARD_FIELD_MAPPING.put(StandardField.SERIES, "tertiary-title"); + STANDARD_FIELD_MAPPING.put(StandardField.NUMBER, "number"); + STANDARD_FIELD_MAPPING.put(StandardField.ISSUE, "issue"); + STANDARD_FIELD_MAPPING.put(StandardField.LOCATION, "pub-location"); + STANDARD_FIELD_MAPPING.put(StandardField.CHAPTER, "section"); + STANDARD_FIELD_MAPPING.put(StandardField.HOWPUBLISHED, "work-type"); + STANDARD_FIELD_MAPPING.put(StandardField.ISSN, "issn"); + STANDARD_FIELD_MAPPING.put(StandardField.ADDRESS, "auth-address"); + STANDARD_FIELD_MAPPING.put(StandardField.PAGETOTAL, "page-total"); + STANDARD_FIELD_MAPPING.put(StandardField.NOTE, "notes"); + STANDARD_FIELD_MAPPING.put(StandardField.LABEL, "label"); + STANDARD_FIELD_MAPPING.put(StandardField.LANGUAGE, "language"); + STANDARD_FIELD_MAPPING.put(StandardField.KEY, "foreign-keys"); + STANDARD_FIELD_MAPPING.put(new UnknownField("accession-num"), "accession-num"); } private static final EndNoteType DEFAULT_TYPE = new EndNoteType("Generic", 15); @@ -103,8 +101,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List return; } - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + DocumentBuilder dBuilder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder(); Document document = dBuilder.newDocument(); Element rootElement = document.createElement("xml"); @@ -117,157 +114,24 @@ public void export(BibDatabaseContext databaseContext, Path file, List Element recordElement = document.createElement("record"); recordsElement.appendChild(recordElement); - // Map entry type - EntryType entryType = entry.getType(); - EndNoteType endNoteType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, DEFAULT_TYPE); - Element refTypeElement = document.createElement("ref-type"); - refTypeElement.setAttribute("name", endNoteType.name()); - refTypeElement.setTextContent(endNoteType.number().toString()); - recordElement.appendChild(refTypeElement); - - // Map database and source-app - Element databaseElement = document.createElement("database"); - databaseElement.setAttribute("name", "MyLibrary"); - databaseElement.setTextContent("MyLibrary"); - recordElement.appendChild(databaseElement); - - Element sourceAppElement = document.createElement("source-app"); - sourceAppElement.setAttribute("name", "JabRef"); - sourceAppElement.setTextContent("JabRef"); - recordElement.appendChild(sourceAppElement); - - // Map contributors (authors and editors) - Element contributorsElement = document.createElement("contributors"); - - entry.getField(StandardField.AUTHOR).ifPresent(authors -> { - Element authorsElement = document.createElement("authors"); - String[] authorArray = authors.split("\\s+and\\s+"); - for (String author : authorArray) { - Element authorElement = document.createElement("author"); - authorElement.setTextContent(author); - authorsElement.appendChild(authorElement); - } - contributorsElement.appendChild(authorsElement); - }); - - entry.getField(StandardField.EDITOR).ifPresent(editors -> { - Element secondaryAuthorsElement = document.createElement("secondary-authors"); - String[] editorArray = editors.split("\\s+and\\s+"); - for (String editor : editorArray) { - Element editorElement = document.createElement("author"); - editorElement.setTextContent(editor); - secondaryAuthorsElement.appendChild(editorElement); - } - contributorsElement.appendChild(secondaryAuthorsElement); - }); - - if (contributorsElement.hasChildNodes()) { - recordElement.appendChild(contributorsElement); - } - - // Map titles - Element titlesElement = document.createElement("titles"); - entry.getField(StandardField.TITLE).ifPresent(title -> { - Element titleElement = document.createElement("title"); - titleElement.setTextContent(title); - titlesElement.appendChild(titleElement); - }); - - entry.getField(StandardField.JOURNAL).ifPresent(journal -> { - Element secondaryTitleElement = document.createElement("secondary-title"); - secondaryTitleElement.setTextContent(journal); - titlesElement.appendChild(secondaryTitleElement); - }); - - if (titlesElement.hasChildNodes()) { - recordElement.appendChild(titlesElement); - } - - // Map periodical and full-title - entry.getField(StandardField.JOURNALTITLE).ifPresent(journalTitle -> { - Element periodicalElement = document.createElement("periodical"); - Element fullTitleElement = document.createElement("full-title"); - fullTitleElement.setTextContent(journalTitle); - periodicalElement.appendChild(fullTitleElement); - recordElement.appendChild(periodicalElement); - }); - - // Map keywords - entry.getField(StandardField.KEYWORDS).ifPresent(keywords -> { - Element keywordsElement = document.createElement("keywords"); - String[] keywordArray = keywords.split(",\\s*"); - for (String keyword : keywordArray) { - Element keywordElement = document.createElement("keyword"); - keywordElement.setTextContent(keyword); - keywordsElement.appendChild(keywordElement); - } - recordElement.appendChild(keywordsElement); - }); - - // Map dates - Element datesElement = document.createElement("dates"); - entry.getField(StandardField.YEAR).ifPresent(year -> { - Element yearElement = document.createElement("year"); - yearElement.setTextContent(year); - datesElement.appendChild(yearElement); - }); - entry.getField(StandardField.MONTH).ifPresent(month -> { - Element yearElement = document.createElement("month"); - yearElement.setTextContent(month); - datesElement.appendChild(yearElement); - }); - entry.getField(StandardField.DAY).ifPresent(day -> { - Element yearElement = document.createElement("day"); - yearElement.setTextContent(day); - datesElement.appendChild(yearElement); - }); - entry.getField(StandardField.DATE).ifPresent(date -> { - Element pubDatesElement = document.createElement("pub-dates"); - Element dateElement = document.createElement("date"); - dateElement.setTextContent(date); - pubDatesElement.appendChild(dateElement); - datesElement.appendChild(pubDatesElement); - }); - if (datesElement.hasChildNodes()) { - recordElement.appendChild(datesElement); - } - - // Map URLs - Element urlsElement = document.createElement("urls"); - entry.getField(StandardField.FILE).ifPresent(fileField -> { - Element pdfUrlsElement = document.createElement("pdf-urls"); - Element urlElement = document.createElement("url"); - urlElement.setTextContent(fileField); - pdfUrlsElement.appendChild(urlElement); - urlsElement.appendChild(pdfUrlsElement); - }); - - entry.getField(StandardField.URL).ifPresent(url -> { - Element webUrlsElement = document.createElement("web-urls"); - Element urlElement = document.createElement("url"); - urlElement.setTextContent(url); - webUrlsElement.appendChild(urlElement); - urlsElement.appendChild(webUrlsElement); - }); - - if (urlsElement.hasChildNodes()) { - recordElement.appendChild(urlsElement); - } + mapEntryType(entry, document, recordElement); + createMetaInformationElements(databaseContext, document, recordElement); + mapAuthorAndEditor(entry, document, recordElement); + mapTitle(entry, document, recordElement); + mapJournalTitle(entry, document, recordElement); + mapKeywords(entry, document, recordElement); + mapDates(entry, document, recordElement); + mapUrls(entry, document, recordElement); - // Map other fields - for (Map.Entry fieldMapping : FIELD_MAPPING.entrySet()) { + for (Map.Entry fieldMapping : STANDARD_FIELD_MAPPING.entrySet()) { Field field = fieldMapping.getKey(); String xmlElement = fieldMapping.getValue(); - if (field != StandardField.AUTHOR && field != StandardField.EDITOR && - field != StandardField.TITLE && field != StandardField.JOURNAL && - field != StandardField.JOURNALTITLE && field != StandardField.KEYWORDS && field != StandardField.YEAR && field != StandardField.MONTH && field != StandardField.DAY && field != StandardField.DATE && field != StandardField.FILE && field != StandardField.URL) { - entry.getField(field).ifPresent(value -> { - Element fieldElement = document.createElement(xmlElement); - fieldElement.setTextContent(value); - recordElement.appendChild(fieldElement); - }); - } + entry.getField(field).ifPresent(value -> { + Element fieldElement = document.createElement(xmlElement); + fieldElement.setTextContent(value); + recordElement.appendChild(fieldElement); + }); } } @@ -281,4 +145,142 @@ public void export(BibDatabaseContext databaseContext, Path file, List StreamResult result = new StreamResult(file.toFile()); transformer.transform(source, result); } + + private static void mapTitle(BibEntry entry, Document document, Element recordElement) { + entry.getFieldOrAlias(StandardField.TITLE).ifPresent(title -> { + Element titlesElement = document.createElement("titles"); + Element titleElement = document.createElement("title"); + titleElement.setTextContent(title); + titlesElement.appendChild(titleElement); + recordElement.appendChild(titlesElement); + }); + } + + private static void mapJournalTitle(BibEntry entry, Document document, Element recordElement) { + entry.getFieldOrAlias(StandardField.JOURNALTITLE).ifPresent(journalTitle -> { + Element periodicalElement = document.createElement("periodical"); + Element fullTitleElement = document.createElement("full-title"); + fullTitleElement.setTextContent(journalTitle); + periodicalElement.appendChild(fullTitleElement); + recordElement.appendChild(periodicalElement); + }); + } + + private static void mapKeywords(BibEntry entry, Document document, Element recordElement) { + entry.getFieldOrAlias(StandardField.KEYWORDS).ifPresent(keywords -> { + Element keywordsElement = document.createElement("keywords"); + String[] keywordArray = keywords.split(",\\s*"); + for (String keyword : keywordArray) { + Element keywordElement = document.createElement("keyword"); + keywordElement.setTextContent(keyword); + keywordsElement.appendChild(keywordElement); + } + recordElement.appendChild(keywordsElement); + }); + } + + private static void mapUrls(BibEntry entry, Document document, Element recordElement) { + Element urlsElement = document.createElement("urls"); + + entry.getFieldOrAlias(StandardField.FILE).ifPresent(fileField -> { + Element pdfUrlsElement = document.createElement("pdf-urls"); + Element urlElement = document.createElement("url"); + urlElement.setTextContent(fileField); + pdfUrlsElement.appendChild(urlElement); + urlsElement.appendChild(pdfUrlsElement); + }); + + entry.getFieldOrAlias(StandardField.URL).ifPresent(url -> { + Element webUrlsElement = document.createElement("web-urls"); + Element urlElement = document.createElement("url"); + urlElement.setTextContent(url); + webUrlsElement.appendChild(urlElement); + urlsElement.appendChild(webUrlsElement); + }); + + if (urlsElement.hasChildNodes()) { + recordElement.appendChild(urlsElement); + } + } + + private static void mapDates(BibEntry entry, Document document, Element recordElement) { + Element datesElement = document.createElement("dates"); + entry.getFieldOrAlias(StandardField.YEAR).ifPresent(year -> { + Element yearElement = document.createElement("year"); + yearElement.setTextContent(year); + datesElement.appendChild(yearElement); + }); + entry.getFieldOrAlias(StandardField.MONTH).ifPresent(month -> { + Element yearElement = document.createElement("month"); + yearElement.setTextContent(month); + datesElement.appendChild(yearElement); + }); + entry.getFieldOrAlias(StandardField.DAY).ifPresent(day -> { + Element yearElement = document.createElement("day"); + yearElement.setTextContent(day); + datesElement.appendChild(yearElement); + }); + entry.getFieldOrAlias(StandardField.DATE).ifPresent(date -> { + Element pubDatesElement = document.createElement("pub-dates"); + Element dateElement = document.createElement("date"); + dateElement.setTextContent(date); + pubDatesElement.appendChild(dateElement); + datesElement.appendChild(pubDatesElement); + }); + if (datesElement.hasChildNodes()) { + recordElement.appendChild(datesElement); + } + } + + private static void mapEntryType(BibEntry entry, Document document, Element recordElement) { + EntryType entryType = entry.getType(); + EndNoteType endNoteType = ENTRY_TYPE_MAPPING.getOrDefault(entryType, DEFAULT_TYPE); + Element refTypeElement = document.createElement("ref-type"); + refTypeElement.setAttribute("name", endNoteType.name()); + refTypeElement.setTextContent(endNoteType.number().toString()); + recordElement.appendChild(refTypeElement); + } + + private static void createMetaInformationElements(BibDatabaseContext databaseContext, Document document, Element recordElement) { + Element databaseElement = document.createElement("database"); + databaseElement.setAttribute("name", "MyLibrary"); + String name = databaseContext.getDatabasePath().map(Path::getFileName).map(Path::toString).orElse("MyLibrary"); + databaseElement.setTextContent(name); + recordElement.appendChild(databaseElement); + + Element sourceAppElement = document.createElement("source-app"); + sourceAppElement.setAttribute("name", "JabRef"); + sourceAppElement.setTextContent("JabRef"); + recordElement.appendChild(sourceAppElement); + } + + private static void mapAuthorAndEditor(BibEntry entry, Document document, Element recordElement) { + Element contributorsElement = document.createElement("contributors"); + + entry.getField(StandardField.AUTHOR).ifPresent(authors -> { + Element authorsElement = document.createElement("authors"); + String[] authorArray = authors.split("\\s+and\\s+"); + for (String author : authorArray) { + Element authorElement = document.createElement("author"); + authorElement.setTextContent(author); + authorsElement.appendChild(authorElement); + } + contributorsElement.appendChild(authorsElement); + }); + + entry.getField(StandardField.EDITOR).ifPresent(editors -> { + Element secondaryAuthorsElement = document.createElement("secondary-authors"); + String[] editorArray = editors.split("\\s+and\\s+"); + for (String editor : editorArray) { + Element editorElement = document.createElement("author"); + editorElement.setTextContent(editor); + secondaryAuthorsElement.appendChild(editorElement); + } + contributorsElement.appendChild(secondaryAuthorsElement); + }); + + if (contributorsElement.hasChildNodes()) { + recordElement.appendChild(contributorsElement); + } + } } From f596f3da5684879a0a232d6ec8dbd9534d6d9bfd Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 09:51:44 +0200 Subject: [PATCH 57/78] Extract method --- .../jabref/logic/exporter/EndnoteXmlExporter.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 13dbc45ec8c..57fd7a6461b 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -11,6 +11,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; @@ -135,15 +136,19 @@ public void export(BibDatabaseContext databaseContext, Path file, List } } + Transformer transformer = createTransformer(); + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(file.toFile()); + transformer.transform(source, result); + } + + private static Transformer createTransformer() throws TransformerConfigurationException { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - - DOMSource source = new DOMSource(document); - StreamResult result = new StreamResult(file.toFile()); - transformer.transform(source, result); + return transformer; } private static void mapTitle(BibEntry entry, Document document, Element recordElement) { From e0c18af7abb86a4f672c0fd464eb1c12cc1f7de3 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 10:40:24 +0200 Subject: [PATCH 58/78] Restructure test --- .../exporter/EndnoteXmlExporterFilesTest.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java index 5bf7589e9b5..be062ecfa8b 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java @@ -33,8 +33,8 @@ public class EndnoteXmlExporterFilesTest { private Exporter exporter; private BibDatabaseContext databaseContext; - private Path exportedFile; - private Path importFile; + private Path exportFile; + private Path bibFileToExport; private BibtexImporter bibtexImporter; private EndnoteXmlImporter endnoteXmlImporter; @@ -45,13 +45,10 @@ public void setUp(@TempDir Path testFolder) throws Exception { when(importFormatPreferences.bibEntryPreferences().getKeywordSeparator()).thenReturn(','); databaseContext = new BibDatabaseContext(); - exporter = new EndnoteXmlExporter(); + exporter = new EndnoteXmlExporter(new BibEntryPreferences(',')); endnoteXmlImporter = new EndnoteXmlImporter(importFormatPreferences); bibtexImporter = new BibtexImporter(importFormatPreferences, new DummyFileUpdateMonitor()); - - Path path = testFolder.resolve("ARandomlyNamedFile.tmp"); - Files.createFile(path); - exportedFile = path.toAbsolutePath(); + exportFile = testFolder.resolve("exported-endnote.xml").toAbsolutePath(); } static Stream fileNames() throws IOException, URISyntaxException { @@ -69,15 +66,14 @@ static Stream fileNames() throws IOException, URISyntaxException { @ParameterizedTest @MethodSource("fileNames") public final void performExport(String filename) throws Exception { - importFile = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); + bibFileToExport = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); + List entries = bibtexImporter.importDatabase(bibFileToExport).getDatabase().getEntries(); + exporter.export(databaseContext, exportFile, entries); + String actual = String.join("\n", Files.readAllLines(exportFile)); + String xmlFileName = filename.replace(".bib", ".xml"); - List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); Path expectedFile = Path.of(ModsExportFormatFilesTest.class.getResource(xmlFileName).toURI()); - - exporter.export(databaseContext, exportedFile, entries); - String expected = String.join("\n", Files.readAllLines(expectedFile)); - String actual = String.join("\n", Files.readAllLines(exportedFile)); // The order of the XML elements changes // The order does not really matter, so we ignore it. @@ -91,10 +87,10 @@ public final void performExport(String filename) throws Exception { @ParameterizedTest @MethodSource("fileNames") public final void exportAsEndnoteAndThenImportAsEndnote(String filename) throws Exception { - importFile = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); - List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); + bibFileToExport = Path.of(EndnoteXmlExporterFilesTest.class.getResource(filename).toURI()); + List entries = bibtexImporter.importDatabase(bibFileToExport).getDatabase().getEntries(); - exporter.export(databaseContext, exportedFile, entries); - BibEntryAssert.assertEquals(entries, exportedFile, endnoteXmlImporter); + exporter.export(databaseContext, exportFile, entries); + BibEntryAssert.assertEquals(entries, exportFile, endnoteXmlImporter); } } From 375614b09e4e5318b7e9989c02116f8693514df1 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 10:44:20 +0200 Subject: [PATCH 59/78] Use "native" method for keyword list parsing --- .../logic/exporter/EndnoteXmlExporter.java | 22 ++++++++++++------- .../logic/exporter/ExporterFactory.java | 2 +- .../exporter/EndnoteXmlExporterTest.java | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 57fd7a6461b..5c49144cf9d 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -17,6 +17,7 @@ import javax.xml.transform.stream.StreamResult; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.Field; @@ -25,6 +26,7 @@ import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.preferences.BibEntryPreferences; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -88,8 +90,11 @@ private record EndNoteType(String name, Integer number) { private static final EndNoteType DEFAULT_TYPE = new EndNoteType("Generic", 15); - public EndnoteXmlExporter() { + private final BibEntryPreferences bibEntryPreferences; + + public EndnoteXmlExporter(BibEntryPreferences bibEntryPreferences) { super("endnote", "EndNote XML", StandardFileType.XML); + this.bibEntryPreferences = bibEntryPreferences; } @Override @@ -120,7 +125,7 @@ public void export(BibDatabaseContext databaseContext, Path file, List mapAuthorAndEditor(entry, document, recordElement); mapTitle(entry, document, recordElement); mapJournalTitle(entry, document, recordElement); - mapKeywords(entry, document, recordElement); + mapKeywords(databaseContext.getDatabase(), entry, document, recordElement); mapDates(entry, document, recordElement); mapUrls(entry, document, recordElement); @@ -171,15 +176,15 @@ private static void mapJournalTitle(BibEntry entry, Document document, Element r }); } - private static void mapKeywords(BibEntry entry, Document document, Element recordElement) { + private void mapKeywords(BibDatabase bibDatabase, BibEntry entry, Document document, Element recordElement) { entry.getFieldOrAlias(StandardField.KEYWORDS).ifPresent(keywords -> { Element keywordsElement = document.createElement("keywords"); - String[] keywordArray = keywords.split(",\\s*"); - for (String keyword : keywordArray) { + entry.getResolvedKeywords(bibEntryPreferences.getKeywordSeparator(), bibDatabase).forEach(keyword -> { Element keywordElement = document.createElement("keyword"); - keywordElement.setTextContent(keyword); + // Hierarchical keywords are separated by the '>' character. See {@link } for details. + keywordElement.setTextContent(keyword.get().toString()); keywordsElement.appendChild(keywordElement); - } + }); recordElement.appendChild(keywordsElement); }); } @@ -225,7 +230,8 @@ private static void mapDates(BibEntry entry, Document document, Element recordEl yearElement.setTextContent(day); datesElement.appendChild(yearElement); }); - entry.getFieldOrAlias(StandardField.DATE).ifPresent(date -> { + // We need to use getField here - getFieldOrAlias for Date tries to convert year, month, and day to a date, which we do not want + entry.getField(StandardField.DATE).ifPresent(date -> { Element pubDatesElement = document.createElement("pub-dates"); Element dateElement = document.createElement("date"); dateElement.setTextContent(date); diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 8a2be8baef3..786cd33c333 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -63,7 +63,7 @@ public static ExporterFactory create(PreferencesService preferencesService, exporters.add(new XmpPdfExporter(xmpPreferences)); exporters.add(new EmbeddedBibFilePdfExporter(bibDatabaseMode, entryTypesManager, fieldPreferences)); exporters.add(new CffExporter()); - exporters.add(new EndnoteXmlExporter()); + exporters.add(new EndnoteXmlExporter(preferencesService.getBibEntryPreferences())); // Now add custom export formats exporters.addAll(customFormats); diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java index b1af4b09567..383a32e02e1 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterTest.java @@ -28,13 +28,13 @@ public class EndnoteXmlExporterTest { private BibEntry bookEntry; @BeforeEach - public void setUp(@TempDir Path testFolder) throws Exception { + public void setUp() throws Exception { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); when(importFormatPreferences.bibEntryPreferences()).thenReturn(mock(BibEntryPreferences.class)); when(importFormatPreferences.bibEntryPreferences().getKeywordSeparator()).thenReturn(','); databaseContext = new BibDatabaseContext(); - exporter = new EndnoteXmlExporter(); + exporter = new EndnoteXmlExporter(new BibEntryPreferences(',')); bookEntry = new BibEntry(StandardEntryType.Book) .withCitationKey("Bhattacharyya2013") From ab70573f08329dffffe1171415737d297df862d9 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 10:47:53 +0200 Subject: [PATCH 60/78] Fix usage of entry.getAuthorTitleYear --- .../org/jabref/migrations/MergeReviewIntoCommentMigration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java b/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java index e599b463564..f7d86408070 100644 --- a/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java +++ b/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java @@ -55,7 +55,7 @@ private static boolean hasReviewField(BibEntry entry) { private String mergeCommentFieldIfPresent(BibEntry entry, String review) { if (entry.getField(StandardField.COMMENT).isPresent()) { - LOGGER.info("Both Comment and Review fields are present in %s! Merging them into the comment field.".formatted(entry.getAuthorTitleYear(150))); + LOGGER.info("Both Comment and Review fields are present in {}. Merging them into the comment field.", entry.getCitationKey().orElse(entry.getAuthorTitleYear(150))); return "%s\n%s:\n%s".formatted(entry.getField(StandardField.COMMENT).get().trim(), Localization.lang("Review"), review.trim()); } return review; From 61372dfd10ee70e4dd7c9015ad7fc624e4f91f88 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 10:50:28 +0200 Subject: [PATCH 61/78] Add hint to getCitationKey() usage --- src/main/java/org/jabref/model/entry/BibEntry.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index 3e26335a11e..19b33f257fb 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -392,6 +392,9 @@ public BibEntry withCitationKey(String newKey) { return this; } + /** + * If not present, {@link BibEntry#getAuthorTitleYear(int)} can be used + */ public Optional getCitationKey() { String key = fields.get(InternalField.KEY_FIELD); if (StringUtil.isBlank(key)) { From a4df60be465fa5f4f4d8c8e5559aae06392f1eb4 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 10:57:26 +0200 Subject: [PATCH 62/78] Add some helper thing --- src/main/java/org/jabref/model/entry/AuthorList.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/model/entry/AuthorList.java b/src/main/java/org/jabref/model/entry/AuthorList.java index 17b68e02fbe..092d04de61c 100644 --- a/src/main/java/org/jabref/model/entry/AuthorList.java +++ b/src/main/java/org/jabref/model/entry/AuthorList.java @@ -1,6 +1,7 @@ package org.jabref.model.entry; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -117,7 +118,7 @@ * */ @AllowedToUseLogic("because it needs access to AuthorList parser") -public class AuthorList { +public class AuthorList implements Iterable { private static final Map AUTHOR_CACHE = Collections.synchronizedMap(new WeakHashMap<>()); private final List authors; @@ -279,7 +280,7 @@ public Author getAuthor(int i) { } /** - * Returns the a list of Author objects. + * Returns the list of Author objects. * * @return the List<Author> object. */ @@ -484,4 +485,9 @@ public String getForAlphabetization() { .map(Author::getNameForAlphabetization) .collect(Collectors.joining(" and ")); } + + @Override + public Iterator iterator() { + return authors.iterator(); + } } From 9b66b5e88362746c63e11173cbbd20a78f983b09 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 11:27:49 +0200 Subject: [PATCH 63/78] Use author parsing --- .../logic/exporter/EndnoteXmlExporter.java | 61 +++++++++---------- .../exporter/EndnoteXmlExporterFilesTest.java | 2 +- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 5c49144cf9d..849311e1462 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -3,9 +3,11 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.SequencedMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -19,6 +21,8 @@ import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.Author; +import org.jabref.model.entry.AuthorList; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; @@ -59,7 +63,8 @@ private record EndNoteType(String name, Integer number) { } // Contains the mapping of all fields not explicitly handled by mapX methods - private static final Map STANDARD_FIELD_MAPPING = new HashMap<>(); + // We need a fixed order here, so we use a SequencedMap + private static final SequencedMap STANDARD_FIELD_MAPPING = new LinkedHashMap<>(); static { STANDARD_FIELD_MAPPING.put(StandardField.PAGES, "pages"); @@ -68,8 +73,6 @@ private record EndNoteType(String name, Integer number) { STANDARD_FIELD_MAPPING.put(StandardField.ISBN, "isbn"); STANDARD_FIELD_MAPPING.put(StandardField.DOI, "electronic-resource-num"); STANDARD_FIELD_MAPPING.put(StandardField.ABSTRACT, "abstract"); - STANDARD_FIELD_MAPPING.put(StandardField.URL, "web-urls"); - STANDARD_FIELD_MAPPING.put(StandardField.FILE, "pdf-urls"); STANDARD_FIELD_MAPPING.put(StandardField.BOOKTITLE, "secondary-title"); STANDARD_FIELD_MAPPING.put(StandardField.EDITION, "edition"); STANDARD_FIELD_MAPPING.put(StandardField.SERIES, "tertiary-title"); @@ -147,15 +150,6 @@ public void export(BibDatabaseContext databaseContext, Path file, List transformer.transform(source, result); } - private static Transformer createTransformer() throws TransformerConfigurationException { - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - return transformer; - } - private static void mapTitle(BibEntry entry, Document document, Element recordElement) { entry.getFieldOrAlias(StandardField.TITLE).ifPresent(title -> { Element titlesElement = document.createElement("titles"); @@ -167,7 +161,7 @@ private static void mapTitle(BibEntry entry, Document document, Element recordEl } private static void mapJournalTitle(BibEntry entry, Document document, Element recordElement) { - entry.getFieldOrAlias(StandardField.JOURNALTITLE).ifPresent(journalTitle -> { + entry.getFieldOrAlias(StandardField.JOURNAL).ifPresent(journalTitle -> { Element periodicalElement = document.createElement("periodical"); Element fullTitleElement = document.createElement("full-title"); fullTitleElement.setTextContent(journalTitle); @@ -267,31 +261,34 @@ private static void createMetaInformationElements(BibDatabaseContext databaseCon private static void mapAuthorAndEditor(BibEntry entry, Document document, Element recordElement) { Element contributorsElement = document.createElement("contributors"); - entry.getField(StandardField.AUTHOR).ifPresent(authors -> { - Element authorsElement = document.createElement("authors"); - String[] authorArray = authors.split("\\s+and\\s+"); - for (String author : authorArray) { - Element authorElement = document.createElement("author"); - authorElement.setTextContent(author); - authorsElement.appendChild(authorElement); - } - contributorsElement.appendChild(authorsElement); + addPersons(authors, document, contributorsElement, "authors"); }); - entry.getField(StandardField.EDITOR).ifPresent(editors -> { - Element secondaryAuthorsElement = document.createElement("secondary-authors"); - String[] editorArray = editors.split("\\s+and\\s+"); - for (String editor : editorArray) { - Element editorElement = document.createElement("author"); - editorElement.setTextContent(editor); - secondaryAuthorsElement.appendChild(editorElement); - } - contributorsElement.appendChild(secondaryAuthorsElement); + addPersons(editors, document, contributorsElement, "secondary-authors"); }); - if (contributorsElement.hasChildNodes()) { recordElement.appendChild(contributorsElement); } } + + private static void addPersons(String authors, Document document, Element contributorsElement, String wrapTagName) { + Element container = document.createElement(wrapTagName); + AuthorList parsedPersons = AuthorList.parse(authors).latexFree(); + for (Author person : parsedPersons) { + Element authorElement = document.createElement("author"); + authorElement.setTextContent(person.getFamilyGiven(false)); + container.appendChild(authorElement); + } + contributorsElement.appendChild(container); + } + + private static Transformer createTransformer() throws TransformerConfigurationException { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + return transformer; + } } diff --git a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java index be062ecfa8b..38838b388eb 100644 --- a/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java +++ b/src/test/java/org/jabref/logic/exporter/EndnoteXmlExporterFilesTest.java @@ -78,7 +78,7 @@ public final void performExport(String filename) throws Exception { // The order of the XML elements changes // The order does not really matter, so we ignore it. // Source: https://stackoverflow.com/a/16540679/873282 - assertThat(expected, isSimilarTo(actual) + assertThat(actual, isSimilarTo(expected) .ignoreWhitespace() .normalizeWhitespace() .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); From 2fe3d62f96ccabccfb284c3c823c933de6e9395c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 11:55:01 +0200 Subject: [PATCH 64/78] Improve (and use JOURNAL only) --- .../fileformat/EndnoteXmlImporter.java | 116 ++++++++---------- .../EndnoteXmlImporterTestArticle2.bib | 2 - ...dnoteXmlImporterTestLabelAndMultiTitle.bib | 5 +- ...ndnoteXmlImporterTest_WithoutUrlStyle2.bib | 4 +- 4 files changed, 53 insertions(+), 74 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index a6d0f0bc7a0..a31dbda79f1 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -11,6 +11,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.StringJoiner; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; @@ -37,6 +38,7 @@ public class EndnoteXmlImporter extends Importer implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(EndnoteXmlImporter.class); + private static final Map ENTRY_TYPE_MAPPING = Map.ofEntries( Map.entry(StandardEntryType.Article, "Journal Article"), Map.entry(StandardEntryType.Book, "Book"), @@ -59,7 +61,7 @@ public class EndnoteXmlImporter extends Importer implements Parser { Map.entry(StandardField.TITLE, "title"), Map.entry(StandardField.AUTHOR, "authors"), Map.entry(StandardField.EDITOR, "secondary-authors"), - Map.entry(StandardField.JOURNALTITLE, "full-title"), + Map.entry(StandardField.JOURNAL, "full-title"), Map.entry(StandardField.BOOKTITLE, "secondary-title"), Map.entry(StandardField.EDITION, "edition"), Map.entry(StandardField.SERIES, "tertiary-title"), @@ -80,12 +82,14 @@ public class EndnoteXmlImporter extends Importer implements Parser { Map.entry(StandardField.KEYWORDS, "keywords"), Map.entry(StandardField.PAGETOTAL, "page-total"), Map.entry(StandardField.NOTE, "notes"), - // Map.entry(StandardField.LABEL, "label"), + // Map.entry(StandardField.LABEL, "label"), // We omit this field Map.entry(StandardField.LANGUAGE, "language"), - // Map.entry(StandardField.KEY, "foreign-keys"), + // Map.entry(StandardField.KEY, "foreign-keys"), // We omit this field Map.entry(StandardField.ADDRESS, "auth-address") ); + private final ImportFormatPreferences preferences; + private final XMLInputFactory xmlInputFactory; public EndnoteXmlImporter(ImportFormatPreferences preferences) { @@ -188,10 +192,11 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "dates" -> { parseDates(reader, entry); } -// case "accession-num" -> { -// StringBuilder accessionNumber = parseElementContent(reader, "accession-num"); -// entry.setField(new UnknownField("accession-num"), accessionNumber.toString()); -// } + // TODO: Left for future work -- test files need to be adpated + // case "accession-num" -> { + // String accessionNumber = parseElementContent(reader, "accession-num"); + // entry.setField(new UnknownField("accession-num"), accessionNumber); + // } default -> { Field field = FIELD_MAPPING.entrySet().stream() .filter(e -> e.getValue().equals(elementName)) @@ -199,8 +204,8 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { .findFirst() .orElse(null); if (field != null) { - StringBuilder value = parseElementContent(reader, elementName); - entry.setField(field, value.toString()); + String value = parseElementContent(reader, elementName); + entry.setField(field, value); } } } @@ -211,52 +216,32 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { } private void parseContributors(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { - StringBuilder authors = new StringBuilder(); - StringBuilder editors = new StringBuilder(); - while (reader.hasNext()) { reader.next(); if (isEndElement(reader, "contributors")) { break; } + extractPersons(reader, "authors", entry, StandardField.AUTHOR); + extractPersons(reader, "secondary-authors", entry, StandardField.EDITOR); + } + } - if (isStartElement(reader, "authors")) { - while (reader.hasNext()) { - reader.next(); - if (isEndElement(reader, "authors")) { - break; - } - if (isStartElement(reader, "author")) { - StringBuilder author = parseElementContent(reader, "author"); - if (!author.isEmpty()) { - if (!authors.isEmpty()) { - authors.append(" and "); - } - authors.append(author); - } - } + private void extractPersons(XMLStreamReader reader, String elementName, BibEntry entry, StandardField author) throws XMLStreamException { + if (isStartElement(reader, elementName)) { + StringJoiner persons = new StringJoiner(" and "); + while (reader.hasNext()) { + reader.next(); + if (isEndElement(reader, elementName)) { + break; } - entry.setField(StandardField.AUTHOR, authors.toString()); - } - - if (isStartElement(reader, "secondary-authors")) { - while (reader.hasNext()) { - reader.next(); - if (isEndElement(reader, "secondary-authors")) { - break; - } - if (isStartElement(reader, "author")) { - StringBuilder editor = parseElementContent(reader, "author"); - if (!editor.isEmpty()) { - if (!editors.isEmpty()) { - editors.append(" and "); - } - editors.append(editor); - } + if (isStartElement(reader, "author")) { + String person = parseElementContent(reader, "author"); + if (!person.isEmpty()) { + persons.add(person); } } - entry.setField(StandardField.EDITOR, editors.toString()); } + entry.setField(author, persons.toString()); } } @@ -271,17 +256,18 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea String elementName = reader.getName().getLocalPart(); switch (elementName) { case "title" -> { - String title = parseElementContent(reader, "title").toString().trim().replaceAll("\\s+", " "); + String title = parseElementContent(reader, "title"); entry.setField(StandardField.TITLE, title); } case "secondary-title" -> { - String secondaryTitle = parseElementContent(reader, "secondary-title").toString().trim().replaceAll("\\s+", " "); + String secondaryTitle = parseElementContent(reader, "secondary-title"); entry.setField(StandardField.JOURNAL, secondaryTitle); } -// case "alt-title" -> { -// String altTitle = parseElementContent(reader, "alt-title").toString().trim().replaceAll("\\s+", " "); -// entry.setField(new UnknownField("alt-title"), altTitle); -// } + // TODO: Left for future work -- test files need to be adpated + // case "alt-title" -> { + // String altTitle = parseElementContent(reader, "alt-title"); + // entry.setField(new UnknownField("alt-title"), altTitle); + // } } } } @@ -298,8 +284,8 @@ private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLS String elementName = reader.getName().getLocalPart(); switch (elementName) { case "full-title", "abbr-2", "abbr-1", "abbr-3" -> { - StringBuilder journalTitle = parseElementContent(reader, elementName); - entry.setField(StandardField.JOURNALTITLE, journalTitle.toString()); + String journalTitle = parseElementContent(reader, elementName); + entry.setField(StandardField.JOURNAL, journalTitle); } } } @@ -315,7 +301,7 @@ private void parseKeywords(XMLStreamReader reader, BibEntry entry) throws XMLStr } if (isStartElement(reader, "keyword")) { - StringBuilder keyword = parseElementContent(reader, "keyword"); + String keyword = parseElementContent(reader, "keyword"); if (!keyword.isEmpty()) { keywordList.add(keyword.toString()); } @@ -343,7 +329,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - String url = parseElementContent(reader, "url").toString().trim(); + String url = parseElementContent(reader, "url"); entry.setField(StandardField.URL, url); } } @@ -355,7 +341,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - String file = parseElementContent(reader, "url").toString().trim(); + String file = parseElementContent(reader, "url"); entry.setField(StandardField.FILE, file); } } @@ -367,7 +353,7 @@ private void parseUrls(XMLStreamReader reader, BibEntry entry) throws XMLStreamE break; } if (isStartElement(reader, "url")) { - String url = parseElementContent(reader, "url").toString().trim(); + String url = clean(parseElementContent(reader, "url")); entry.setField(StandardField.URL, url); } } @@ -388,8 +374,8 @@ private void parseDates(XMLStreamReader reader, BibEntry entry) throws XMLStream String elementName = reader.getName().getLocalPart(); switch (elementName) { case "year", "month", "day" -> { - StringBuilder date = parseElementContent(reader, elementName); - entry.setField(StandardField.valueOf(elementName.toUpperCase()), date.toString()); + String date = parseElementContent(reader, elementName); + entry.setField(StandardField.fromName(elementName).get(), date); } case "pub-dates" -> { while (reader.hasNext()) { @@ -398,8 +384,8 @@ private void parseDates(XMLStreamReader reader, BibEntry entry) throws XMLStream break; } if (isStartElement(reader, "date")) { - StringBuilder pubDate = parseElementContent(reader, "date"); - entry.setField(StandardField.DATE, pubDate.toString()); + String pubDate = parseElementContent(reader, "date"); + entry.setField(StandardField.DATE, pubDate); } } } @@ -408,7 +394,7 @@ private void parseDates(XMLStreamReader reader, BibEntry entry) throws XMLStream } } - private StringBuilder parseElementContent(XMLStreamReader reader, String elementName) throws XMLStreamException { + private String parseElementContent(XMLStreamReader reader, String elementName) throws XMLStreamException { StringBuilder content = new StringBuilder(); while (reader.hasNext()) { reader.next(); @@ -421,11 +407,11 @@ private StringBuilder parseElementContent(XMLStreamReader reader, String element content.append(reader.getText()); } } - return new StringBuilder(content.toString().trim().replaceAll("\\s+", " ").trim()); + return clean(content.toString()); } private String clean(String input) { - return input.trim().replaceAll(" +", " "); + return input.trim().replaceAll("\\s+", " "); } private boolean isStartElement(XMLStreamReader reader, String elementName) { @@ -450,7 +436,7 @@ public List parseEntries(InputStream inputStream) throws ParseExceptio return importDatabase( new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); } catch (IOException e) { - LOGGER.error(e.getLocalizedMessage(), e); + LOGGER.error("Could not import file", e); } return Collections.emptyList(); } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index 190f5f078ae..f3fad24585c 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -4,7 +4,6 @@ @article{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some notes}, number = {1}, @@ -20,7 +19,6 @@ @book{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some other notes}, number = {1}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index f92c737f0c2..fcbc0da68e0 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -4,7 +4,6 @@ @article{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some notes}, number = {1}, @@ -20,7 +19,6 @@ @book{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some other notes}, number = {1}, @@ -33,9 +31,8 @@ @book{ @article{, author = {Ainley, D.G. and Ribic, C.A. and Wodd, R.C.}, journal = {Journal of Animal Ecology}, - journaltitle = {Journal of Animal Ecology}, pages = {1-20}, title = {A demographic study of the south polar skua Catharacta maccormicki at Cape Crozier}, volume = {59}, year = {1990} -} \ No newline at end of file +} diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index 316175e1382..f3fad24585c 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -4,7 +4,6 @@ @article{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some notes}, number = {1}, @@ -20,7 +19,6 @@ @book{ date = {Jan}, isbn = {0012-9658}, journal = {Ecology}, - journaltitle = {Ecology}, language = {English}, note = {some other notes}, number = {1}, @@ -29,4 +27,4 @@ @book{ url = {://000200148800014}, volume = {18}, year = {1937} -} \ No newline at end of file +} From 4532e284020ebb2dd76961c87cc753edea1e4629 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 17 Apr 2024 11:59:11 +0200 Subject: [PATCH 65/78] Fix obsolete .toString() --- src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java | 2 +- .../jabref/logic/importer/fileformat/EndnoteXmlImporter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 849311e1462..219873b62a4 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -176,7 +176,7 @@ private void mapKeywords(BibDatabase bibDatabase, BibEntry entry, Document docum entry.getResolvedKeywords(bibEntryPreferences.getKeywordSeparator(), bibDatabase).forEach(keyword -> { Element keywordElement = document.createElement("keyword"); // Hierarchical keywords are separated by the '>' character. See {@link } for details. - keywordElement.setTextContent(keyword.get().toString()); + keywordElement.setTextContent(keyword.get()); keywordsElement.appendChild(keywordElement); }); recordElement.appendChild(keywordsElement); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index a31dbda79f1..8ed00c0cdef 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -303,7 +303,7 @@ private void parseKeywords(XMLStreamReader reader, BibEntry entry) throws XMLStr if (isStartElement(reader, "keyword")) { String keyword = parseElementContent(reader, "keyword"); if (!keyword.isEmpty()) { - keywordList.add(keyword.toString()); + keywordList.add(keyword); } } } From e0964a82d37ec629b292ac891bb71d262b835487 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 17:01:11 +0530 Subject: [PATCH 66/78] Removed commented alt-title import --- .../logic/importer/fileformat/EndnoteXmlImporter.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 8ed00c0cdef..476240ed7ce 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -28,6 +28,7 @@ import org.jabref.model.entry.KeywordList; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.EntryType; import org.jabref.model.entry.types.IEEETranEntryType; import org.jabref.model.entry.types.StandardEntryType; @@ -264,10 +265,10 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea entry.setField(StandardField.JOURNAL, secondaryTitle); } // TODO: Left for future work -- test files need to be adpated - // case "alt-title" -> { - // String altTitle = parseElementContent(reader, "alt-title"); - // entry.setField(new UnknownField("alt-title"), altTitle); - // } + case "alt-title" -> { + String altTitle = parseElementContent(reader, "alt-title"); + entry.setField(new UnknownField("alt-title"), altTitle); + } } } } From 8a081edbfa9749f04cd255c71555d3c8dd714497 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 17:06:02 +0530 Subject: [PATCH 67/78] Added back 'aalto-xml' comments and IS_COALESCING property --- .../logic/importer/fileformat/EndnoteXmlImporter.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 476240ed7ce..6faf944aa1f 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -96,6 +96,12 @@ public class EndnoteXmlImporter extends Importer implements Parser { public EndnoteXmlImporter(ImportFormatPreferences preferences) { this.preferences = preferences; xmlInputFactory = XMLInputFactory.newInstance(); + + // prevent xxe (https://rules.sonarsource.com/java/RSPEC-2755) + // not suported by aalto-xml + // xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + // required for reading Unicode characters such as ö + xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); } @Override From a3bb94d755d5d7633bd628da0f92e0b850b11c24 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 17:15:47 +0530 Subject: [PATCH 68/78] Adapt Importer test bib's for alt-title --- .../importer/fileformat/EndnoteXmlImporterTestArticle2.bib | 2 ++ .../fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib | 2 ++ .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index f3fad24585c..896e1b8d0f0 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -1,5 +1,6 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, + alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, @@ -15,6 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, + alt-title = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index fcbc0da68e0..726c3e077ba 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -1,5 +1,6 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, + alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, @@ -15,6 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, + alt-title = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index f3fad24585c..896e1b8d0f0 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -1,5 +1,6 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, + alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, @@ -15,6 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, + alt-title = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, From 7d9763d5f9d8276eac62b6cea310af28e56452f1 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 17:20:42 +0530 Subject: [PATCH 69/78] Add export for alt-title --- .../org/jabref/logic/exporter/EndnoteXmlExporter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 219873b62a4..9dade11f16c 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -153,9 +153,17 @@ public void export(BibDatabaseContext databaseContext, Path file, List private static void mapTitle(BibEntry entry, Document document, Element recordElement) { entry.getFieldOrAlias(StandardField.TITLE).ifPresent(title -> { Element titlesElement = document.createElement("titles"); + Element titleElement = document.createElement("title"); titleElement.setTextContent(title); titlesElement.appendChild(titleElement); + + entry.getField(new UnknownField("alt-title")).ifPresent(altTitle -> { + Element altTitleElement = document.createElement("alt-title"); + altTitleElement.setTextContent(altTitle); + titlesElement.appendChild(altTitleElement); + }); + recordElement.appendChild(titlesElement); }); } From fdb465d1e1ad623ff5375518c0319347d0164d1f Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 17:30:39 +0530 Subject: [PATCH 70/78] Removed TODO comment (complete) --- .../org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 6faf944aa1f..ac78ffff292 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -270,7 +270,6 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea String secondaryTitle = parseElementContent(reader, "secondary-title"); entry.setField(StandardField.JOURNAL, secondaryTitle); } - // TODO: Left for future work -- test files need to be adpated case "alt-title" -> { String altTitle = parseElementContent(reader, "alt-title"); entry.setField(new UnknownField("alt-title"), altTitle); From eba7afd5387415a1f6461fc31072c0215f5d2287 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 18:47:06 +0530 Subject: [PATCH 71/78] Cleanup operation if journal matches alt-title --- .../org/jabref/logic/exporter/EndnoteXmlExporter.java | 6 ++++++ .../logic/importer/fileformat/EndnoteXmlImporter.java | 11 ++++++++++- .../fileformat/EndnoteXmlImporterTestArticle2.bib | 2 +- .../EndnoteXmlImporterTestLabelAndMultiTitle.bib | 2 +- .../EndnoteXmlImporterTest_WithoutUrlStyle2.bib | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java index 9dade11f16c..39b2343c665 100644 --- a/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java +++ b/src/main/java/org/jabref/logic/exporter/EndnoteXmlExporter.java @@ -164,6 +164,12 @@ private static void mapTitle(BibEntry entry, Document document, Element recordEl titlesElement.appendChild(altTitleElement); }); + entry.getField(StandardField.BOOKTITLE).ifPresent(secondaryTitle -> { + Element secondaryTitleElement = document.createElement("secondary-title"); + secondaryTitleElement.setTextContent(secondaryTitle); + titlesElement.appendChild(secondaryTitleElement); + }); + recordElement.appendChild(titlesElement); }); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index ac78ffff292..d8ecdad14f5 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -219,6 +219,15 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { } } + // Cleanup: Remove alt-title if it matches the journal + if (entry.hasField(StandardField.JOURNAL) && entry.hasField(new UnknownField("alt-title"))) { + String journal = entry.getField(StandardField.JOURNAL).orElse(""); + String altTitle = entry.getField(new UnknownField("alt-title")).orElse(""); + if (journal.equals(altTitle)) { + entry.clearField(new UnknownField("alt-title")); + } + } + return entry; } @@ -268,7 +277,7 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea } case "secondary-title" -> { String secondaryTitle = parseElementContent(reader, "secondary-title"); - entry.setField(StandardField.JOURNAL, secondaryTitle); + entry.setField(StandardField.BOOKTITLE, secondaryTitle); } case "alt-title" -> { String altTitle = parseElementContent(reader, "alt-title"); diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index 896e1b8d0f0..c399447252d 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -16,7 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, - alt-title = {Ecology}, + booktitle = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index 726c3e077ba..0d46eb752ec 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -16,7 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, - alt-title = {Ecology}, + booktitle = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index 896e1b8d0f0..c399447252d 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -16,7 +16,7 @@ @article{ } @book{, address = {Univ Chicago, Chicago, IL USA}, - alt-title = {Ecology}, + booktitle = {Ecology}, author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, From 60f3ae2032ad75ee84de79ed3f8a58a6ab19c2f9 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 18:49:05 +0530 Subject: [PATCH 72/78] Update expected bib wrt cleanup --- .../logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib | 1 - .../fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib | 1 - .../fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib | 1 - 3 files changed, 3 deletions(-) diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index c399447252d..2818bece7f5 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -1,6 +1,5 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, - alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index 0d46eb752ec..ca2ad852e20 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -1,6 +1,5 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, - alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index c399447252d..2818bece7f5 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -1,6 +1,5 @@ @article{, address = {Cent States Forest Expt Stn, Columbus, OH USA}, - alt-title = {Ecology}, author = {Chapman, A. G.}, date = {Jan}, isbn = {0012-9658}, From 07bf22c6542be243df58595dc6944262183640d8 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 18:56:06 +0530 Subject: [PATCH 73/78] Update expected xml titles to include secondary-titles --- .../logic/exporter/EndnoteXmlExportTestMultipleEntries.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml index 8998539bfb9..ec211bdcf1c 100644 --- a/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml +++ b/src/test/resources/org/jabref/logic/exporter/EndnoteXmlExportTestMultipleEntries.xml @@ -12,6 +12,7 @@ Episode-Rule Mining with Minimal Occurrences via First Local Maximization in Confidence + Proceedings of the 9th International Symposium on Information and Communication Technology Web-site traversal pattern From ca8e5f739a9a5bba77fa2b62a10a9735f530a451 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 20:37:04 +0530 Subject: [PATCH 74/78] Handle case of Books/Non-article journal -> booktitle --- .../importer/fileformat/EndnoteXmlImporter.java | 12 ++++++++++-- .../fileformat/EndnoteXmlImporterTestArticle2.bib | 1 - .../EndnoteXmlImporterTestLabelAndMultiTitle.bib | 1 - .../EndnoteXmlImporterTest_WithoutUrlStyle2.bib | 1 - 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index d8ecdad14f5..18ee705fa79 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -277,7 +277,11 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea } case "secondary-title" -> { String secondaryTitle = parseElementContent(reader, "secondary-title"); - entry.setField(StandardField.BOOKTITLE, secondaryTitle); + if (entry.getType().equals(StandardEntryType.Article)) { + entry.setField(StandardField.JOURNAL, secondaryTitle); + } else { + entry.setField(StandardField.BOOKTITLE, secondaryTitle); + } } case "alt-title" -> { String altTitle = parseElementContent(reader, "alt-title"); @@ -300,7 +304,11 @@ private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLS switch (elementName) { case "full-title", "abbr-2", "abbr-1", "abbr-3" -> { String journalTitle = parseElementContent(reader, elementName); - entry.setField(StandardField.JOURNAL, journalTitle); + if (entry.getType().equals(StandardEntryType.Article)) { + entry.setField(StandardField.JOURNAL, journalTitle); + } else { + entry.setField(StandardField.BOOKTITLE, journalTitle); + } } } } diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib index 2818bece7f5..72f00bd8af9 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestArticle2.bib @@ -19,7 +19,6 @@ @book{ author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, - journal = {Ecology}, language = {English}, note = {some other notes}, number = {1}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib index ca2ad852e20..d8d124007b0 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTestLabelAndMultiTitle.bib @@ -19,7 +19,6 @@ @book{ author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, - journal = {Ecology}, language = {English}, note = {some other notes}, number = {1}, diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib index 2818bece7f5..72f00bd8af9 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/EndnoteXmlImporterTest_WithoutUrlStyle2.bib @@ -19,7 +19,6 @@ @book{ author = {Strohecker, H. F.}, date = {Jan}, isbn = {0012-9658}, - journal = {Ecology}, language = {English}, note = {some other notes}, number = {1}, From 08393ba8fad14d76c1811fb95f8a929371728192 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 21:10:55 +0530 Subject: [PATCH 75/78] Journal (alt-periodical) check for book --- .../fileformat/EndnoteXmlImporter.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 18ee705fa79..6e0efdab882 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -187,8 +187,8 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "titles" -> { parseTitles(reader, entry); } - case "periodical" -> { - parsePeriodical(reader, entry); + case "periodical", "alt-periodical" -> { + parsePeriodical(reader, entry, elementName); } case "keywords" -> { parseKeywords(reader, entry); @@ -292,24 +292,28 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea } } - private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { + private void parsePeriodical(XMLStreamReader reader, BibEntry entry, String elementName) throws XMLStreamException { while (reader.hasNext()) { reader.next(); - if (isEndElement(reader, "periodical")) { + if (isEndElement(reader, elementName)) { break; } if (isStartElement(reader)) { - String elementName = reader.getName().getLocalPart(); - switch (elementName) { - case "full-title", "abbr-2", "abbr-1", "abbr-3" -> { - String journalTitle = parseElementContent(reader, elementName); - if (entry.getType().equals(StandardEntryType.Article)) { - entry.setField(StandardField.JOURNAL, journalTitle); - } else { - entry.setField(StandardField.BOOKTITLE, journalTitle); - } - } + parseJournalOrBookTitle(reader, entry); + } + } + } + + private void parseJournalOrBookTitle(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "full-title", "abbr-2", "abbr-1", "abbr-3" -> { + String title = parseElementContent(reader, elementName); + if (entry.getType().equals(StandardEntryType.Article)) { + entry.setField(StandardField.JOURNAL, title); + } else { + entry.setField(StandardField.BOOKTITLE, title); } } } From 6af33a30a6ab5bd6004b98d644fae3dafe7659c1 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 21:20:59 +0530 Subject: [PATCH 76/78] Add cleanup for booktitle==alt-title --- .../importer/fileformat/EndnoteXmlImporter.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 6e0efdab882..15f07f401ac 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -220,11 +220,18 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { } // Cleanup: Remove alt-title if it matches the journal - if (entry.hasField(StandardField.JOURNAL) && entry.hasField(new UnknownField("alt-title"))) { - String journal = entry.getField(StandardField.JOURNAL).orElse(""); + if (entry.hasField(new UnknownField("alt-title"))) { String altTitle = entry.getField(new UnknownField("alt-title")).orElse(""); - if (journal.equals(altTitle)) { - entry.clearField(new UnknownField("alt-title")); + if (entry.hasField(StandardField.JOURNAL)) { + String journal = entry.getField(StandardField.JOURNAL).orElse(""); + if (journal.equals(altTitle)) { + entry.clearField(new UnknownField("alt-title")); + } + } else if (entry.hasField(StandardField.BOOKTITLE)) { + String booktitle = entry.getField(StandardField.BOOKTITLE).orElse(""); + if (booktitle.equals(altTitle)) { + entry.clearField(new UnknownField("alt-title")); + } } } From 0527ec776e3d42a4f378cf7dbffcb70e87739146 Mon Sep 17 00:00:00 2001 From: subhramit Date: Wed, 17 Apr 2024 21:27:41 +0530 Subject: [PATCH 77/78] More efficient cleanup --- .../importer/fileformat/EndnoteXmlImporter.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 15f07f401ac..46d65611df4 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -220,18 +220,11 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { } // Cleanup: Remove alt-title if it matches the journal + String journalOrBooktitle = entry.getField(StandardField.JOURNAL).or(() -> entry.getField(StandardField.BOOKTITLE)).orElse(""); if (entry.hasField(new UnknownField("alt-title"))) { String altTitle = entry.getField(new UnknownField("alt-title")).orElse(""); - if (entry.hasField(StandardField.JOURNAL)) { - String journal = entry.getField(StandardField.JOURNAL).orElse(""); - if (journal.equals(altTitle)) { - entry.clearField(new UnknownField("alt-title")); - } - } else if (entry.hasField(StandardField.BOOKTITLE)) { - String booktitle = entry.getField(StandardField.BOOKTITLE).orElse(""); - if (booktitle.equals(altTitle)) { - entry.clearField(new UnknownField("alt-title")); - } + if (journalOrBooktitle.equals(altTitle)) { + entry.clearField(new UnknownField("alt-title")); } } From 794376f2e775574bba06c6165e7ce9f1f9e2c60c Mon Sep 17 00:00:00 2001 From: subhramit Date: Thu, 18 Apr 2024 00:31:56 +0530 Subject: [PATCH 78/78] Review changes - minor comments --- .../fileformat/EndnoteXmlImporter.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index 46d65611df4..5c7f3aa6777 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -62,7 +62,6 @@ public class EndnoteXmlImporter extends Importer implements Parser { Map.entry(StandardField.TITLE, "title"), Map.entry(StandardField.AUTHOR, "authors"), Map.entry(StandardField.EDITOR, "secondary-authors"), - Map.entry(StandardField.JOURNAL, "full-title"), Map.entry(StandardField.BOOKTITLE, "secondary-title"), Map.entry(StandardField.EDITION, "edition"), Map.entry(StandardField.SERIES, "tertiary-title"), @@ -88,6 +87,7 @@ public class EndnoteXmlImporter extends Importer implements Parser { // Map.entry(StandardField.KEY, "foreign-keys"), // We omit this field Map.entry(StandardField.ADDRESS, "auth-address") ); + private static final UnknownField FIELD_ALT_TITLE = new UnknownField("alt-title"); private final ImportFormatPreferences preferences; @@ -187,8 +187,8 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { case "titles" -> { parseTitles(reader, entry); } - case "periodical", "alt-periodical" -> { - parsePeriodical(reader, entry, elementName); + case "periodical" -> { + parsePeriodical(reader, entry); } case "keywords" -> { parseKeywords(reader, entry); @@ -221,10 +221,10 @@ private BibEntry parseRecord(XMLStreamReader reader) throws XMLStreamException { // Cleanup: Remove alt-title if it matches the journal String journalOrBooktitle = entry.getField(StandardField.JOURNAL).or(() -> entry.getField(StandardField.BOOKTITLE)).orElse(""); - if (entry.hasField(new UnknownField("alt-title"))) { - String altTitle = entry.getField(new UnknownField("alt-title")).orElse(""); + if (entry.hasField(FIELD_ALT_TITLE)) { + String altTitle = entry.getField(FIELD_ALT_TITLE).orElse(""); if (journalOrBooktitle.equals(altTitle)) { - entry.clearField(new UnknownField("alt-title")); + entry.clearField(FIELD_ALT_TITLE); } } @@ -285,17 +285,17 @@ private void parseTitles(XMLStreamReader reader, BibEntry entry) throws XMLStrea } case "alt-title" -> { String altTitle = parseElementContent(reader, "alt-title"); - entry.setField(new UnknownField("alt-title"), altTitle); + entry.setField(FIELD_ALT_TITLE, altTitle); } } } } } - private void parsePeriodical(XMLStreamReader reader, BibEntry entry, String elementName) throws XMLStreamException { + private void parsePeriodical(XMLStreamReader reader, BibEntry entry) throws XMLStreamException { while (reader.hasNext()) { reader.next(); - if (isEndElement(reader, elementName)) { + if (isEndElement(reader, "periodical")) { break; }