package net.sf.jabref.export.layout.format; import net.sf.jabref.AuthorList; import net.sf.jabref.export.layout.AbstractParamLayoutFormatter; import java.util.ArrayList; import java.util.regex.Pattern; /** * Versatile author name formatter that takes arguments to control the formatting style. */ public class Authors extends AbstractParamLayoutFormatter { /* AuthorSort = [FirstFirst | LastFirst | LastFirstFirstFirst] AuthorAbbr = [FullName | Initials | FirstInitial | MiddleInitial | InitialsNoSpace | LastName] AuthorSep = [Comma | And | Colon | Semicolon | Sep=<string>] AuthorLastSep = [And | Comma | Colon | Semicolon | Amp | Oxford | LastSep=<string>] AuthorPunc = [FullPunc | NoPunc | NoComma | NoPeriod] AuthorNumber = [inf | <number>] AuthorNumberEtAl = [ {1} | <number>] EtAlString = [ et al. | EtAl=<string>] */ static ArrayList<String> authorOrder = new ArrayList<String>(), authorAbbr = new ArrayList<String>(), authorPunc = new ArrayList<String>(), separators = new ArrayList<String>(), lastSeparators = new ArrayList<String>(); static Pattern numberPattern = Pattern.compile("[0-9]+"); static { authorOrder.add("firstfirst"); authorOrder.add("lastfirst"); authorOrder.add("lastfirstfirstfirst"); authorAbbr.add("fullname"); authorAbbr.add("initials"); authorAbbr.add("firstinitial"); authorAbbr.add("middleinitial"); authorAbbr.add("lastname"); authorAbbr.add("initialsnospace"); authorPunc.add("fullpunc"); authorPunc.add("nopunc"); authorPunc.add("nocomma"); authorPunc.add("noperiod"); separators.add("comma"); separators.add("and"); separators.add("colon"); separators.add("semicolon"); separators.add("sep"); lastSeparators.add("and"); lastSeparators.add("colon"); lastSeparators.add("semicolon"); lastSeparators.add("amp"); lastSeparators.add("oxford"); lastSeparators.add("lastsep"); } final static int FIRST_FIRST = 0, LAST_FIRST = 1, LF_FF = 2; final static String COMMA = ", ", AMP = " & ", COLON = ": ", SEMICOLON = "; ", AND = " and ", OXFORD = ", and "; int flMode = FIRST_FIRST; boolean abbreviate = true, firstInitialOnly = false, middleInitial = false, lastNameOnly = false, abbrDots = true, abbrSpaces = true; boolean setSep = false; boolean setMaxAuthors = false; int maxAuthors = -1; int authorNumberEtAl = 1; String firstFirstSeparator = " ", lastFirstSeparator = ", ", separator = COMMA, lastSeparator = AND, etAlString = " et al.", jrSeparator = " "; public void setArgument(String arg) { String[] parts = parseArgument(arg); for (int i = 0; i < parts.length; i++) { int index = parts[i].indexOf("="); if (index > 0) { String key = parts[i].substring(0, index); String value = parts[i].substring(index+1); handleArgument(key, value); } else handleArgument(parts[i], ""); } } private void handleArgument(String key, String value) { if (authorOrder.contains(key.trim().toLowerCase())) { if (comp(key, "FirstFirst")) flMode = FIRST_FIRST; else if (comp(key, "LastFirst")) flMode = LAST_FIRST; else if (comp(key, "LastFirstFirstFirst")) flMode = LF_FF; } else if (authorAbbr.contains(key.trim().toLowerCase())) { if (comp(key, "FullName")) { abbreviate = false; } else if (comp(key, "Initials")) { abbreviate = true; firstInitialOnly = false; } else if (comp(key, "FirstInitial")) { abbreviate = true; firstInitialOnly = true; } else if (comp(key, "MiddleInitial")) { abbreviate = true; middleInitial = true; } else if (comp(key, "LastName")) { lastNameOnly = true; } else if (comp(key, "InitialsNoSpace")) { abbreviate = true; abbrSpaces = false; } } else if (authorPunc.contains(key.trim().toLowerCase())) { if (comp(key, "FullPunc")) { abbrDots = true; lastFirstSeparator = ", "; } else if (comp(key, "NoPunc")) { abbrDots = false; lastFirstSeparator = " "; } else if (comp(key, "NoComma")) { abbrDots = true; lastFirstSeparator = " "; } else if (comp(key, "NoPeriod")) { abbrDots = false; lastFirstSeparator = ", "; } } // AuthorSep = [Comma | And | Colon | Semicolon | sep=<string>] // AuthorLastSep = [And | Comma | Colon | Semicolon | Amp | Oxford | lastsep=<string>] else if (separators.contains(key.trim().toLowerCase()) || lastSeparators.contains(key.trim().toLowerCase())) { if (comp(key, "Comma")) { if (!setSep) { separator = COMMA; setSep = true; } else lastSeparator = COMMA; } else if (comp(key, "And")) { if (!setSep) { separator = AND; setSep = true; } else lastSeparator = AND; } else if (comp(key, "Colon")) { if (!setSep) { separator = COLON; setSep = true; } else lastSeparator = COLON; } else if (comp(key, "Semicolon")) { if (!setSep) { separator = SEMICOLON; setSep = true; } else lastSeparator = SEMICOLON; } else if (comp(key, "Oxford")) { lastSeparator = OXFORD; } else if (comp(key, "Amp")) { lastSeparator = AMP; } else if (comp(key, "Sep") && (value.length() > 0)) { separator = value; setSep = true; } else if (comp(key, "LastSep") && (value.length() > 0)) { lastSeparator = value; } } else if (key.trim().toLowerCase().equals("etal") && (value.length() > 0)) { etAlString = value; } else if (numberPattern.matcher(key.trim()).matches()) { // Just a number: int num = Integer.parseInt(key.trim()); if (!setMaxAuthors) { maxAuthors = num; setMaxAuthors = true; } else authorNumberEtAl = num; } } /** * Check for case-insensitive equality between two strings after removing * white space at the beginning and end of the first string. * @param one The first string - whitespace is trimmed * @param two The second string * @return true if the strings are deemed equal */ public boolean comp(String one, String two) { return one.trim().equalsIgnoreCase(two); } public String format(String fieldText) { StringBuilder sb = new StringBuilder(); AuthorList al = AuthorList.getAuthorList(fieldText); if ((maxAuthors < 0) || (al.size() <= maxAuthors)) { for (int i=0; i<al.size(); i++) { AuthorList.Author a = al.getAuthor(i); addSingleName(sb, a, (flMode == FIRST_FIRST) || ((flMode == LF_FF) && (i > 0))); if (i < al.size()-2) sb.append(separator); else if (i < al.size()-1) sb.append(lastSeparator); } } else { for (int i=0; i<Math.min(al.size() - 1, authorNumberEtAl); i++) { if (i > 0) sb.append(separator); addSingleName(sb, al.getAuthor(i), flMode == FIRST_FIRST); } sb.append(etAlString); } return sb.toString(); } private void addSingleName(StringBuilder sb, AuthorList.Author a, boolean firstFirst) { String firstNamePart = a.getFirst(); String lastNamePart = a.getLast(); String von = a.getVon(); if ((von != null) && (von.length() > 0)) lastNamePart = von+" "+lastNamePart; String jr = a.getJr(); if ((jr != null) && (jr.length() > 0)) lastNamePart = lastNamePart+jrSeparator+jr; if (abbreviate && (firstNamePart != null)) { firstNamePart = a.getFirstAbbr(); if (firstInitialOnly && (firstNamePart.length() > 2)) firstNamePart = firstNamePart.substring(0, 2); else if (middleInitial) { String abbr = firstNamePart; firstNamePart = a.getFirst(); int index = firstNamePart.indexOf(" "); //System.out.println(firstNamePart); //System.out.println(index); if (index >= 0) { firstNamePart = firstNamePart.substring(0, index+1); if (abbr.length() > 3) { firstNamePart = firstNamePart + abbr.substring(3); } } } if (!abbrDots) firstNamePart = firstNamePart.replaceAll("\\.", ""); if (!abbrSpaces) firstNamePart = firstNamePart.replaceAll(" ", ""); } if (lastNameOnly || (firstNamePart == null)) { sb.append(lastNamePart); } else if (firstFirst) { sb.append(firstNamePart).append(firstFirstSeparator); sb.append(lastNamePart); } else { sb.append(lastNamePart).append(lastFirstSeparator).append(firstNamePart); } } public static void main(String[] args) { Authors format = new Authors(); format.setArgument("lastfirstfirstfirst , initials, Nocomma,Amp,Semicolon,30 ,EtAl = m.fl."); System.out.println(format.format("Alfredsen, Jr, Jo Arve and Morten Omholt Alver and Yngvar von Olsen and Sebastian A. L. M. Kooijman")); } }