Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support biblatex apa citation for legal entry types #8966

Merged
merged 10 commits into from
Aug 1, 2022
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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💕🎉

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