From 5690fbe6ad89b1bb1c68f94098fe07e3d69d34ee Mon Sep 17 00:00:00 2001 From: Artur H <62839385+BeeJay28@users.noreply.github.com> Date: Fri, 19 May 2023 08:57:56 +0200 Subject: [PATCH 01/68] Add fill in of selectedApplicationProperty when opening the editDialog of external application preference (#9921) --- CHANGELOG.md | 1 + .../externalfiletypes/EditExternalFileTypeViewModel.java | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eeb59e82b4e..00565ff0f3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where passing a URL containing a DOI led to a "No entry found" notification. [#9821](https://github.com/JabRef/jabref/issues/9821) - We fixed some minor visual inconsistencies and issues in the preferences dialog. [#9866](https://github.com/JabRef/jabref/pull/9866) - The order of save actions is now retained. [#9890](https://github.com/JabRef/jabref/pull/9890) +- We fixed an issue in the preferences 'External file types' tab ignoring a custom application path in the edit dialog. [#9895](https://github.com/JabRef/jabref/issues/9895) - We fixed an issue in the preferences where custom columns could be added to the entry table with no qualifier. [#9913](https://github.com/JabRef/jabref/issues/9913) ### Removed diff --git a/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeViewModel.java b/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeViewModel.java index 693f6eab412..7a095e76b94 100644 --- a/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/externalfiletypes/EditExternalFileTypeViewModel.java @@ -27,6 +27,7 @@ public EditExternalFileTypeViewModel(ExternalFileTypeItemViewModel fileTypeViewM defaultApplicationSelectedProperty.setValue(true); } else { customApplicationSelectedProperty.setValue(true); + selectedApplicationProperty.setValue(fileTypeViewModel.applicationProperty().getValue()); } } From 8ebf0779709d05f009226900807abf31b26998f3 Mon Sep 17 00:00:00 2001 From: Mahendra Kumar Date: Fri, 19 May 2023 23:08:29 +0530 Subject: [PATCH 02/68] changes in identifierbindings --- buildSrc/build.gradle | 2 ++ .../java/org/jabref/gui/maintable/BibEntryTableViewModel.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 4d40a0a8944..8d36487e1e6 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -25,3 +25,5 @@ sourceSets{ * Source: https://github.com/gradle/gradle/issues/17236#issuecomment-923074298 */ tasks.getByName("jar").setProperty("duplicatesStrategy", DuplicatesStrategy.EXCLUDE); +sourceCompatibility = JavaVersion.VERSION_19 +targetCompatibility = JavaVersion.VERSION_19 diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java index da8c89c9e70..90bd4a66ffa 100644 --- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java +++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java @@ -61,8 +61,10 @@ private static EasyBinding> createLinkedIdentifiersBinding(Bi entry.getFieldBinding(StandardField.DOI), entry.getFieldBinding(StandardField.URI), entry.getFieldBinding(StandardField.EPRINT), - (url, doi, uri, eprint) -> { + entry.getFieldBinding(StandardField.ISBN), + (url, doi, uri, eprint,isbn) -> { Map identifiers = new HashMap<>(); + isbn.ifPresent(value -> identifiers.put(StandardField.URL,"https://openlibrary.org/isbn/"+value)); url.ifPresent(value -> identifiers.put(StandardField.URL, value)); doi.ifPresent(value -> identifiers.put(StandardField.DOI, value)); uri.ifPresent(value -> identifiers.put(StandardField.URI, value)); From e80cd9fb6397b1adcbe25232eeaaa424412d3d3e Mon Sep 17 00:00:00 2001 From: Matthew Theiley Date: Sat, 20 May 2023 12:46:30 +0930 Subject: [PATCH 03/68] 9817 adding HTTP Status Exception check to Grobid Citation Fetcher --- .../jabref/logic/importer/fetcher/GrobidCitationFetcher.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/jabref/logic/importer/fetcher/GrobidCitationFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/GrobidCitationFetcher.java index c33d7e83ac8..628bcde3c36 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/GrobidCitationFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/GrobidCitationFetcher.java @@ -16,6 +16,7 @@ import org.jabref.model.entry.BibEntry; import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode; +import org.jsoup.HttpStatusException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +45,10 @@ public GrobidCitationFetcher(GrobidPreferences grobidPreferences, ImportFormatPr private Optional parseUsingGrobid(String plainText) throws RuntimeException { try { return grobidService.processCitation(plainText, importFormatPreferences, GrobidService.ConsolidateCitations.WITH_METADATA); + } catch (HttpStatusException e) { + String msg = "Connection failure."; + LOGGER.debug(msg, e); + throw new RuntimeException(msg, e); } catch (SocketTimeoutException e) { String msg = "Connection timed out."; LOGGER.debug(msg, e); From 75eae4ff1a95c7e9dd8b89b264896ebb031b22ae Mon Sep 17 00:00:00 2001 From: Mahendra Kumar Date: Sat, 20 May 2023 13:33:36 +0530 Subject: [PATCH 04/68] changes after review comments --- src/main/java/org/jabref/gui/desktop/JabRefDesktop.java | 2 +- .../java/org/jabref/gui/maintable/BibEntryTableViewModel.java | 4 ++-- src/main/java/org/jabref/gui/maintable/OpenUrlAction.java | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java b/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java index ac7ae1e1727..6240e7b8140 100644 --- a/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java +++ b/src/main/java/org/jabref/gui/desktop/JabRefDesktop.java @@ -105,7 +105,7 @@ public static void openExternalViewer(BibDatabaseContext databaseContext, field = StandardField.URL; } - if (StandardField.URL == field) { + if (StandardField.URL == field || StandardField.ISBN == field) { openBrowser(link); } else if (StandardField.PS == field) { try { diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java index 90bd4a66ffa..6f614cb2679 100644 --- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java +++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java @@ -62,13 +62,13 @@ private static EasyBinding> createLinkedIdentifiersBinding(Bi entry.getFieldBinding(StandardField.URI), entry.getFieldBinding(StandardField.EPRINT), entry.getFieldBinding(StandardField.ISBN), - (url, doi, uri, eprint,isbn) -> { + (url, doi, uri, eprint, isbn) -> { Map identifiers = new HashMap<>(); - isbn.ifPresent(value -> identifiers.put(StandardField.URL,"https://openlibrary.org/isbn/"+value)); url.ifPresent(value -> identifiers.put(StandardField.URL, value)); doi.ifPresent(value -> identifiers.put(StandardField.DOI, value)); uri.ifPresent(value -> identifiers.put(StandardField.URI, value)); eprint.ifPresent(value -> identifiers.put(StandardField.EPRINT, value)); + isbn.ifPresent(value -> identifiers.put(StandardField.ISBN, value)); return identifiers; }); } diff --git a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java index 805452e792c..6f4ff87a16b 100644 --- a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java @@ -62,6 +62,10 @@ public void execute() { link = entry.getField(StandardField.URL); field = StandardField.URL; } + if (entry.hasField(StandardField.ISBN)) { + link = Optional.of("https://openlibrary.org/isbn/" + entry.getField(StandardField.ISBN).get()); + field = StandardField.ISBN; + } if (link.isPresent()) { try { From 9038bdaccae027a5559e77032e4aa964ecec42be Mon Sep 17 00:00:00 2001 From: Mahendra Kumar Date: Sat, 20 May 2023 17:29:51 +0530 Subject: [PATCH 05/68] Fixes web icon also for ISBNs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00565ff0f3c..ebbf042ef5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - The order of save actions is now retained. [#9890](https://github.com/JabRef/jabref/pull/9890) - We fixed an issue in the preferences 'External file types' tab ignoring a custom application path in the edit dialog. [#9895](https://github.com/JabRef/jabref/issues/9895) - We fixed an issue in the preferences where custom columns could be added to the entry table with no qualifier. [#9913](https://github.com/JabRef/jabref/issues/9913) +- We fixed an issue where ISBNs were not having a link icon in linked identifiers column. [#9819](https://github.com/JabRef/jabref/issues/9819) ### Removed From 515edcc837b397d1b4e0493140d00dce354e8eee Mon Sep 17 00:00:00 2001 From: Ting Tse Chang <87943503+DinjerChang@users.noreply.github.com> Date: Sat, 20 May 2023 05:07:37 -0700 Subject: [PATCH 06/68] Rewrite EndnoteXMLImporter as a StAX-Parser (#9880) Co-authored-by: chiao26168 <72399061+chiao26168@users.noreply.github.com> --- CHANGELOG.md | 1 + build.gradle | 8 - .../fileformat/EndnoteXmlImporter.java | 560 ++++++++----- src/main/resources/xjc/endnote/endnote.xsd | 790 ------------------ ...dnoteXmlImporterTest_EmptyKeywordStyle.bib | 2 +- 5 files changed, 366 insertions(+), 995 deletions(-) delete mode 100644 src/main/resources/xjc/endnote/endnote.xsd diff --git a/CHANGELOG.md b/CHANGELOG.md index 00565ff0f3c..06ccef14d13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - In case the library contains empty entries, they are not written to disk. [#8645](https://github.com/JabRef/jabref/issues/8645) - The formatter `remove_unicode_ligatures` is now called `replace_unicode_ligatures`. [#9890](https://github.com/JabRef/jabref/pull/9890) + ### Fixed - We fixed an issue where the browser import would add ' characters before the BibTeX entry on Linux. [#9588](https://github.com/JabRef/jabref/issues/9588) diff --git a/build.gradle b/build.gradle index 34ab610c984..6877e3b17df 100644 --- a/build.gradle +++ b/build.gradle @@ -261,7 +261,6 @@ processResources { task generateSource(dependsOn: ["generateBstGrammarSource", "generateSearchGrammarSource", - "generateEndnoteSource", "generateCitaviSource"]) { group = 'JabRef' description 'Generates all necessary (Java) source files.' @@ -289,14 +288,7 @@ tasks.register("generateSearchGrammarSource", JavaExec) { args = ["-o","src-gen/main/java/org/jabref/search" , "-visitor", "-no-listener", "-package", "org.jabref.search", "$projectDir/src/main/antlr4/org/jabref/search/Search.g4"] } -task generateEndnoteSource(type: XjcTask) { - group = 'JabRef' - description = "Generates java files for the endnote importer." - schemaFile = "src/main/resources/xjc/endnote/endnote.xsd" - outputDirectory = "src-gen/main/java/" - javaPackage = "org.jabref.logic.importer.fileformat.endnote" -} task generateCitaviSource(type: XjcTask) { group = 'JabRef' 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 8ba682156cc..9134f9288e6 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -7,61 +7,38 @@ 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; -import java.util.Optional; -import java.util.stream.Collectors; +import javax.xml.XMLConstants; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.events.XMLEvent; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.Importer; +import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.importer.fileformat.endnote.Abstract; -import org.jabref.logic.importer.fileformat.endnote.Authors; -import org.jabref.logic.importer.fileformat.endnote.Contributors; -import org.jabref.logic.importer.fileformat.endnote.Dates; -import org.jabref.logic.importer.fileformat.endnote.ElectronicResourceNum; -import org.jabref.logic.importer.fileformat.endnote.Isbn; -import org.jabref.logic.importer.fileformat.endnote.Keyword; -import org.jabref.logic.importer.fileformat.endnote.Keywords; -import org.jabref.logic.importer.fileformat.endnote.Label; -import org.jabref.logic.importer.fileformat.endnote.Notes; -import org.jabref.logic.importer.fileformat.endnote.Number; -import org.jabref.logic.importer.fileformat.endnote.Pages; -import org.jabref.logic.importer.fileformat.endnote.PdfUrls; -import org.jabref.logic.importer.fileformat.endnote.Publisher; -import org.jabref.logic.importer.fileformat.endnote.Record; -import org.jabref.logic.importer.fileformat.endnote.RefType; -import org.jabref.logic.importer.fileformat.endnote.RelatedUrls; -import org.jabref.logic.importer.fileformat.endnote.SecondaryTitle; -import org.jabref.logic.importer.fileformat.endnote.Style; -import org.jabref.logic.importer.fileformat.endnote.Title; -import org.jabref.logic.importer.fileformat.endnote.Titles; -import org.jabref.logic.importer.fileformat.endnote.Url; -import org.jabref.logic.importer.fileformat.endnote.Urls; -import org.jabref.logic.importer.fileformat.endnote.Volume; -import org.jabref.logic.importer.fileformat.endnote.Xml; -import org.jabref.logic.importer.fileformat.endnote.Year; 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 org.jabref.model.util.OptionalUtil; -import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBException; -import jakarta.xml.bind.Unmarshaller; +import com.google.common.base.Joiner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,12 +51,15 @@ public class EndnoteXmlImporter extends Importer implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(EndnoteXmlImporter.class); private final ImportFormatPreferences preferences; - private Unmarshaller unmarshaller; public EndnoteXmlImporter(ImportFormatPreferences preferences) { this.preferences = preferences; } + private static String join(List list, String string) { + return Joiner.on(string).join(list); + } + @Override public String getName() { return "EndNote XML"; @@ -115,47 +95,110 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { } @Override - public ParserResult importDatabase(BufferedReader reader) throws IOException { - Objects.requireNonNull(reader); + public ParserResult importDatabase(BufferedReader input) throws IOException { + Objects.requireNonNull(input); + + List bibItems = new ArrayList<>(); + try { - Object unmarshalledObject = unmarshallRoot(reader); - if (unmarshalledObject instanceof Xml root) { - // We have an article set, an article, a book article or a book article set - List bibEntries = root - .getRecords().getRecord() - .stream() - .map(this::parseRecord) - .collect(Collectors.toList()); - return new ParserResult(bibEntries); - } else { - return ParserResult.fromErrorMessage("File does not start with xml tag."); + XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + + // prevent xxe (https://rules.sonarsource.com/java/RSPEC-2755) + xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + // required for reading Unicode characters such as ö + xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true); + + XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(input); + + while (reader.hasNext()) { + reader.next(); + if (isStartXMLEvent(reader)) { + String elementName = reader.getName().getLocalPart(); + if ("record".equals(elementName)) { + parseRecord(reader, bibItems, elementName); + } + } } - } catch (JAXBException | XMLStreamException e) { + } catch (XMLStreamException e) { LOGGER.debug("could not parse document", e); return ParserResult.fromError(e); } + return new ParserResult(bibItems); } - private Object unmarshallRoot(BufferedReader reader) throws XMLStreamException, JAXBException { - initUnmarshaller(); - - XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); - XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(reader); - - // Go to the root element - while (!xmlStreamReader.isStartElement()) { - xmlStreamReader.next(); + 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<>(); + + 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 "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); + } + } + } + if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { + break; + } } - return unmarshaller.unmarshal(xmlStreamReader); - } + BibEntry entry = new BibEntry(entryType); + entry.putKeywords(keywordList, preferences.bibEntryPreferences().getKeywordSeparator()); - private void initUnmarshaller() throws JAXBException { - if (unmarshaller == null) { - // Lazy init because this is expensive - JAXBContext context = JAXBContext.newInstance("org.jabref.logic.importer.fileformat.endnote"); - unmarshaller = context.createUnmarshaller(); - } + entry.setField(fields); + entry.setFiles(linkedFiles); + bibItems.add(entry); } private static EntryType convertRefNameToType(String refName) { @@ -170,156 +213,258 @@ private static EntryType convertRefNameToType(String refName) { }; } - private BibEntry parseRecord(Record endNoteRecord) { - BibEntry entry = new BibEntry(); - - entry.setType(getType(endNoteRecord)); - Optional.ofNullable(getAuthors(endNoteRecord)) - .ifPresent(value -> entry.setField(StandardField.AUTHOR, value)); - Optional.ofNullable(endNoteRecord.getTitles()) - .map(Titles::getTitle) - .map(Title::getStyle) - .map(this::mergeStyleContents) - .ifPresent(value -> entry.setField(StandardField.TITLE, clean(value))); - Optional.ofNullable(endNoteRecord.getTitles()) - .map(Titles::getSecondaryTitle) - .map(SecondaryTitle::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.JOURNAL, clean(value))); - Optional.ofNullable(endNoteRecord.getPages()) - .map(Pages::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.PAGES, value)); - Optional.ofNullable(endNoteRecord.getNumber()) - .map(Number::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.NUMBER, value)); - Optional.ofNullable(endNoteRecord.getVolume()) - .map(Volume::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.VOLUME, value)); - Optional.ofNullable(endNoteRecord.getDates()) - .map(Dates::getYear) - .map(Year::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.YEAR, value)); - Optional.ofNullable(endNoteRecord.getNotes()) - .map(Notes::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.NOTE, value.trim())); - getUrl(endNoteRecord) - .ifPresent(value -> entry.setField(StandardField.URL, value)); - entry.putKeywords(getKeywords(endNoteRecord), preferences.bibEntryPreferences().getKeywordSeparator()); - Optional.ofNullable(endNoteRecord.getAbstract()) - .map(Abstract::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.ABSTRACT, value.trim())); - entry.setFiles(getLinkedFiles(endNoteRecord)); - Optional.ofNullable(endNoteRecord.getIsbn()) - .map(Isbn::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.ISBN, clean(value))); - Optional.ofNullable(endNoteRecord.getElectronicResourceNum()) - .map(ElectronicResourceNum::getStyle) - .map(Style::getContent) - .ifPresent(doi -> entry.setField(StandardField.DOI, doi.trim())); - Optional.ofNullable(endNoteRecord.getPublisher()) - .map(Publisher::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(StandardField.PUBLISHER, value)); - Optional.ofNullable(endNoteRecord.getLabel()) - .map(Label::getStyle) - .map(Style::getContent) - .ifPresent(value -> entry.setField(new UnknownField("endnote-label"), value)); - - return entry; + private void handleAuthorList(XMLStreamReader reader, Map fields, String startElement) throws XMLStreamException { + List authorNames = new ArrayList<>(); + + while (reader.hasNext()) { + reader.next(); + if (isStartXMLEvent(reader)) { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "author" -> { + parseAuthor(reader, authorNames); + } + } + } + + 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()); + } + } + } + } + + if (isEndXMLEvent(reader) && "author".equals(reader.getName().getLocalPart())) { + break; + } + } } - private EntryType getType(Record endNoteRecord) { - return Optional.ofNullable(endNoteRecord.getRefType()) - .map(RefType::getName) - .map(EndnoteXmlImporter::convertRefNameToType) - .orElse(StandardEntryType.Article); + 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; + } + } } - private List getLinkedFiles(Record endNoteRecord) { - Optional urls = Optional.ofNullable(endNoteRecord.getUrls()) - .map(Urls::getPdfUrls); - return OptionalUtil.toStream(urls) - .flatMap(pdfUrls -> pdfUrls.getUrl().stream()) - .flatMap(url -> OptionalUtil.toStream(getUrlValue(url))) - .map(url -> { - try { - return new LinkedFile(new URL(url), "PDF"); - } catch (MalformedURLException e) { - LOGGER.info("Unable to parse {}", url); - return null; - } - }) - .collect(Collectors.toList()); + private void parseYear(XMLStreamReader reader, Map fields) 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())) { + break; + } + } + } + + private void handleKeywordsList(XMLStreamReader reader, KeywordList keywordList, String startElement) throws XMLStreamException { + + while (reader.hasNext()) { + reader.next(); + if (isStartXMLEvent(reader)) { + String elementName = reader.getName().getLocalPart(); + switch (elementName) { + case "keyword" -> { + parseKeyword(reader, keywordList); + } + } + } + if (isEndXMLEvent(reader) && reader.getName().getLocalPart().equals(startElement)) { + break; + } + } } - private Optional getUrl(Record endNoteRecord) { - Optional urls = Optional.ofNullable(endNoteRecord.getUrls()) - .map(Urls::getRelatedUrls); - return OptionalUtil.toStream(urls) - .flatMap(url -> url.getUrl().stream()) - .flatMap(url -> OptionalUtil.toStream(getUrlValue(url))) - .findFirst(); + 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 String mergeStyleContents(List diff --git a/dependent/turabian-fullnote-bibliography.csl b/dependent/turabian-fullnote-bibliography.csl new file mode 100644 index 00000000000..67f916a42c5 --- /dev/null +++ b/dependent/turabian-fullnote-bibliography.csl @@ -0,0 +1,15 @@ + + diff --git a/european-review-of-agricultural-economics.csl b/european-review-of-agricultural-economics.csl index 80d5b9700d1..9945751671f 100644 --- a/european-review-of-agricultural-economics.csl +++ b/european-review-of-agricultural-economics.csl @@ -214,9 +214,6 @@ - - - @@ -1227,7 +1224,7 @@ - + @@ -1242,7 +1239,7 @@ - + diff --git a/food-and-agriculture-organization-of-the-united-nations-numeric.csl b/food-and-agriculture-organization-of-the-united-nations-numeric.csl new file mode 100644 index 00000000000..6e985542482 --- /dev/null +++ b/food-and-agriculture-organization-of-the-united-nations-numeric.csl @@ -0,0 +1,377 @@ + + diff --git a/fundamental-and-applied-limnology.csl b/fundamental-and-applied-limnology.csl index 8777a232882..de3f1c499c8 100644 --- a/fundamental-and-applied-limnology.csl +++ b/fundamental-and-applied-limnology.csl @@ -47,8 +47,8 @@ @@ -116,7 +116,7 @@ - @@ -197,7 +197,7 @@ - @@ -230,9 +230,6 @@ - - - @@ -258,7 +255,7 @@ - @@ -1023,7 +1020,7 @@ - @@ -1303,7 +1300,7 @@ - @@ -1576,7 +1573,7 @@ - + @@ -1593,7 +1590,7 @@ - + diff --git a/german-council-of-economic-experts.csl b/german-council-of-economic-experts.csl index df8463fa1fa..f7df9274351 100644 --- a/german-council-of-economic-experts.csl +++ b/german-council-of-economic-experts.csl @@ -30,7 +30,7 @@ Style for the German Council of Economic Experts - 2021-09-13T14:00:00+02:00 + 2023-05-26T14:00:00+02:00 This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License @@ -64,7 +64,7 @@ - + @@ -111,7 +111,7 @@ - + diff --git a/harvard-deakin-university.csl b/harvard-deakin-university.csl index 0ede477a1e5..771504ed934 100644 --- a/harvard-deakin-university.csl +++ b/harvard-deakin-university.csl @@ -4,7 +4,7 @@ Deakin University - Harvard http://www.zotero.org/styles/harvard-deakin-university - + simtyrell diff --git a/harvard-the-university-of-melbourne.csl b/harvard-the-university-of-melbourne.csl deleted file mode 100644 index 585b9d1a8da..00000000000 --- a/harvard-the-university-of-melbourne.csl +++ /dev/null @@ -1,222 +0,0 @@ - - diff --git a/harvard-university-of-the-west-of-england.csl b/harvard-university-of-the-west-of-england.csl index e5bdfcb075c..408d51fd9bf 100644 --- a/harvard-university-of-the-west-of-england.csl +++ b/harvard-university-of-the-west-of-england.csl @@ -12,13 +12,18 @@ Harvard author-date style updated for University of the West of England (UWE) (et-al format updated to comply with UWE Harvard Referencing - 2022-04-10T15:09:45+00:00 + 2023-05-02T13:01:26+00:00 This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License + + + available from + + - @@ -42,29 +47,18 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + @@ -98,12 +92,10 @@ - - - - - + + @@ -113,7 +105,7 @@ - + @@ -280,7 +272,7 @@ - + @@ -310,10 +302,10 @@ - + - + @@ -321,9 +313,9 @@ - + - + @@ -331,7 +323,7 @@ - + @@ -344,19 +336,25 @@ - + - - + + + + + + + + - + diff --git a/ieee-with-url.csl b/ieee-with-url.csl index 26dbc82af21..63d871fbc99 100644 --- a/ieee-with-url.csl +++ b/ieee-with-url.csl @@ -4,7 +4,9 @@ IEEE (with URL) http://www.zotero.org/styles/ieee-with-url - + + + Michael Berkowitz @@ -25,11 +27,26 @@ Sebastian Karcher + + Giuseppe Silano + g.silano89@gmail.com + http://giuseppesilano.net + + + Patrick O'Brien + + + Brenton M. Wiernik + + + Oliver Couch + oliver.couch@gmail.com + - IEEE style with URLs as per the 2018 guidelines, V 11.12.2018. - 2019-12-20T09:20:25+00:00 + IEEE style as per the 2021 guidelines, V 01.29.2021. + 2023-04-23T03:05:51+00:00 This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License @@ -45,6 +62,13 @@ + + + + + + + @@ -151,26 +175,20 @@ + - - - - - - - - + + + + - - - - - - + + + @@ -178,27 +196,41 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - @@ -212,8 +244,30 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -235,118 +289,146 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/journal-of-the-american-philosophical-association.csl b/journal-of-the-american-philosophical-association.csl new file mode 100644 index 00000000000..39ef20eab02 --- /dev/null +++ b/journal-of-the-american-philosophical-association.csl @@ -0,0 +1,188 @@ + + diff --git a/mots.csl b/mots.csl index f6a0b1f2ad4..f1d6d822a6a 100644 --- a/mots.csl +++ b/mots.csl @@ -1,5 +1,5 @@ -