diff --git a/CHANGELOG.md b/CHANGELOG.md index e443c7ae84d..5c0d1237af2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where brackets in regular expressions were not working. [6469](https://github.com/JabRef/jabref/pull/6469) - We fixed an issue where LaTeX citations for specific commands (\autocites) of biblatex-mla were not recognized. [#6476](https://github.com/JabRef/jabref/issues/6476) - We fixed an issue where drag and drop was not working on empty database. [#6487](https://github.com/JabRef/jabref/issues/6487) +- We fixed an issue where "null" appeared in generated BibTeX keys. [#6459](https://github.com/JabRef/jabref/issues/6459) +- We fixed an issue where the authors' names were incorrectly displayed in the authors' column when they were bracketed. [#6465](https://github.com/JabRef/jabref/issues/6465) [#6459](https://github.com/JabRef/jabref/issues/6459) ### Removed diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java index c09c540ef39..91da602cdf7 100644 --- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java +++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java @@ -115,28 +115,27 @@ public ObservableValue getFields(OrFields fields) { ObservableValue value = fieldValues.get(fields); if (value != null) { return value; - } else { - value = Bindings.createStringBinding(() -> { - boolean isName = false; + } - Optional content = Optional.empty(); - for (Field field : fields) { - content = entry.getResolvedFieldOrAliasLatexFree(field, database); - if (content.isPresent()) { - isName = field.getProperties().contains(FieldProperty.PERSON_NAMES); - break; - } - } + value = Bindings.createStringBinding(() -> { + for (Field field : fields) { + if (field.getProperties().contains(FieldProperty.PERSON_NAMES)) { + Optional name = entry.getResolvedFieldOrAlias(field, database); - String result = content.orElse(null); - if (isName) { - return nameFormatter.formatName(result); + if (name.isPresent()) { + return nameFormatter.formatNameLatexFree(name.get()); + } } else { - return result; + Optional content = entry.getResolvedFieldOrAliasLatexFree(field, database); + + if (content.isPresent()) { + return content.get(); + } } - }, entry.getObservables()); - fieldValues.put(fields, value); - return value; - } + } + return ""; + }, entry.getObservables()); + fieldValues.put(fields, value); + return value; } } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableNameFormatter.java b/src/main/java/org/jabref/gui/maintable/MainTableNameFormatter.java index 741c0027c66..287f249a17a 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableNameFormatter.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableNameFormatter.java @@ -20,26 +20,28 @@ public class MainTableNameFormatter { } /** - * Format a name field for the table, according to user preferences. + * Format a name field for the table, according to user preferences and with latex expressions translated if + * possible. * * @param nameToFormat The contents of the name field. * @return The formatted name field. */ - public String formatName(final String nameToFormat) { + public String formatNameLatexFree(final String nameToFormat) { if (nameToFormat == null) { return null; } + AuthorList authors = AuthorList.parse(nameToFormat); if (namesAsIs) { return nameToFormat; } else if (namesNatbib) { - return AuthorList.fixAuthorNatbib(nameToFormat); + return authors.getAsNatbibLatexFree(); } else if (namesLastOnly) { - return AuthorList.fixAuthorLastNameOnlyCommas(nameToFormat, false); + return authors.getAsLastNamesLatexFree(false); } else if (namesFf) { - return AuthorList.fixAuthorFirstNameFirstCommas(nameToFormat, abbrAuthorNames, false); + return authors.getAsFirstLastNamesLatexFree(abbrAuthorNames, false); } else { - return AuthorList.fixAuthorLastNameFirstCommas(nameToFormat, abbrAuthorNames, false); + return authors.getAsLastFirstNamesLatexFree(abbrAuthorNames, false); } } } diff --git a/src/main/java/org/jabref/logic/bibtexkeypattern/BracketedPattern.java b/src/main/java/org/jabref/logic/bibtexkeypattern/BracketedPattern.java index cc7e843d016..d5ca948d037 100644 --- a/src/main/java/org/jabref/logic/bibtexkeypattern/BracketedPattern.java +++ b/src/main/java/org/jabref/logic/bibtexkeypattern/BracketedPattern.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -10,6 +11,7 @@ import java.util.Scanner; import java.util.StringJoiner; import java.util.StringTokenizer; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,9 +43,54 @@ public class BracketedPattern { private static final Logger LOGGER = LoggerFactory.getLogger(BracketedPattern.class); - private static final String STARTING_CAPITAL_PATTERN = "[^A-Z]"; private static final int CHARS_OF_FIRST = 5; - private static final Pattern REGEX_PATTERN = Pattern.compile(".*\\(\\{([A-Z]+)\\}\\).*"); + + /** Matches everything that is not an uppercase ASCII letter */ + private static final Pattern NOT_CAPITAL_FIRST_CHARACTER = Pattern.compile("[^A-Z]"); + /** Matches with "({[A-Z]}+)", which should be used to abbreviate the name of an institution */ + private static final Pattern ABBREVIATIONS = Pattern.compile(".*\\(\\{[A-Z]+}\\).*"); + /** Matches with "dep"/"dip", case insensitive */ + private static final Pattern DEPARTMENTS = Pattern.compile("^d[ei]p.*", Pattern.CASE_INSENSITIVE); + private enum Institution { + SCHOOL, + DEPARTMENT, + UNIVERSITY, + TECHNOLOGY; + + /** Matches "uni" at the start of a string or after a space, case insensitive */ + private static final Pattern UNIVERSITIES = Pattern.compile("^uni.*", Pattern.CASE_INSENSITIVE); + /** Matches with "tech", case insensitive */ + private static final Pattern TECHNOLOGICAL_INSTITUTES = Pattern.compile("^tech.*", Pattern.CASE_INSENSITIVE); + /** Matches with "dep"/"dip"/"lab", case insensitive */ + private static final Pattern DEPARTMENTS_OR_LABS = Pattern.compile("^(d[ei]p|lab).*", Pattern.CASE_INSENSITIVE); + + /** + * Find which types of institutions have words in common with the given name parts. + * @param nameParts a list of words that constitute parts of an institution's name. + * @return set containing all types that matches + */ + public static EnumSet findTypes(List nameParts) { + EnumSet parts = EnumSet.noneOf(Institution.class); + // Deciding about a part type… + for (String namePart : nameParts) { + if (UNIVERSITIES.matcher(namePart).matches()) { + parts.add(Institution.UNIVERSITY); + } else if (TECHNOLOGICAL_INSTITUTES.matcher(namePart).matches()) { + parts.add(Institution.TECHNOLOGY); + } else if (StandardField.SCHOOL.getName().equalsIgnoreCase(namePart)) { + parts.add(Institution.SCHOOL); + } else if (DEPARTMENTS_OR_LABS.matcher(namePart).matches()) { + parts.add(Institution.DEPARTMENT); + } + } + + if (parts.contains(Institution.TECHNOLOGY)) { + parts.remove(Institution.UNIVERSITY); // technology institute isn't university :-) + } + + return parts; + } + } private final String pattern; @@ -1200,8 +1247,8 @@ private static boolean isInstitution(String author) { * *

* An institution name should be inside {} brackets. If the - * institution name also includes its abbreviation this abbreviation should - * be also in {} brackets. For the previous example the value + * institution name includes its abbreviation this abbreviation should + * be in {} brackets. For the previous example the value * should look like: * {The Attributed Graph Grammar System ({AGG})}. *

@@ -1213,15 +1260,15 @@ private static boolean isInstitution(String author) { * *

* If an institution does not include its abbreviation the key should be - * generated form its name in the following way: + * generated from its name in the following way: *

* *

* The institution value can contain: institution name, part of the - * institution, address, etc. Those information should be separated by - * comma. Name of the institution and possible part of the institution - * should be on the beginning, while address and secondary information - * should be on the end. + * institution, address, etc. These values should be comma separated. + * Institution name and possible part of the institution + * should be in the beginning, while address and secondary information + * should be in the end. *

* * Each part is examined separately: @@ -1229,17 +1276,18 @@ private static boolean isInstitution(String author) { *
  • We remove all tokens of a part which are one of the defined ignore * words (the, press), which end with a dot (ltd., co., ...) and which first * character is lowercase (of, on, di, ...).
  • - *
  • We detect a type of the part: university, technology institute, + *
  • We detect the types of the part: university, technology institute, * department, school, rest *
      *
    • University: "Uni[NameOfTheUniversity]"
    • - *
    • Department: will be an abbreviation of all words beginning with the - * uppercase letter except of words: d[ei]p.*, school, - * faculty
    • + *
    • Department: If the institution value contains more than one comma + * separated part, the department will be an abbreviation of all words + * beginning with the uppercase letter except of words: + * d[ei]p.*, school, faculty
    • *
    • School: same as department
    • *
    • Rest: If there are less than 3 tokens in such part than the result - * will be by concatenating those tokens, otherwise the result will be build - * from the first letters of words starting with and uppercase letter.
    • + * is a concatenation of those tokens. Otherwise, the result will be built + * from the first letter in each token. *
    * *

    @@ -1262,20 +1310,23 @@ private static boolean isInstitution(String author) { * */ private static String generateInstitutionKey(String content) { - if (content.isEmpty()) { - return content; + if (content == null) { + return null; + } + if (content.isBlank()) { + return ""; } String result = content; result = unifyDiacritics(result); - result = result.replaceAll("^\\{", "").replaceAll("\\}$", ""); - Matcher matcher = REGEX_PATTERN.matcher(result); + result = result.replaceAll("^\\{", "").replaceAll("}$", ""); + Matcher matcher = ABBREVIATIONS.matcher(result); if (matcher.matches()) { return matcher.group(1); } result = removeDiacritics(result); - String[] parts = result.split(","); + String[] institutionNameTokens = result.split(","); // Key parts String university = null; @@ -1283,113 +1334,97 @@ private static String generateInstitutionKey(String content) { String school = null; String rest = null; - List ignore = Arrays.asList("press", "the"); - for (int index = 0; index < parts.length; index++) { - List part = new ArrayList<>(); - - // Cleanup: remove unnecessary words. - for (String k : parts[index].replaceAll("\\{[A-Z]+\\}", "").split("[ \\-_]")) { - if ((!(k.isEmpty()) // remove empty - && !ignore.contains(k.toLowerCase(Locale.ENGLISH)) // remove ignored words - && (k.charAt(k.length() - 1) != '.') - && (String.valueOf(k.charAt(0))).matches("[A-Z]")) - || ((k.length() >= 3) && "uni".equalsIgnoreCase(k.substring(0, 2)))) { - part.add(k); - } - } + for (int index = 0; index < institutionNameTokens.length; index++) { + List tokenParts = getValidInstitutionNameParts(institutionNameTokens[index]); + EnumSet tokenTypes = Institution.findTypes(tokenParts); - boolean isUniversity = false; // university - boolean isTechnology = false; // technology institute - boolean isDepartment = false; // departments - boolean isSchool = false; // schools - - // Deciding about a part type... - for (String k : part) { - if (k.matches("^[Uu][Nn][Ii].*")) { // Starts with "uni" case and locale independent - isUniversity = true; - } - if (k.matches("^[Tt][Ee][Cc][Hh].*")) { // Starts with "tech" case and locale independent - isTechnology = true; - } - if (StandardField.SCHOOL.getName().equalsIgnoreCase(k)) { - isSchool = true; - } - if (k.matches("^[Dd][EeIi][Pp].*") || k.matches("^[Ll][Aa][Bb].*")) { // Starts with "dep"/"dip"/"lab", case and locale independent - isDepartment = true; - } - } - if (isTechnology) { - isUniversity = false; // technology institute isn't university :-) - } - - // University part looks like: Uni[NameOfTheUniversity] - // - // If university is detected than the previous part is suggested - // as department - if (isUniversity) { + if (tokenTypes.contains(Institution.UNIVERSITY)) { StringBuilder universitySB = new StringBuilder(); + // University part looks like: Uni[NameOfTheUniversity] universitySB.append("Uni"); - for (String k : part) { - if (!k.matches("^[Uu][Nn][Ii].*")) { + for (String k : tokenParts) { + if (!"uni".regionMatches(true, 0, k, 0, 3)) { universitySB.append(k); } } university = universitySB.toString(); + // If university is detected than the previous part is suggested + // as department if ((index > 0) && (department == null)) { - department = parts[index - 1]; + department = institutionNameTokens[index - 1]; } - + } else if ((tokenTypes.contains(Institution.SCHOOL) + || tokenTypes.contains(Institution.DEPARTMENT)) + && institutionNameTokens.length > 1) { // School is an abbreviation of all the words beginning with a // capital letter excluding: department, school and faculty words. - // - // Explicitly defined department part is build the same way as - // school - } else if (isSchool || isDepartment) { StringBuilder schoolSB = new StringBuilder(); StringBuilder departmentSB = new StringBuilder(); - for (String k : part) { - if (!k.matches("^[Dd][EeIi][Pp].*") && !StandardField.SCHOOL.getName().equalsIgnoreCase(k) - && !"faculty".equalsIgnoreCase(k) - && !(k.replaceAll(STARTING_CAPITAL_PATTERN, "").isEmpty())) { - if (isSchool) { - schoolSB.append(k.replaceAll(STARTING_CAPITAL_PATTERN, "")); + for (String k : tokenParts) { + if (noOtherInstitutionKeyWord(k)) { + if (tokenTypes.contains(Institution.SCHOOL)) { + schoolSB.append(NOT_CAPITAL_FIRST_CHARACTER.matcher(k).replaceAll("")); } - if (isDepartment) { - departmentSB.append(k.replaceAll(STARTING_CAPITAL_PATTERN, "")); + // Explicitly defined department part is build the same way as school + if (tokenTypes.contains(Institution.DEPARTMENT)) { + departmentSB.append(NOT_CAPITAL_FIRST_CHARACTER.matcher(k).replaceAll("")); } } } - if (isSchool) { + if (tokenTypes.contains(Institution.SCHOOL)) { school = schoolSB.toString(); } - if (isDepartment) { + if (tokenTypes.contains(Institution.DEPARTMENT)) { department = departmentSB.toString(); } - // A part not matching university, department nor school. } else if (rest == null) { - StringBuilder restSB = new StringBuilder(); - // Less than 3 parts -> concatenate those - if (part.size() < 3) { - for (String k : part) { - restSB.append(k); - // More than 3 parts -> use 1st letter abbreviation - } + // A part not matching university, department nor school + if (tokenParts.size() >= 3) { + // If there are more than 3 parts, only keep the first character of each word + final int[] codePoints = tokenParts.stream() + .filter(Predicate.not(String::isBlank)) + .mapToInt((s) -> s.codePointAt(0)) + .toArray(); + rest = new String(codePoints, 0, codePoints.length); } else { - for (String k : part) { - k = k.replaceAll(STARTING_CAPITAL_PATTERN, ""); - if (!(k.isEmpty())) { - restSB.append(k); - } - } + rest = String.join("", tokenParts); } - rest = restSB.toString(); } } // Putting parts together. - return (university == null ? rest : university) + return (university == null ? Objects.toString(rest, "") : university) + (school == null ? "" : school) + ((department == null) || ((school != null) && department.equals(school)) ? "" : department); } + + /** + * Checks that this is not an institution keyword and has an uppercase first letter, except univ/tech key word. + * @param word to check + * @return + */ + private static boolean noOtherInstitutionKeyWord(String word) { + return !DEPARTMENTS.matcher(word).matches() + && !StandardField.SCHOOL.getName().equalsIgnoreCase(word) + && !"faculty".equalsIgnoreCase(word) + && !NOT_CAPITAL_FIRST_CHARACTER.matcher(word).replaceAll("").isEmpty(); + } + + private static List getValidInstitutionNameParts(String name) { + List nameParts = new ArrayList<>(); + List ignore = Arrays.asList("press", "the"); + + // Cleanup: remove unnecessary words. + for (String part : name.replaceAll("\\{[A-Z]+}", "").split("[ \\-_]")) { + if ((!(part.isEmpty()) // remove empty + && !ignore.contains(part.toLowerCase(Locale.ENGLISH)) // remove ignored words + && (part.charAt(part.length() - 1) != '.') + && Character.isUpperCase(part.charAt(0))) + || ((part.length() >= 3) && "uni".equalsIgnoreCase(part.substring(0, 3)))) { + nameParts.add(part); + } + } + return nameParts; + } } diff --git a/src/main/java/org/jabref/model/entry/AuthorList.java b/src/main/java/org/jabref/model/entry/AuthorList.java index 6acc67deabb..b617b792632 100644 --- a/src/main/java/org/jabref/model/entry/AuthorList.java +++ b/src/main/java/org/jabref/model/entry/AuthorList.java @@ -11,6 +11,8 @@ import java.util.WeakHashMap; import java.util.stream.Collectors; +import org.jabref.model.strings.LatexToUnicodeAdapter; + /** * This is an immutable class representing information of either author * or editor field in bibtex record. @@ -125,14 +127,18 @@ public class AuthorList { private final static Collection AVOID_TERMS_IN_LOWER_CASE = Arrays.asList("jr", "sr", "jnr", "snr", "von", "zu", "van", "der"); private final List authors; private final String[] authorsFirstFirst = new String[4]; + private final String[] authorsFirstFirstLatexFree = new String[4]; private final String[] authorsLastOnly = new String[2]; + private final String[] authorsLastOnlyLatexFree = new String[2]; private final String[] authorLastFirstAnds = new String[2]; private final String[] authorsLastFirst = new String[4]; + private final String[] authorsLastFirstLatexFree = new String[4]; private final String[] authorsLastFirstFirstLast = new String[2]; // Variables for storing computed strings, so they only need to be created once: private String authorsNatbib; private String authorsFirstFirstAnds; private String authorsAlph; + private String authorsNatbibLatexFree; /** * Creates a new list of authors. @@ -223,8 +229,8 @@ public static AuthorList parse(String authors) { * * @see AuthorList#getAsFirstLastNames */ - public static String fixAuthorFirstNameFirstCommas(String authors, boolean abbr, boolean oxfordComma) { - return AuthorList.parse(authors).getAsFirstLastNames(abbr, oxfordComma); + public static String fixAuthorFirstNameFirstCommas(String authors, boolean abbreviate, boolean oxfordComma) { + return AuthorList.parse(authors).getAsFirstLastNames(abbreviate, oxfordComma); } /** @@ -241,8 +247,8 @@ public static String fixAuthorFirstNameFirst(String authors) { * * @see AuthorList#getAsLastFirstNames */ - public static String fixAuthorLastNameFirstCommas(String authors, boolean abbr, boolean oxfordComma) { - return AuthorList.parse(authors).getAsLastFirstNames(abbr, oxfordComma); + public static String fixAuthorLastNameFirstCommas(String authors, boolean abbreviate, boolean oxfordComma) { + return AuthorList.parse(authors).getAsLastFirstNames(abbreviate, oxfordComma); } /** @@ -390,6 +396,15 @@ public String getAsNatbib() { return authorsNatbib; } + public String getAsNatbibLatexFree() { + // Check if we've computed this before: + if (authorsNatbibLatexFree != null) { + return authorsNatbibLatexFree; + } + authorsNatbibLatexFree = LatexToUnicodeAdapter.format(getAsNatbib()); + return authorsNatbibLatexFree; + } + /** * Returns the list of authors separated by commas with last name only; If * the list consists of two or more authors, "and" is inserted before the @@ -409,11 +424,11 @@ public String getAsNatbib() { * Oxford comma. */ public String getAsLastNames(boolean oxfordComma) { - int abbrInt = oxfordComma ? 0 : 1; + int abbreviationIndex = oxfordComma ? 0 : 1; // Check if we've computed this before: - if (authorsLastOnly[abbrInt] != null) { - return authorsLastOnly[abbrInt]; + if (authorsLastOnly[abbreviationIndex] != null) { + return authorsLastOnly[abbreviationIndex]; } StringBuilder result = new StringBuilder(); @@ -433,8 +448,19 @@ public String getAsLastNames(boolean oxfordComma) { result.append(getAuthor(i).getLastOnly()); } } - authorsLastOnly[abbrInt] = result.toString(); - return authorsLastOnly[abbrInt]; + authorsLastOnly[abbreviationIndex] = result.toString(); + return authorsLastOnly[abbreviationIndex]; + } + + public String getAsLastNamesLatexFree(boolean oxfordComma) { + int abbreviationIndex = oxfordComma ? 0 : 1; + + // Check if we've computed this before: + if (authorsLastOnlyLatexFree[abbreviationIndex] != null) { + return authorsLastOnlyLatexFree[abbreviationIndex]; + } + authorsLastOnlyLatexFree[abbreviationIndex] = LatexToUnicodeAdapter.format(getAsLastNames(oxfordComma)); + return authorsLastOnlyLatexFree[abbreviationIndex]; } /** @@ -460,12 +486,12 @@ public String getAsLastNames(boolean oxfordComma) { * Oxford comma. */ public String getAsLastFirstNames(boolean abbreviate, boolean oxfordComma) { - int abbrInt = abbreviate ? 0 : 1; - abbrInt += oxfordComma ? 0 : 2; + int abbreviationIndex = abbreviate ? 0 : 1; + abbreviationIndex += oxfordComma ? 0 : 2; // Check if we've computed this before: - if (authorsLastFirst[abbrInt] != null) { - return authorsLastFirst[abbrInt]; + if (authorsLastFirst[abbreviationIndex] != null) { + return authorsLastFirst[abbreviationIndex]; } StringBuilder result = new StringBuilder(); @@ -485,8 +511,21 @@ public String getAsLastFirstNames(boolean abbreviate, boolean oxfordComma) { result.append(getAuthor(i).getLastFirst(abbreviate)); } } - authorsLastFirst[abbrInt] = result.toString(); - return authorsLastFirst[abbrInt]; + authorsLastFirst[abbreviationIndex] = result.toString(); + return authorsLastFirst[abbreviationIndex]; + } + + public String getAsLastFirstNamesLatexFree(boolean abbreviate, boolean oxfordComma) { + int abbreviationIndex = abbreviate ? 0 : 1; + abbreviationIndex += oxfordComma ? 0 : 2; + + // Check if we've computed this before: + if (authorsLastFirstLatexFree[abbreviationIndex] != null) { + return authorsLastFirstLatexFree[abbreviationIndex]; + } + + authorsLastFirstLatexFree[abbreviationIndex] = LatexToUnicodeAdapter.format(getAsLastFirstNames(abbreviate, oxfordComma)); + return authorsLastFirstLatexFree[abbreviationIndex]; } @Override @@ -509,22 +548,22 @@ public String toString() { * @return formatted list of authors. */ public String getAsLastFirstNamesWithAnd(boolean abbreviate) { - int abbrInt = abbreviate ? 0 : 1; + int abbreviationIndex = abbreviate ? 0 : 1; // Check if we've computed this before: - if (authorLastFirstAnds[abbrInt] != null) { - return authorLastFirstAnds[abbrInt]; + if (authorLastFirstAnds[abbreviationIndex] != null) { + return authorLastFirstAnds[abbreviationIndex]; } - authorLastFirstAnds[abbrInt] = getAuthors().stream().map(author -> author.getLastFirst(abbreviate)) + authorLastFirstAnds[abbreviationIndex] = getAuthors().stream().map(author -> author.getLastFirst(abbreviate)) .collect(Collectors.joining(" and ")); - return authorLastFirstAnds[abbrInt]; + return authorLastFirstAnds[abbreviationIndex]; } public String getAsLastFirstFirstLastNamesWithAnd(boolean abbreviate) { - int abbrInt = abbreviate ? 0 : 1; + int abbreviationIndex = abbreviate ? 0 : 1; // Check if we've computed this before: - if (authorsLastFirstFirstLast[abbrInt] != null) { - return authorsLastFirstFirstLast[abbrInt]; + if (authorsLastFirstFirstLast[abbreviationIndex] != null) { + return authorsLastFirstFirstLast[abbreviationIndex]; } StringBuilder result = new StringBuilder(); @@ -536,8 +575,8 @@ public String getAsLastFirstFirstLastNamesWithAnd(boolean abbreviate) { } } - authorsLastFirstFirstLast[abbrInt] = result.toString(); - return authorsLastFirstFirstLast[abbrInt]; + authorsLastFirstFirstLast[abbreviationIndex] = result.toString(); + return authorsLastFirstFirstLast[abbreviationIndex]; } /** @@ -555,29 +594,29 @@ public String getAsLastFirstFirstLastNamesWithAnd(boolean abbreviate) { * Smith and P. Black Brown"

  • * * - * @param abbr whether to abbreivate first names. + * @param abbreviate whether to abbreivate first names. * @param oxfordComma Whether to put a comma before the and at the end. * @return formatted list of authors. * @see serial comma for an detailed explaination about the * Oxford comma. */ - public String getAsFirstLastNames(boolean abbr, boolean oxfordComma) { + public String getAsFirstLastNames(boolean abbreviate, boolean oxfordComma) { - int abbrInt = abbr ? 0 : 1; - abbrInt += oxfordComma ? 0 : 2; + int abbreviationIndex = abbreviate ? 0 : 1; + abbreviationIndex += oxfordComma ? 0 : 2; // Check if we've computed this before: - if (authorsFirstFirst[abbrInt] != null) { - return authorsFirstFirst[abbrInt]; + if (authorsFirstFirst[abbreviationIndex] != null) { + return authorsFirstFirst[abbreviationIndex]; } StringBuilder result = new StringBuilder(); if (!isEmpty()) { - result.append(getAuthor(0).getFirstLast(abbr)); + result.append(getAuthor(0).getFirstLast(abbreviate)); int i = 1; while (i < (getNumberOfAuthors() - 1)) { result.append(", "); - result.append(getAuthor(i).getFirstLast(abbr)); + result.append(getAuthor(i).getFirstLast(abbreviate)); i++; } if ((getNumberOfAuthors() > 2) && oxfordComma) { @@ -585,11 +624,24 @@ public String getAsFirstLastNames(boolean abbr, boolean oxfordComma) { } if (getNumberOfAuthors() > 1) { result.append(" and "); - result.append(getAuthor(i).getFirstLast(abbr)); + result.append(getAuthor(i).getFirstLast(abbreviate)); } } - authorsFirstFirst[abbrInt] = result.toString(); - return authorsFirstFirst[abbrInt]; + authorsFirstFirst[abbreviationIndex] = result.toString(); + return authorsFirstFirst[abbreviationIndex]; + } + + public String getAsFirstLastNamesLatexFree(boolean abbreviate, boolean oxfordComma) { + int abbreviationIndex = abbreviate ? 0 : 1; + abbreviationIndex += oxfordComma ? 0 : 2; + + // Check if we've computed this before: + if (authorsFirstFirstLatexFree[abbreviationIndex] != null) { + return authorsFirstFirstLatexFree[abbreviationIndex]; + } + + authorsFirstFirstLatexFree[abbreviationIndex] = LatexToUnicodeAdapter.format(getAsFirstLastNames(abbreviate, oxfordComma)); + return authorsFirstFirstLatexFree[abbreviationIndex]; } /** @@ -660,7 +712,7 @@ public String getForAlphabetization() { return authorsAlph; } - public void addAuthor(String first, String firstabbr, String von, String last, String jr) { - authors.add(new Author(first, firstabbr, von, last, jr)); + public void addAuthor(String first, String firstNameAbbreviation, String von, String last, String jr) { + authors.add(new Author(first, firstNameAbbreviation, von, last, jr)); } } diff --git a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java index 6d42a9d7ac6..e7d44365ec2 100644 --- a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java +++ b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java @@ -1,10 +1,12 @@ package org.jabref.logic.bibtexkeypattern; +import java.util.Collections; import java.util.Optional; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.fileformat.BibtexParser; +import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -52,17 +54,38 @@ void setUp() { importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); } + static String generateKey(BibEntry entry, String pattern) { + return generateKey(entry, pattern, new BibDatabase()); + } + + static String generateKey(BibEntry entry, String pattern, BibDatabase database) { + GlobalBibtexKeyPattern keyPattern = new GlobalBibtexKeyPattern(Collections.emptyList()); + keyPattern.setDefaultValue("[" + pattern + "]"); + BibtexKeyPatternPreferences patternPreferences = new BibtexKeyPatternPreferences( + false, + false, + false, + BibtexKeyPatternPreferences.KeySuffix.SECOND_WITH_A, + "", + "", + DEFAULT_UNWANTED_CHARACTERS, + keyPattern, + ','); + + return new BibtexKeyGenerator(keyPattern, database, patternPreferences).generateKey(entry); + } + @Test void testAndInAuthorName() throws ParseException { Optional entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Simon Holland}}", importFormatPreferences, fileMonitor); assertEquals("Holland", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testCrossrefAndInAuthorNames() throws Exception { + void testCrossrefAndInAuthorNames() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -73,7 +96,7 @@ void testCrossrefAndInAuthorNames() throws Exception { database.insertEntry(entry2); assertEquals("Holland", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "auth", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -82,12 +105,12 @@ void testAndAuthorNames() throws ParseException { String bibtexString = "@ARTICLE{whatevery, author={Mari D. Herland and Mona-Iren Hauge and Ingeborg M. Helgeland}}"; Optional entry = BibtexParser.singleFromString(bibtexString, importFormatPreferences, fileMonitor); assertEquals("HerlandHaugeHelgeland", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "authors3", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "authors3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testCrossrefAndAuthorNames() throws Exception { + void testCrossrefAndAuthorNames() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -98,7 +121,7 @@ void testCrossrefAndAuthorNames() throws Exception { database.insertEntry(entry2); assertEquals("HerlandHaugeHelgeland", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "authors3", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "authors3", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -107,7 +130,7 @@ void testSpecialLatexCharacterInAuthorName() throws ParseException { Optional entry = BibtexParser.singleFromString( "@ARTICLE{kohn, author={Simon Popovi\\v{c}ov\\'{a}}}", importFormatPreferences, fileMonitor); assertEquals("Popovicova", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @@ -121,73 +144,73 @@ void testMakeLabelAndCheckLegalKeys() throws ParseException { Optional entry0 = BibtexParser.singleFromString( "@ARTICLE{kohn, author={Andreas Köning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Koe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Áöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Aoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Éöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Eoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Íöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Ioe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ĺöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Loe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ńöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Noe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Óöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Ooe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ŕöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Roe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Śöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Soe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Úöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Uoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ýöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Yoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Źöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Zoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @@ -199,57 +222,56 @@ void testMakeLabelAndCheckLegalKeysAccentGrave() throws ParseException { Optional entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Àöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Aoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Èöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Eoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ìöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Ioe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Òöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Ooe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andreas Ùöning}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Uoe", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Oraib Al-Ketan}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("AlK", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andrés D'Alessandro}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("DAl", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andrés Aʹrnold}, year={2000}}", importFormatPreferences, fileMonitor); assertEquals("Arn", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + BibtexKeyGenerator.cleanKey(generateKey(entry0.orElse(null), "auth3", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } /** - * Tests if checkLegalKey replaces Non-ASCII chars. There are quite a few chars that should be replaced. Perhaps + * Tests if cleanKey replaces Non-ASCII chars. There are quite a few chars that should be replaced. Perhaps * there is a better method than the current. - * - * @see BibtexKeyGenerator#checkLegalKey(String) + * @see BibtexKeyGenerator#cleanKey(String, String) */ @Test void testCheckLegalKey() { @@ -330,12 +352,12 @@ void testUniversity() throws ParseException { Optional entry = BibtexParser.singleFromString( "@ARTICLE{kohn, author={{Link{\\\"{o}}ping University}}}", importFormatPreferences, fileMonitor); assertEquals("UniLinkoeping", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testcrossrefUniversity() throws Exception { + void testcrossrefUniversity() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -346,7 +368,7 @@ void testcrossrefUniversity() throws Exception { database.insertEntry(entry2); assertEquals("UniLinkoeping", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "auth", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -356,12 +378,12 @@ void testDepartment() throws ParseException { "@ARTICLE{kohn, author={{Link{\\\"{o}}ping University, Department of Electrical Engineering}}}", importFormatPreferences, fileMonitor); assertEquals("UniLinkoepingEE", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testcrossrefDepartment() throws Exception { + void testcrossrefDepartment() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -372,7 +394,7 @@ void testcrossrefDepartment() throws Exception { database.insertEntry(entry2); assertEquals("UniLinkoepingEE", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "auth", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -382,12 +404,32 @@ void testSchool() throws ParseException { "@ARTICLE{kohn, author={{Link{\\\"{o}}ping University, School of Computer Engineering}}}", importFormatPreferences, fileMonitor); assertEquals("UniLinkoepingCE", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", + new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); + } + + @Test + void generateKeyAbbreviateCorporateAuthorDepartmentWithoutAcademicInstitute() throws ParseException { + Optional entry = BibtexParser.singleFromString( + "@ARTICLE{null, author={{Department of Localhost NullGenerators}}}", + importFormatPreferences, fileMonitor); + assertEquals("DLN", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", + new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); + } + + @Test + void generateKeyAbbreviateCorporateAuthorSchoolWithoutAcademicInstitute() throws ParseException { + Optional entry = BibtexParser.singleFromString( + "@ARTICLE{null, author={{The School of Null}}}", + importFormatPreferences, fileMonitor); + assertEquals("SchoolNull", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testcrossrefSchool() throws Exception { + void testcrossrefSchool() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -398,7 +440,7 @@ void testcrossrefSchool() throws Exception { database.insertEntry(entry2); assertEquals("UniLinkoepingCE", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "auth", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -407,12 +449,12 @@ void testInstituteOfTechnology() throws ParseException { Optional entry = BibtexParser.singleFromString( "@ARTICLE{kohn, author={{Massachusetts Institute of Technology}}}", importFormatPreferences, fileMonitor); assertEquals("MIT", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry.get(), "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry.orElse(null), "auth", new BibDatabase()), DEFAULT_UNWANTED_CHARACTERS)); } @Test - void testcrossrefInstituteOfTechnology() throws Exception { + void testcrossrefInstituteOfTechnology() { BibDatabase database = new BibDatabase(); BibEntry entry1 = new BibEntry(); entry1.setField(StandardField.CROSSREF, "entry2"); @@ -423,7 +465,7 @@ void testcrossrefInstituteOfTechnology() throws Exception { database.insertEntry(entry2); assertEquals("MIT", - BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry1, "auth", + BibtexKeyGenerator.cleanKey(generateKey(entry1, "auth", database), DEFAULT_UNWANTED_CHARACTERS)); } @@ -709,6 +751,8 @@ void testFirstPage() { assertEquals("43", BibtexKeyGenerator.firstPage("43+")); } + @SuppressWarnings("ConstantConditions") + @Test void testFirstPageNull() { assertThrows(NullPointerException.class, () -> BibtexKeyGenerator.firstPage(null)); } @@ -731,6 +775,7 @@ void testPagePrefix() { assertEquals("", BibtexKeyGenerator.pagePrefix("43+")); } + @SuppressWarnings("ConstantConditions") @Test void testPagePrefixNull() { assertThrows(NullPointerException.class, () -> BibtexKeyGenerator.pagePrefix(null)); @@ -748,6 +793,7 @@ void testLastPage() { assertEquals("43", BibtexKeyGenerator.lastPage("43+")); } + @SuppressWarnings("ConstantConditions") @Test void testLastPageNull() { assertThrows(NullPointerException.class, () -> BibtexKeyGenerator.lastPage(null)); @@ -879,16 +925,13 @@ void keywordNKeywordsSeparatedBySpace() { BibEntry entry = new BibEntry(); entry.setField(StandardField.KEYWORDS, "w1, w2a w2b, w3"); - String result = BibtexKeyGenerator.generateKey(entry, "keyword1"); - assertEquals("w1", result); + assertEquals("w1", generateKey(entry, "keyword1")); // check keywords with space - result = BibtexKeyGenerator.generateKey(entry, "keyword2"); - assertEquals("w2aw2b", result); + assertEquals("w2aw2b", generateKey(entry, "keyword2")); // check out of range - result = BibtexKeyGenerator.generateKey(entry, "keyword4"); - assertEquals("", result); + assertEquals("", generateKey(entry, "keyword4")); } @Test @@ -902,9 +945,7 @@ void crossrefkeywordNKeywordsSeparatedBySpace() { database.insertEntry(entry1); entry2.setField(StandardField.KEYWORDS, "w1, w2a w2b, w3"); - String result = BibtexKeyGenerator.generateKey(entry1, "keyword1", database); - - assertEquals("w1", result); + assertEquals("w1", generateKey(entry1, "keyword1", database)); } @Test @@ -913,16 +954,13 @@ void keywordsNKeywordsSeparatedBySpace() { entry.setField(StandardField.KEYWORDS, "w1, w2a w2b, w3"); // all keywords - String result = BibtexKeyGenerator.generateKey(entry, "keywords"); - assertEquals("w1w2aw2bw3", result); + assertEquals("w1w2aw2bw3", generateKey(entry, "keywords")); // check keywords with space - result = BibtexKeyGenerator.generateKey(entry, "keywords2"); - assertEquals("w1w2aw2b", result); + assertEquals("w1w2aw2b", generateKey(entry, "keywords2")); // check out of range - result = BibtexKeyGenerator.generateKey(entry, "keywords55"); - assertEquals("w1w2aw2bw3", result); + assertEquals("w1w2aw2bw3", generateKey(entry, "keywords55")); } @Test @@ -936,9 +974,7 @@ void crossrefkeywordsNKeywordsSeparatedBySpace() { database.insertEntry(entry1); entry2.setField(StandardField.KEYWORDS, "w1, w2a w2b, w3"); - String result = BibtexKeyGenerator.generateKey(entry1, "keywords", database); - - assertEquals("w1w2aw2bw3", result); + assertEquals("w1w2aw2bw3", generateKey(entry1, "keywords", database)); } @Test @@ -965,8 +1001,8 @@ void testCheckLegalNullInNullOut() { void testApplyModifiers() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "Green Scheduling of Whatever"); - assertEquals("GSo", BibtexKeyGenerator.generateKey(entry, "shorttitleINI")); - assertEquals("GreenSchedulingWhatever", BibtexKeyGenerator.generateKey(entry, "shorttitle", + assertEquals("GSo", generateKey(entry, "shorttitleINI")); + assertEquals("GreenSchedulingWhatever", generateKey(entry, "shorttitle", new BibDatabase())); } @@ -981,7 +1017,7 @@ void testcrossrefShorttitle() { database.insertEntry(entry1); entry2.setField(StandardField.TITLE, "Green Scheduling of Whatever"); - assertEquals("GreenSchedulingWhatever", BibtexKeyGenerator.generateKey(entry1, "shorttitle", + assertEquals("GreenSchedulingWhatever", generateKey(entry1, "shorttitle", database)); } @@ -996,105 +1032,105 @@ void testcrossrefShorttitleInitials() { database.insertEntry(entry1); entry2.setField(StandardField.TITLE, "Green Scheduling of Whatever"); - assertEquals("GSo", BibtexKeyGenerator.generateKey(entry1, "shorttitleINI", database)); + assertEquals("GSo", generateKey(entry1, "shorttitleINI", database)); } @Test - void generateKeyStripsColonFromTitle() throws Exception { + void generateKeyStripsColonFromTitle() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "Green Scheduling of: Whatever"); - assertEquals("GreenSchedulingOfWhatever", BibtexKeyGenerator.generateKey(entry, "title")); + assertEquals("GreenSchedulingOfWhatever", generateKey(entry, "title")); } @Test - void generateKeyStripsApostropheFromTitle() throws Exception { + void generateKeyStripsApostropheFromTitle() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "Green Scheduling of `Whatever`"); - assertEquals("GreenSchedulingofWhatever", BibtexKeyGenerator.generateKey(entry, "title")); + assertEquals("GreenSchedulingofWhatever", generateKey(entry, "title")); } @Test - void generateKeyWithOneModifier() throws Exception { + void generateKeyWithOneModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "The Interesting Title"); - assertEquals("theinterestingtitle", BibtexKeyGenerator.generateKey(entry, "title:lower")); + assertEquals("theinterestingtitle", generateKey(entry, "title:lower")); } @Test - void generateKeyWithTwoModifiers() throws Exception { + void generateKeyWithTwoModifiers() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "The Interesting Title"); - assertEquals("theinterestingtitle", BibtexKeyGenerator.generateKey(entry, "title:lower:(_)")); + assertEquals("theinterestingtitle", generateKey(entry, "title:lower:(_)")); } @Test - void generateKeyWithTitleCapitalizeModifier() throws Exception { + void generateKeyWithTitleCapitalizeModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "the InTeresting title longer than THREE words"); - assertEquals("TheInterestingTitleLongerThanThreeWords", BibtexKeyGenerator.generateKey(entry, "title:capitalize")); + assertEquals("TheInterestingTitleLongerThanThreeWords", generateKey(entry, "title:capitalize")); } @Test - void generateKeyWithShortTitleCapitalizeModifier() throws Exception { + void generateKeyWithShortTitleCapitalizeModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "the InTeresting title longer than THREE words"); - assertEquals("InterestingTitleLonger", BibtexKeyGenerator.generateKey(entry, "shorttitle:capitalize")); + assertEquals("InterestingTitleLonger", generateKey(entry, "shorttitle:capitalize")); } @Test - void generateKeyWithTitleTitleCaseModifier() throws Exception { + void generateKeyWithTitleTitleCaseModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "A title WITH some of The key words"); - assertEquals("ATitlewithSomeoftheKeyWords", BibtexKeyGenerator.generateKey(entry, "title:titlecase")); + assertEquals("ATitlewithSomeoftheKeyWords", generateKey(entry, "title:titlecase")); } @Test - void generateKeyWithShortTitleTitleCaseModifier() throws Exception { + void generateKeyWithShortTitleTitleCaseModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "the InTeresting title longer than THREE words"); - assertEquals("InterestingTitleLonger", BibtexKeyGenerator.generateKey(entry, "shorttitle:titlecase")); + assertEquals("InterestingTitleLonger", generateKey(entry, "shorttitle:titlecase")); } @Test - void generateKeyWithTitleSentenceCaseModifier() throws Exception { + void generateKeyWithTitleSentenceCaseModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.TITLE, "A title WITH some of The key words"); - assertEquals("Atitlewithsomeofthekeywords", BibtexKeyGenerator.generateKey(entry, "title:sentencecase")); + assertEquals("Atitlewithsomeofthekeywords", generateKey(entry, "title:sentencecase")); } @Test - void generateKeyWithAuthUpperYearShortTitleCapitalizeModifier() throws Exception { + void generateKeyWithAuthUpperYearShortTitleCapitalizeModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, AUTHOR_STRING_FIRSTNAME_FULL_LASTNAME_FULL_COUNT_1); entry.setField(StandardField.YEAR, "2019"); entry.setField(StandardField.TITLE, "the InTeresting title longer than THREE words"); - assertEquals("NEWTON2019InterestingTitleLonger", BibtexKeyGenerator.generateKey(entry, "[auth:upper][year][shorttitle:capitalize]")); + assertEquals("NEWTON2019InterestingTitleLonger", generateKey(entry, "[auth:upper][year][shorttitle:capitalize]")); } @Test - void generateKeyWithYearAuthUpperTitleSentenceCaseModifier() throws Exception { + void generateKeyWithYearAuthUpperTitleSentenceCaseModifier() { BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, AUTHOR_STRING_FIRSTNAME_FULL_LASTNAME_FULL_COUNT_3); entry.setField(StandardField.YEAR, "2019"); entry.setField(StandardField.TITLE, "the InTeresting title longer than THREE words"); - assertEquals("NewtonMaxwellEtAl_2019_TheInterestingTitleLongerThanThreeWords", BibtexKeyGenerator.generateKey(entry, "[authors2]_[year]_[title:capitalize]")); + assertEquals("NewtonMaxwellEtAl_2019_TheInterestingTitleLongerThanThreeWords", generateKey(entry, "[authors2]_[year]_[title:capitalize]")); } @Test - void generateKeyWithMinusInCitationStyleOutsideAField() throws Exception { + void generateKeyWithMinusInCitationStyleOutsideAField() { BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, AUTHOR_STRING_FIRSTNAME_FULL_LASTNAME_FULL_COUNT_1); entry.setField(StandardField.YEAR, "2019"); - assertEquals("Newton-2019", BibtexKeyGenerator.generateKey(entry, "[auth]-[year]")); + assertEquals("Newton-2019", generateKey(entry, "[auth]-[year]")); } @Test - void generateKeyWithWithFirstNCharacters() throws Exception { + void generateKeyWithWithFirstNCharacters() { BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, "Newton, Isaac"); entry.setField(StandardField.YEAR, "2019"); - assertEquals("newt-2019", BibtexKeyGenerator.generateKey(entry, "[auth4:lower]-[year]")); + assertEquals("newt-2019", generateKey(entry, "[auth4:lower]-[year]")); } } diff --git a/src/test/java/org/jabref/model/entry/AuthorListTest.java b/src/test/java/org/jabref/model/entry/AuthorListTest.java index 77bb79b5b7d..eda59858ac6 100644 --- a/src/test/java/org/jabref/model/entry/AuthorListTest.java +++ b/src/test/java/org/jabref/model/entry/AuthorListTest.java @@ -7,15 +7,58 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class AuthorListTest { + /* + Examples are similar to page 4 in + [BibTeXing by Oren Patashnik](https://ctan.org/tex-archive/biblio/bibtex/contrib/doc/) + */ + private static final String MUHAMMAD_ALKHWARIZMI = "Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}}"; + private static final String CORRADO_BOHM = "Corrado B{\\\"o}hm"; + private static final String KURT_GODEL = "Kurt G{\\\"{o}}del"; + private static final String BANU_MOSA = "{The Ban\\={u} M\\={u}s\\={a} brothers}"; + public static int size(String bibtex) { return AuthorList.parse(bibtex).getNumberOfAuthors(); } + private static AuthorList emptyAuthor() { + return AuthorList.parse(""); + } + + private static AuthorList oneAuthorWithLatex() { + return AuthorList.parse(MUHAMMAD_ALKHWARIZMI); + } + + private static AuthorList twoAuthorsWithLatex() { + return AuthorList.parse(MUHAMMAD_ALKHWARIZMI + " and " + CORRADO_BOHM); + } + + private static AuthorList threeAuthorsWithLatex() { + return AuthorList.parse(MUHAMMAD_ALKHWARIZMI + " and " + CORRADO_BOHM + " and " + KURT_GODEL); + } + + private static AuthorList oneInstitutionWithLatex() { + return AuthorList.parse(BANU_MOSA); + } + + private static AuthorList oneInstitutionWithParanthesisAtStart() { + return AuthorList.parse("{{\\L{}}ukasz Micha\\l{}}"); + } + + private static AuthorList twoInstitutionsWithLatex() { + return AuthorList.parse(BANU_MOSA + " and " + BANU_MOSA); + } + + private static AuthorList mixedAuthorAndInstituteWithLatex() { + return AuthorList.parse(BANU_MOSA + " and " + CORRADO_BOHM); + } + @Test public void testFixAuthorNatbib() { assertEquals("", AuthorList.fixAuthorNatbib("")); @@ -26,9 +69,62 @@ public void testFixAuthorNatbib() { .fixAuthorNatbib("John von Neumann and John Smith and Black Brown, Peter")); // Is not cached! - assertTrue(AuthorList - .fixAuthorNatbib("John von Neumann and John Smith and Black Brown, Peter").equals(AuthorList - .fixAuthorNatbib("John von Neumann and John Smith and Black Brown, Peter"))); + assertSame(AuthorList + .fixAuthorNatbib("John von Neumann and John Smith and Black Brown, Peter"), AuthorList + .fixAuthorNatbib("John von Neumann and John Smith and Black Brown, Peter")); + } + + @Test + public void getAsNatbibLatexFreeEmptyAuthorStringForEmptyInput() { + assertEquals("", emptyAuthor().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeCachesLatexFreeString() { + String cachedString = oneAuthorWithLatex().getAsNatbibLatexFree(); + assertSame(cachedString, oneAuthorWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeOneAuthorNameFromLatex() { + assertEquals("al-Khwārizmī", + oneAuthorWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeTwoAuthorNamesFromLatex() { + assertEquals("al-Khwārizmī and Böhm", + twoAuthorsWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeAuthorEtAlFromLatex() { + assertEquals("al-Khwārizmī et al.", + threeAuthorsWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeOneInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeTwoInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeUnicodeMixedAuthorsFromLatex() { + assertEquals("The Banū Mūsā brothers and Böhm", + mixedAuthorAndInstituteWithLatex().getAsNatbibLatexFree()); + } + + @Test + public void getAsNatbibLatexFreeOneInstitutionWithParanthesisAtStart() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsNatbibLatexFree()); } @Test @@ -36,7 +132,7 @@ public void testGetAuthorList() { // Test caching in authorCache. AuthorList al = AuthorList.parse("John Smith"); assertEquals(al, AuthorList.parse("John Smith")); - assertFalse(al.equals(AuthorList.parse("Smith"))); + assertNotEquals(al, AuthorList.parse("Smith")); } @Test @@ -52,10 +148,9 @@ public void testFixAuthorFirstNameFirstCommas() { false)); // Check caching - assertTrue(AuthorList.fixAuthorFirstNameFirstCommas( - "John von Neumann and John Smith and Black Brown, Peter", true, false).equals( - AuthorList - .fixAuthorFirstNameFirstCommas("John von Neumann and John Smith and Black Brown, Peter", true, false))); + assertEquals(AuthorList.fixAuthorFirstNameFirstCommas( + "John von Neumann and John Smith and Black Brown, Peter", true, false), AuthorList + .fixAuthorFirstNameFirstCommas("John von Neumann and John Smith and Black Brown, Peter", true, false)); assertEquals("John Smith and Peter Black Brown", AuthorList .fixAuthorFirstNameFirstCommas("John Smith and Black Brown, Peter", false, false)); @@ -83,10 +178,9 @@ public void testFixAuthorFirstNameFirstCommas() { true)); // Check caching - assertTrue(AuthorList.fixAuthorFirstNameFirstCommas( - "John von Neumann and John Smith and Black Brown, Peter", true, true).equals( - AuthorList - .fixAuthorFirstNameFirstCommas("John von Neumann and John Smith and Black Brown, Peter", true, true))); + assertEquals(AuthorList.fixAuthorFirstNameFirstCommas( + "John von Neumann and John Smith and Black Brown, Peter", true, true), AuthorList + .fixAuthorFirstNameFirstCommas("John von Neumann and John Smith and Black Brown, Peter", true, true)); assertEquals("John Smith and Peter Black Brown", AuthorList .fixAuthorFirstNameFirstCommas("John Smith and Black Brown, Peter", false, true)); @@ -106,6 +200,111 @@ public void testFixAuthorFirstNameFirstCommas() { "John Peter von Neumann", true, true)); } + @Test + public void getAsFirstLastNamesLatexFreeEmptyAuthorStringForEmptyInputAbbr() { + assertEquals("", emptyAuthor().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeCachesLatexFreeStringAbbr() { + String cachedString = oneAuthorWithLatex().getAsFirstLastNamesLatexFree(true, false); + assertSame(cachedString, oneAuthorWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeOneAuthorNameFromLatexAbbr() { + assertEquals("M. al-Khwārizmī", + oneAuthorWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeTwoAuthorNamesFromLatexAbbr() { + assertEquals("M. al-Khwārizmī and C. Böhm", + twoAuthorsWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeThreeUnicodeAuthorsFromLatexAbbr() { + assertEquals("M. al-Khwārizmī, C. Böhm and K. Gödel", + threeAuthorsWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeOneInsitutionNameFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers", oneInstitutionWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeTwoInsitutionNameFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeMixedAuthorsFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers and C. Böhm", + mixedAuthorAndInstituteWithLatex().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeOneInstitutionWithParanthesisAtStartAbbr() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsFirstLastNamesLatexFree(true, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeEmptyAuthorStringForEmptyInput() { + assertEquals("", emptyAuthor().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeCachesLatexFreeString() { + String cachedString = oneAuthorWithLatex().getAsFirstLastNamesLatexFree(false, false); + assertSame(cachedString, oneAuthorWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeOneAuthorNameFromLatex() { + assertEquals("Muḥammad al-Khwārizmī", + oneAuthorWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeTwoAuthorNamesFromLatex() { + assertEquals("Muḥammad al-Khwārizmī and Corrado Böhm", + twoAuthorsWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeThreeUnicodeAuthorsFromLatex() { + assertEquals("Muḥammad al-Khwārizmī, Corrado Böhm and Kurt Gödel", + threeAuthorsWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeOneInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeTwoInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeUnicodeMixedAuthorsFromLatex() { + assertEquals("The Banū Mūsā brothers and Corrado Böhm", + mixedAuthorAndInstituteWithLatex().getAsFirstLastNamesLatexFree(false, false)); + } + + @Test + public void getAsFirstLastNamesLatexFreeOneInstitutionWithParanthesisAtStart() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsFirstLastNamesLatexFree(false, false)); + } + @Test public void testFixAuthorFirstNameFirst() { assertEquals("John Smith", AuthorList.fixAuthorFirstNameFirst("John Smith")); @@ -120,9 +319,9 @@ public void testFixAuthorFirstNameFirst() { .fixAuthorFirstNameFirst("von Last, Jr. III, First")); // Check caching - assertTrue(AuthorList - .fixAuthorFirstNameFirst("John von Neumann and John Smith and Black Brown, Peter").equals(AuthorList - .fixAuthorFirstNameFirst("John von Neumann and John Smith and Black Brown, Peter"))); + assertEquals(AuthorList + .fixAuthorFirstNameFirst("John von Neumann and John Smith and Black Brown, Peter"), AuthorList + .fixAuthorFirstNameFirst("John von Neumann and John Smith and Black Brown, Peter")); } @Test @@ -141,7 +340,7 @@ public void testFixAuthorLastNameFirstCommasNoComma() { // Check caching assertEquals(a, b); - assertTrue(a.equals(b)); + assertSame(a, b); assertEquals("Smith, John and Black Brown, Peter", AuthorList.fixAuthorLastNameFirstCommas("John Smith and Black Brown, Peter", false, false)); @@ -174,7 +373,7 @@ public void testFixAuthorLastNameFirstCommasOxfordComma() { // Check caching assertEquals(a, b); - assertTrue(a.equals(b)); + assertSame(a, b); assertEquals("Smith, John and Black Brown, Peter", AuthorList .fixAuthorLastNameFirstCommas("John Smith and Black Brown, Peter", false, true)); @@ -192,6 +391,218 @@ public void testFixAuthorLastNameFirstCommasOxfordComma() { "John Peter von Neumann", true, true)); } + @Test + public void getAsLastFirstNamesLatexFreeEmptyAuthorStringForEmptyInputAbbr() { + assertEquals("", emptyAuthor().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeCachesLatexFreeStringAbbr() { + String cachedString = oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, false); + assertSame(cachedString, oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneAuthorNameFromLatexAbbr() { + assertEquals("al-Khwārizmī, M.", + oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoAuthorNamesFromLatexAbbr() { + assertEquals("al-Khwārizmī, M. and Böhm, C.", + twoAuthorsWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeThreeUnicodeAuthorsFromLatexAbbr() { + assertEquals("al-Khwārizmī, M., Böhm, C. and Gödel, K.", + threeAuthorsWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneInsitutionNameFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoInsitutionNameFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeMixedAuthorsFromLatexAbbr() { + assertEquals("The Banū Mūsā brothers and Böhm, C.", + mixedAuthorAndInstituteWithLatex().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeOneInstitutionWithParanthesisAtStartAbbr() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsLastFirstNamesLatexFree(true, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeEmptyAuthorStringForEmptyInput() { + assertEquals("", emptyAuthor().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeCachesLatexFreeString() { + String cachedString = oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, false); + assertSame(cachedString, oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneAuthorNameFromLatex() { + assertEquals("al-Khwārizmī, Muḥammad", + oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoAuthorNamesFromLatex() { + assertEquals("al-Khwārizmī, Muḥammad and Böhm, Corrado", + twoAuthorsWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeThreeUnicodeAuthorsFromLatex() { + assertEquals("al-Khwārizmī, Muḥammad, Böhm, Corrado and Gödel, Kurt", + threeAuthorsWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeMixedAuthorsFromLatex() { + assertEquals("The Banū Mūsā brothers and Böhm, Corrado", + mixedAuthorAndInstituteWithLatex().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeOneInstitutionWithParanthesisAtStart() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsLastFirstNamesLatexFree(false, false)); + } + + @Test + public void getAsLastFirstNamesLatexFreeEmptyAuthorStringForEmptyInputAbbrOxfordComma() { + assertEquals("", emptyAuthor().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeCachesLatexFreeStringAbbrOxfordComma() { + String cachedString = oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, true); + assertSame(cachedString, oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneAuthorNameFromLatexAbbrOxfordComma() { + assertEquals("al-Khwārizmī, M.", + oneAuthorWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoAuthorNamesFromLatexAbbrOxfordComma() { + assertEquals("al-Khwārizmī, M. and Böhm, C.", + twoAuthorsWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeThreeUnicodeAuthorsFromLatexAbbrOxfordComma() { + assertEquals("al-Khwārizmī, M., Böhm, C., and Gödel, K.", + threeAuthorsWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneInsitutionNameFromLatexAbbrOxfordComma() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoInsitutionNameFromLatexAbbrOxfordComma() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeMixedAuthorsFromLatexAbbrOxfordComma() { + assertEquals("The Banū Mūsā brothers and Böhm, C.", + mixedAuthorAndInstituteWithLatex().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeOneInstitutionWithParanthesisAtStartAbbrOxfordComma() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsLastFirstNamesLatexFree(true, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeEmptyAuthorStringForEmptyInputOxfordComma() { + assertEquals("", emptyAuthor().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeCachesLatexFreeStringOxfordComma() { + String cachedString = oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, true); + assertSame(cachedString, oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneAuthorNameFromLatexOxfordComma() { + assertEquals("al-Khwārizmī, Muḥammad", + oneAuthorWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoAuthorNamesFromLatexOxfordComma() { + assertEquals("al-Khwārizmī, Muḥammad and Böhm, Corrado", + twoAuthorsWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeThreeUnicodeAuthorsFromLatexOxfordComma() { + assertEquals("al-Khwārizmī, Muḥammad, Böhm, Corrado, and Gödel, Kurt", + threeAuthorsWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeOneInsitutionNameFromLatexOxfordComma() { + assertEquals("The Banū Mūsā brothers", + oneInstitutionWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeTwoInsitutionNameFromLatexOxfordComma() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeUnicodeMixedAuthorsFromLatexOxfordComma() { + assertEquals("The Banū Mūsā brothers and Böhm, Corrado", + mixedAuthorAndInstituteWithLatex().getAsLastFirstNamesLatexFree(false, true)); + } + + @Test + public void getAsLastFirstNamesLatexFreeOneInstitutionWithParanthesisAtStartOxfordComma() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsLastFirstNamesLatexFree(false, true)); + } + @Test public void testFixAuthorLastNameFirst() { @@ -208,9 +619,9 @@ public void testFixAuthorLastNameFirst() { assertEquals("von Last, Jr, First", AuthorList .fixAuthorLastNameFirst("von Last, Jr ,First")); - assertTrue(AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter").equals(AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter"))); + assertEquals(AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter"), AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter")); // Test Abbreviation == false assertEquals("Smith, John", AuthorList.fixAuthorLastNameFirst("John Smith", false)); @@ -225,10 +636,9 @@ public void testFixAuthorLastNameFirst() { assertEquals("von Last, Jr, First", AuthorList.fixAuthorLastNameFirst( "von Last, Jr ,First", false)); - assertTrue(AuthorList.fixAuthorLastNameFirst( - "John von Neumann and John Smith and Black Brown, Peter", false).equals( - AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", false))); + assertEquals(AuthorList.fixAuthorLastNameFirst( + "John von Neumann and John Smith and Black Brown, Peter", false), AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", false)); // Test Abbreviate == true assertEquals("Smith, J.", AuthorList.fixAuthorLastNameFirst("John Smith", true)); @@ -243,10 +653,9 @@ public void testFixAuthorLastNameFirst() { assertEquals("von Last, Jr, F.", AuthorList.fixAuthorLastNameFirst("von Last, Jr ,First", true)); - assertTrue(AuthorList.fixAuthorLastNameFirst( - "John von Neumann and John Smith and Black Brown, Peter", true).equals( - AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", true))); + assertEquals(AuthorList.fixAuthorLastNameFirst( + "John von Neumann and John Smith and Black Brown, Peter", true), AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", true)); } @Test @@ -257,10 +666,9 @@ public void testFixAuthorLastNameOnlyCommas() { assertEquals("Smith", AuthorList.fixAuthorLastNameOnlyCommas("John Smith", false)); assertEquals("Smith", AuthorList.fixAuthorLastNameOnlyCommas("Smith, Jr, John", false)); - assertTrue(AuthorList.fixAuthorLastNameOnlyCommas( - "John von Neumann and John Smith and Black Brown, Peter", false).equals( - AuthorList - .fixAuthorLastNameOnlyCommas("John von Neumann and John Smith and Black Brown, Peter", false))); + assertEquals(AuthorList.fixAuthorLastNameOnlyCommas( + "John von Neumann and John Smith and Black Brown, Peter", false), AuthorList + .fixAuthorLastNameOnlyCommas("John von Neumann and John Smith and Black Brown, Peter", false)); assertEquals("von Neumann, Smith and Black Brown", AuthorList .fixAuthorLastNameOnlyCommas( @@ -270,16 +678,59 @@ public void testFixAuthorLastNameOnlyCommas() { assertEquals("Smith", AuthorList.fixAuthorLastNameOnlyCommas("John Smith", true)); assertEquals("Smith", AuthorList.fixAuthorLastNameOnlyCommas("Smith, Jr, John", true)); - assertTrue(AuthorList.fixAuthorLastNameOnlyCommas( - "John von Neumann and John Smith and Black Brown, Peter", true).equals( - AuthorList - .fixAuthorLastNameOnlyCommas("John von Neumann and John Smith and Black Brown, Peter", true))); + assertEquals(AuthorList.fixAuthorLastNameOnlyCommas( + "John von Neumann and John Smith and Black Brown, Peter", true), AuthorList + .fixAuthorLastNameOnlyCommas("John von Neumann and John Smith and Black Brown, Peter", true)); assertEquals("von Neumann, Smith, and Black Brown", AuthorList .fixAuthorLastNameOnlyCommas( "John von Neumann and John Smith and Black Brown, Peter", true)); } + @Test + public void getAsLastNamesLatexFreeCachesLatexFreeString() { + String cachedString = oneAuthorWithLatex().getAsLastNamesLatexFree(false); + assertSame(cachedString, oneAuthorWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeOneAuthorNameFromLatex() { + assertEquals("al-Khwārizmī", oneAuthorWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeTwoAuthorNamesFromLatex() { + assertEquals("al-Khwārizmī and Böhm", twoAuthorsWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeThreeUnicodeAuthorsFromLatex() { + assertEquals("al-Khwārizmī, Böhm and Gödel", threeAuthorsWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeOneInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers", oneInstitutionWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeTwoInsitutionNameFromLatex() { + assertEquals("The Banū Mūsā brothers and The Banū Mūsā brothers", + twoInstitutionsWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeUnicodeMixedAuthorsFromLatex() { + assertEquals("The Banū Mūsā brothers and Böhm", + mixedAuthorAndInstituteWithLatex().getAsLastNamesLatexFree(false)); + } + + @Test + public void getAsLastNamesLatexFreeOneInstitutionWithParanthesisAtStart() { + assertEquals("Łukasz Michał", + oneInstitutionWithParanthesisAtStart().getAsLastNamesLatexFree(false)); + } + @Test public void testFixAuthorForAlphabetization() { assertEquals("Smith, J.", AuthorList.fixAuthorForAlphabetization("John Smith")); @@ -409,7 +860,7 @@ public void testGetAuthorsNatbib() { // Test caching AuthorList al = AuthorList .parse("John von Neumann and John Smith and Black Brown, Peter"); - assertTrue(al.getAsNatbib().equals(al.getAsNatbib())); + assertEquals(al.getAsNatbib(), al.getAsNatbib()); } @Test @@ -654,6 +1105,36 @@ public void parseNameWithBraces() throws Exception { assertEquals(new AuthorList(expected), AuthorList.parse("H{e}lene Fiaux")); } + @Test + public void parseFirstNameFromFirstAuthorMultipleAuthorsWithLatexNames() throws Exception { + assertEquals("Mu{\\d{h}}ammad", + twoAuthorsWithLatex().getAuthor(0).getFirst().orElse(null)); + } + + @Test + public void parseFirstNameFromSecondAuthorMultipleAuthorsWithLatexNames() throws Exception { + assertEquals("Corrado", + twoAuthorsWithLatex().getAuthor(1).getFirst().orElse(null)); + } + + @Test + public void parseLastNameFromFirstAuthorMultipleAuthorsWithLatexNames() throws Exception { + assertEquals("al-Khw{\\={a}}rizm{\\={i}}", + twoAuthorsWithLatex().getAuthor(0).getLast().orElse(null)); + } + + @Test + public void parseLastNameFromSecondAuthorMultipleAuthorsWithLatexNames() throws Exception { + assertEquals("B{\\\"o}hm", + twoAuthorsWithLatex().getAuthor(1).getLast().orElse(null)); + } + + @Test + public void parseInstitutionAuthorWithLatexNames() throws Exception { + assertEquals("The Ban\\={u} M\\={u}s\\={a} brothers", + oneInstitutionWithLatex().getAuthor(0).getLast().orElse(null)); + } + /** * This tests the issue described at https://github.com/JabRef/jabref/pull/2669#issuecomment-288519458 */