From ce72cb6062901bbe0b626eeb725f1028794fd3b5 Mon Sep 17 00:00:00 2001 From: Stanley F Date: Tue, 3 Sep 2019 15:18:13 +0200 Subject: [PATCH] implement field inheritance for crossref-relationships * based on biblatex inheritance rules (c.f. doc appendix B) * fixes JabRef/jabref#5045 --- .../java/org/jabref/model/entry/BibEntry.java | 126 ++++++++++++++++-- 1 file changed, 113 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index 85adabb0ed7..1a19c95baa8 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -32,6 +32,7 @@ import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.identifier.DOI; 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.LatexToUnicodeAdapter; import org.jabref.model.strings.StringUtil; @@ -112,6 +113,110 @@ public Optional getResolvedFieldOrAlias(OrFields fields, BibDatabase dat return Optional.empty(); } + /** + * Map an (empty) field of a BibEntry to a field of a cross-referenced entry. + * + * @param targetField field name of the BibEntry + * @param targetEntry type of the BibEntry + * @param sourceEntry type of the cross-referenced BibEntry + * + * @return the mapped field or null if there is no valid mapping available + */ + private Field getSourceField(Field targetField, EntryType targetEntry, EntryType sourceEntry) { + //// 1. Sort out forbidden fields + if ((targetField == StandardField.IDS) || + (targetField == StandardField.CROSSREF) || + (targetField == StandardField.XREF) || + (targetField == StandardField.ENTRYSET) || + (targetField == StandardField.RELATED) || + (targetField == StandardField.SORTKEY)) { + return null; + } + + //// 2. Handle special field mappings + if ((sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.InBook) || + (sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.BookInBook) || + (sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.SuppBook) || + (sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.InBook) || + (sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.BookInBook) || + (sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.SuppBook)) { + if (targetField == StandardField.AUTHOR) { return StandardField.AUTHOR; } + if (targetField == StandardField.BOOKAUTHOR) { return StandardField.AUTHOR; } + } + + if ((sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.Book) || + (sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.InBook) || + (sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.BookInBook) || + (sourceEntry == StandardEntryType.MvBook && targetEntry == StandardEntryType.SuppBook) || + (sourceEntry == StandardEntryType.MvCollection && targetEntry == StandardEntryType.Collection) || + (sourceEntry == StandardEntryType.MvCollection && targetEntry == StandardEntryType.InCollection) || + (sourceEntry == StandardEntryType.MvCollection && targetEntry == StandardEntryType.SuppCollection) || + (sourceEntry == StandardEntryType.MvProceedings && targetEntry == StandardEntryType.Proceedings) || + (sourceEntry == StandardEntryType.MvProceedings && targetEntry == StandardEntryType.InProceedings) || + (sourceEntry == StandardEntryType.MvReference && targetEntry == StandardEntryType.Reference) || + (sourceEntry == StandardEntryType.MvReference && targetEntry == StandardEntryType.InReference)) { + if (targetField == StandardField.MAINTITLE) { return StandardField.TITLE; } + if (targetField == StandardField.MAINSUBTITLE) { return StandardField.SUBTITLE; } + if (targetField == StandardField.MAINTITLEADDON) { return StandardField.TITLEADDON; } + + // those fields are no more available for the same-name inheritance strategy + if ((targetField == StandardField.TITLE) || + (targetField == StandardField.SUBTITLE) || + (targetField == StandardField.TITLEADDON)) { + return null; + } + + // for these fields, inheritance is not allowed for the specified entry types + if ((targetField == StandardField.SHORTTITLE)) { + return null; + } + } + + if ((sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.InBook) || + (sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.BookInBook) || + (sourceEntry == StandardEntryType.Book && targetEntry == StandardEntryType.SuppBook) || + (sourceEntry == StandardEntryType.Collection && targetEntry == StandardEntryType.InCollection) || + (sourceEntry == StandardEntryType.Collection && targetEntry == StandardEntryType.SuppCollection) || + (sourceEntry == StandardEntryType.Reference && targetEntry == StandardEntryType.InReference) || + (sourceEntry == StandardEntryType.Proceedings && targetEntry == StandardEntryType.InProceedings)) { + if (targetField == StandardField.BOOKTITLE) { return StandardField.TITLE; } + if (targetField == StandardField.BOOKSUBTITLE) { return StandardField.SUBTITLE; } + if (targetField == StandardField.BOOKTITLEADDON) { return StandardField.TITLEADDON; } + + // those fields are no more available for the same-name inheritance strategy + if ((targetField == StandardField.TITLE) || + (targetField == StandardField.SUBTITLE) || + (targetField == StandardField.TITLEADDON)) { + return null; + } + + // for these fields, inheritance is not allowed for the specified entry types + if ((targetField == StandardField.SHORTTITLE)) { + return null; + } + } + + if ((sourceEntry == IEEETranEntryType.Periodical && targetEntry == StandardEntryType.Article) || + (sourceEntry == IEEETranEntryType.Periodical && targetEntry == StandardEntryType.SuppPeriodical)) { + if (targetField == StandardField.JOURNALTITLE) { return StandardField.TITLE; } + if (targetField == StandardField.JOURNALSUBTITLE) { return StandardField.SUBTITLE; } + + // those fields are no more available for the same-name inheritance strategy + if ((targetField == StandardField.TITLE) || + (targetField == StandardField.SUBTITLE)) { + return null; + } + + // for these fields, inheritance is not allowed for the specified entry types + if ((targetField == StandardField.SHORTTITLE)) { + return null; + } + } + + //// 3. Fallback to inherit the field with the same name. + return targetField; + } + /** * Returns the text stored in the given field of the given bibtex entry * which belongs to the given database. @@ -137,21 +242,16 @@ public Optional getResolvedFieldOrAlias(Field field, BibDatabase databas Optional result = getFieldOrAlias(field); // If this field is not set, and the entry has a crossref, try to look up the - // field in the referred entry: Do not do this for the bibtex key. - if (!result.isPresent() && (database != null)) { + // field in the referred entry, following the biblatex rules + if (result.isEmpty() && (database != null)) { Optional referred = database.getReferencedEntry(this); if (referred.isPresent()) { - result = referred.get().getFieldOrAlias(field); - if (!result.isPresent() && type.equals(StandardEntryType.InProceedings)) { - if (field == StandardField.BOOKTITLE) { - result = referred.get().getFieldOrAlias(StandardField.TITLE); - } - else if (field == StandardField.BOOKSUBTITLE) { - result = referred.get().getFieldOrAlias(StandardField.SUBTITLE); - } - else if (field == StandardField.BOOKAUTHOR) { - result = referred.get().getFieldOrAlias(StandardField.AUTHOR); - } + EntryType sourceEntry = referred.get().type.get(); + EntryType targetEntry = type.get(); + Field sourceField = getSourceField(field, targetEntry, sourceEntry); + + if (sourceField != null) { + result = referred.get().getFieldOrAlias(sourceField); } } }