Skip to content

Commit

Permalink
Support biblatex apa citation for legal entry types (#8966)
Browse files Browse the repository at this point in the history
Co-authored-by: Siedlerchr <[email protected]>
  • Loading branch information
Ognimalf and Siedlerchr authored Aug 1, 2022
1 parent 8389254 commit 02f51f7
Show file tree
Hide file tree
Showing 26 changed files with 369 additions and 108 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- JabRef now writes log files. Linux: `$home/.cache/jabref/logs/version`, Windows: `%APPDATA%\..\Local\harawata\jabref\version\logs`, Mac: `Users/.../Library/Logs/jabref/version`
- We added an importer for Citavi backup files, support ".ctv5bak" and ".ctv6bak" file formats. [#8322](https://github.com/JabRef/jabref/issues/8322)
- We added a feature to drag selected entries and drop them to other opened inactive library tabs [koppor521](https://github.com/koppor/jabref/issues/521).
- We added support for the [biblatex-apa](https://github.com/plk/biblatex-apa) legal entry types `Legislation`, `Legadminmaterial`, `Jurisdiction`, `Constitution` and `Legal` [#8931](https://github.com/JabRef/jabref/issues/8931)

### Changed

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/jabref/gui/EntryTypeView.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.BibEntryType;
import org.jabref.model.entry.types.BiblatexAPAEntryTypeDefinitions;
import org.jabref.model.entry.types.BiblatexEntryTypeDefinitions;
import org.jabref.model.entry.types.BiblatexSoftwareEntryTypeDefinitions;
import org.jabref.model.entry.types.BibtexEntryTypeDefinitions;
Expand Down Expand Up @@ -157,6 +158,7 @@ public void initialize() {
.filter(e -> !recommendedEntries.contains(e))
.collect(Collectors.toList());
otherEntries.addAll(BiblatexSoftwareEntryTypeDefinitions.ALL);
otherEntries.addAll(BiblatexAPAEntryTypeDefinitions.ALL);
} else {
recommendedEntries = BibtexEntryTypeDefinitions.RECOMMENDED;
otherEntries = BibtexEntryTypeDefinitions.ALL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private <T> void parse(T entryType, Map<Field, String> fields) {
} else if (isMethodToIgnore(method.getName())) {
continue;
} else if (method.getName().startsWith("get")) {
putIfValueNotNull(fields, FieldFactory.parseField(method.getName().replace("get", "")), (String) method.invoke(entryType));
putIfValueNotNull(fields, FieldFactory.parseField(entryType, method.getName().replace("get", "")), (String) method.invoke(entryType));
}
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
LOGGER.error("Could not invoke method", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ private String purge(String context, String stringToPurge) {
}
// strip empty lines
while ((runningIndex < indexOfAt) &&
(context.charAt(runningIndex) == '\r' ||
context.charAt(runningIndex) == '\n')) {
((context.charAt(runningIndex) == '\r') ||
(context.charAt(runningIndex) == '\n'))) {
runningIndex++;
}
return context.substring(runningIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.jabref.model.entry.Author;
import org.jabref.model.entry.AuthorList;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.BiblatexSoftwareField;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UnknownField;
Expand Down Expand Up @@ -95,7 +96,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException {
StandardEntryType entryType = StandardEntryType.Software;

// Map CFF fields to JabRef Fields
HashMap<String, StandardField> fieldMap = getFieldMappings();
HashMap<String, Field> fieldMap = getFieldMappings();
for (Map.Entry<String, String> property : citation.values.entrySet()) {
if (fieldMap.containsKey(property.getKey())) {
entryMap.put(fieldMap.get(property.getKey()), property.getValue());
Expand All @@ -120,7 +121,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException {
entryMap.put(StandardField.AUTHOR, authorStr);

// Select DOI to keep
if (entryMap.get(StandardField.DOI) == null && citation.ids != null) {
if ((entryMap.get(StandardField.DOI) == null) && (citation.ids != null)) {
List<CffIdentifier> doiIds = citation.ids.stream()
.filter(id -> id.type.equals("doi"))
.collect(Collectors.toList());
Expand All @@ -137,14 +138,14 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException {
.collect(Collectors.toList());

if (swhIds.size() == 1) {
entryMap.put(StandardField.SWHID, swhIds.get(0));
entryMap.put(BiblatexSoftwareField.SWHID, swhIds.get(0));
} else if (swhIds.size() > 1) {
List<String> relSwhIds = swhIds.stream()
.filter(id -> id.split(":").length > 3) // quick filter for invalid swhids
.filter(id -> id.split(":")[2].equals("rel"))
.collect(Collectors.toList());
if (relSwhIds.size() == 1) {
entryMap.put(StandardField.SWHID, relSwhIds.get(0));
entryMap.put(BiblatexSoftwareField.SWHID, relSwhIds.get(0));
}
}
}
Expand All @@ -166,19 +167,19 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException {

try {
citation = mapper.readValue(reader, CffFormat.class);
return citation != null && citation.values.get("title") != null;
return (citation != null) && (citation.values.get("title") != null);
} catch (IOException e) {
return false;
}
}

private HashMap<String, StandardField> getFieldMappings() {
HashMap<String, StandardField> fieldMappings = new HashMap<>();
private HashMap<String, Field> getFieldMappings() {
HashMap<String, Field> fieldMappings = new HashMap<>();
fieldMappings.put("title", StandardField.TITLE);
fieldMappings.put("version", StandardField.VERSION);
fieldMappings.put("doi", StandardField.DOI);
fieldMappings.put("license", StandardField.LICENSE);
fieldMappings.put("repository", StandardField.REPOSITORY);
fieldMappings.put("license", BiblatexSoftwareField.LICENSE);
fieldMappings.put("repository", BiblatexSoftwareField.REPOSITORY);
fieldMappings.put("url", StandardField.URL);
fieldMappings.put("abstract", StandardField.ABSTRACT);
fieldMappings.put("message", StandardField.COMMENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException {
} else if ("DT- ".equals(code)) {
setOrAppend(b, new UnknownField("documenttype"), line.substring(4).trim(), ", ");
} else {
setOrAppend(b, FieldFactory.parseField(code.substring(0, 2)), line.substring(4).trim(), ", ");
setOrAppend(b, FieldFactory.parseField(StandardEntryType.Book, line.substring(0, 2)), line.substring(4).trim(), ", ");
}
}
results.add(b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public ParserResult importDatabase(BufferedReader reader) throws IOException {
if ("ER".equals(beg) || "EF".equals(beg) || "VR".equals(beg) || "FN".equals(beg)) {
continue;
}
hm.put(FieldFactory.parseField(beg), value);
hm.put(FieldFactory.parseField(type, beg), value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ private void addArticleIdList(Map<Field, String> fields, ArticleIdList articleId
if ("pubmed".equals(id.getIdType())) {
fields.put(StandardField.PMID, id.getContent());
} else {
fields.put(FieldFactory.parseField(id.getIdType()), id.getContent());
fields.put(FieldFactory.parseField(StandardEntryType.Article, id.getIdType()), id.getContent());
}
}
}
Expand Down Expand Up @@ -499,7 +499,7 @@ private void addKeyWords(Map<Field, String> fields, List<KeywordList> allKeyword
private void addOtherId(Map<Field, String> fields, List<OtherID> otherID) {
for (OtherID id : otherID) {
if ((id.getSource() != null) && (id.getContent() != null)) {
fields.put(FieldFactory.parseField(id.getSource()), id.getContent());
fields.put(FieldFactory.parseField(StandardEntryType.Article, id.getSource()), id.getContent());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public MetaData parse(MetaData metaData, Map<String, String> data, Character key
String user = entry.getKey().substring(MetaData.FILE_DIRECTORY.length() + 1);
metaData.setUserFileDirectory(user, getSingleItem(value));
} else if (entry.getKey().startsWith(MetaData.SELECTOR_META_PREFIX)) {
// edge case, it might be one special field e.g. article from biblatex-apa, but we can't distinguish this from any other field and rather prefer to handle it as UnknownField
metaData.addContentSelector(ContentSelectors.parse(FieldFactory.parseField(entry.getKey().substring(MetaData.SELECTOR_META_PREFIX.length())), StringUtil.unquote(entry.getValue(), MetaData.ESCAPE_CHARACTER)));
} else if (entry.getKey().startsWith(MetaData.FILE_DIRECTORY + "Latex-")) {
// The user name comes directly after "FILE_DIRECTORYLatex-"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.field.BibField;
import org.jabref.model.entry.field.FieldFactory;
import org.jabref.model.entry.types.BiblatexAPAEntryTypeDefinitions;
import org.jabref.model.entry.types.BiblatexEntryTypeDefinitions;
import org.jabref.model.entry.types.BiblatexSoftwareEntryTypeDefinitions;
import org.jabref.model.entry.types.BibtexEntryTypeDefinitions;
Expand All @@ -21,7 +22,7 @@
public class BibEntryTypesManager {
public static final String ENTRYTYPE_FLAG = "jabref-entrytype: ";
private final InternalEntryTypes BIBTEX = new InternalEntryTypes(Stream.concat(BibtexEntryTypeDefinitions.ALL.stream(), IEEETranEntryTypeDefinitions.ALL.stream()).collect(Collectors.toList()));
private final InternalEntryTypes BIBLATEX = new InternalEntryTypes(Stream.concat(BiblatexEntryTypeDefinitions.ALL.stream(), BiblatexSoftwareEntryTypeDefinitions.ALL.stream()).collect(Collectors.toList()));
private final InternalEntryTypes BIBLATEX = new InternalEntryTypes(Stream.concat(BiblatexEntryTypeDefinitions.ALL.stream(), Stream.concat(BiblatexSoftwareEntryTypeDefinitions.ALL.stream(), BiblatexAPAEntryTypeDefinitions.ALL.stream())).collect(Collectors.toList()));

public BibEntryTypesManager() {
}
Expand Down Expand Up @@ -99,6 +100,7 @@ public List<BibEntryType> getAllCustomTypes(BibDatabaseMode mode) {
return customizedTypes.stream()
.filter(entryType -> BiblatexEntryTypeDefinitions.ALL.stream().noneMatch(biblatexType -> biblatexType.getType().equals(entryType.getType())))
.filter(entryType -> BiblatexSoftwareEntryTypeDefinitions.ALL.stream().noneMatch(biblatexSoftware -> biblatexSoftware.getType().equals(entryType.getType())))
.filter(entryType -> BiblatexAPAEntryTypeDefinitions.ALL.stream().noneMatch(biblatexAPA -> biblatexAPA.getType().equals(entryType.getType())))
.collect(Collectors.toList());
}
}
Expand Down
82 changes: 82 additions & 0 deletions src/main/java/org/jabref/model/entry/field/BiblatexApaField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.jabref.model.entry.field;

import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Optional;
import java.util.Set;

import org.jabref.model.entry.types.BiblatexApaEntryType;

public enum BiblatexApaField implements Field {

AMENDMENT("amendment"),
ARTICLE("article"),
CITATION("citation"),
CITATION_CITEORG("citation_citeorg"),
CITATION_CITEDATE("citation_citedate", FieldProperty.DATE),
CITATION_CITEINFO("citation_citeinfo"),
SECTION("section", FieldProperty.NUMERIC),
SOURCE("source");

private final String name;
private final String displayName;
private final Set<FieldProperty> properties;

BiblatexApaField(String name) {
this.name = name;
this.displayName = null;
this.properties = EnumSet.noneOf(FieldProperty.class);
}

BiblatexApaField(String name, String displayName) {
this.name = name;
this.displayName = displayName;
this.properties = EnumSet.noneOf(FieldProperty.class);
}

BiblatexApaField(String name, String displayName, FieldProperty first, FieldProperty... rest) {
this.name = name;
this.displayName = displayName;
this.properties = EnumSet.of(first, rest);
}

BiblatexApaField(String name, FieldProperty first, FieldProperty... rest) {
this.name = name;
this.displayName = null;
this.properties = EnumSet.of(first, rest);
}

public static <T> Optional<BiblatexApaField> fromName(T type, String name) {
if (!(type instanceof BiblatexApaEntryType)) {
return Optional.empty();
}
return Arrays.stream(BiblatexApaField.values())
.filter(field -> field.getName().equalsIgnoreCase(name))
.findAny();
}

@Override
public Set<FieldProperty> getProperties() {
return Collections.unmodifiableSet(properties);
}

@Override
public String getName() {
return name;
}

@Override
public boolean isStandardField() {
return false;
}

@Override
public String getDisplayName() {
if (displayName == null) {
return Field.super.getDisplayName();
} else {
return displayName;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.jabref.model.entry.field;

import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Optional;
import java.util.Set;

import org.jabref.model.entry.types.BiblatexSoftwareEntryType;

public enum BiblatexSoftwareField implements Field {

HALID("hal_id"),
HALVERSION("hal_version"),
INTRODUCEDIN("introducedin"),
LICENSE("license"),
RELATEDTYPE("relatedtype"),
RELATEDSTRING("relatedstring"),
REPOSITORY("repository"),
SWHID("swhid");

private final String name;
private final String displayName;
private final Set<FieldProperty> properties;

BiblatexSoftwareField(String name) {
this.name = name;
this.displayName = null;
this.properties = EnumSet.noneOf(FieldProperty.class);
}

BiblatexSoftwareField(String name, String displayName) {
this.name = name;
this.displayName = displayName;
this.properties = EnumSet.noneOf(FieldProperty.class);
}

BiblatexSoftwareField(String name, String displayName, FieldProperty first, FieldProperty... rest) {
this.name = name;
this.displayName = displayName;
this.properties = EnumSet.of(first, rest);
}

BiblatexSoftwareField(String name, FieldProperty first, FieldProperty... rest) {
this.name = name;
this.displayName = null;
this.properties = EnumSet.of(first, rest);
}

public static <T> Optional<BiblatexSoftwareField> fromName(T type, String name) {
if (!(type instanceof BiblatexSoftwareEntryType)) {
return Optional.empty();
}
return Arrays.stream(BiblatexSoftwareField.values())
.filter(field -> field.getName().equalsIgnoreCase(name))
.findAny();
}

@Override
public Set<FieldProperty> getProperties() {
return Collections.unmodifiableSet(properties);
}

@Override
public String getName() {
return name;
}

@Override
public boolean isStandardField() {
return false;
}

@Override
public String getDisplayName() {
if (displayName == null) {
return Field.super.getDisplayName();
} else {
return displayName;
}
}
}
24 changes: 18 additions & 6 deletions src/main/java/org/jabref/model/entry/field/FieldFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,23 @@ public static String serializeFieldsList(Collection<Field> fields) {
.collect(Collectors.joining(DELIMITER));
}

public static <T> Field parseField(T type, String fieldName) {
return OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
InternalField.fromName(fieldName),
StandardField.fromName(fieldName)),
SpecialField.fromName(fieldName)),
IEEEField.fromName(fieldName)),
BiblatexSoftwareField.fromName(type, fieldName)),
BiblatexApaField.fromName(type, fieldName))
.orElse(new UnknownField(fieldName));
}

public static Field parseField(String fieldName) {
return OptionalUtil.<Field>orElse(OptionalUtil.<Field>orElse(OptionalUtil.<Field>orElse(
InternalField.fromName(fieldName),
StandardField.fromName(fieldName)),
SpecialField.fromName(fieldName)),
IEEEField.fromName(fieldName))
.orElse(new UnknownField(fieldName));
return parseField(null, fieldName);
}

public static Set<Field> getKeyFields() {
Expand Down Expand Up @@ -138,6 +148,8 @@ private static Set<Field> getFieldsFiltered(Predicate<Field> selector) {

private static Set<Field> getAllFields() {
Set<Field> fields = new HashSet<>();
fields.addAll(EnumSet.allOf(BiblatexApaField.class));
fields.addAll(EnumSet.allOf(BiblatexSoftwareField.class));
fields.addAll(EnumSet.allOf(IEEEField.class));
fields.addAll(EnumSet.allOf(InternalField.class));
fields.addAll(EnumSet.allOf(SpecialField.class));
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/model/entry/field/IEEEField.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public enum IEEEField implements Field {
this.properties = EnumSet.of(first, rest);
}

public static Optional<IEEEField> fromName(String name) {
public static <T> Optional<IEEEField> fromName(String name) {
return Arrays.stream(IEEEField.values())
.filter(field -> field.getName().equalsIgnoreCase(name))
.findAny();
Expand Down
Loading

0 comments on commit 02f51f7

Please sign in to comment.