/* Copyright (C) 2003-2011 JabRef contributors.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.sf.jabref.oo;
import net.sf.jabref.AuthorList;
import net.sf.jabref.BibtexDatabase;
import net.sf.jabref.BibtexEntry;
import net.sf.jabref.Globals;
import net.sf.jabref.export.layout.Layout;
import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.export.layout.LayoutHelper;
import net.sf.jabref.export.layout.format.RemoveLatexCommands;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
/**
* This class embodies a bibliography formatting for OpenOffice, which is composed
* of the following elements:
*
* 1) Each OO bib entry type must have a formatting. A formatting is an array of elements, each
* of which is either a piece of constant text, an entry field value, or a tab. Each element has
* a character format associated with it.
*
* 2) Many field values (e.g. author) need to be formatted before input to OpenOffice. The style
* has the responsibility of formatting all field values. Formatting is handled by 0-n
* JabRef LayoutFormatter classes.
*
* 3) If the entries are not numbered, a citation marker must be produced for each entry. This
* operation is performed for each JabRef BibtexEntry.
*/
public class OOBibStyle implements Comparable {
public static final String UNDEFINED_CITATION_MARKER = "??";
String name = null;
SortedSet<String> journals = new TreeSet<String>();
// Formatter to be run on fields before they are used as part of citation marker:
LayoutFormatter fieldFormatter = new OOPreFormatter();
Layout defaultBibLayout;
// reference layout mapped from entry type number:
HashMap<String, Layout> bibLayout = new HashMap<String, Layout>();
HashMap properties = new HashMap();
HashMap citProperties = new HashMap();
Pattern numPattern = Pattern.compile("-?\\d+");
boolean valid = false;
final static int NONE = 0, LAYOUT = 1, PROPERTIES=2, CITATION=3, NAME=4, JOURNALS=5;
final static String LAYOUT_MRK = "LAYOUT",
PROPERTIES_MARK = "PROPERTIES",
CITATION_MARK = "CITATION",
NAME_MARK = "NAME",
JOURNALS_MARK = "JOURNALS",
DEFAULT_MARK = "default";
private File styleFile = null;
private static long styleFileModificationTime = Long.MIN_VALUE;
private String COMBINED_ENTRIES_SEPARATOR = "-";
//private Pattern quoted = Pattern.compile("\".*^\\\\\"");
private Pattern quoted = Pattern.compile("\".*\"");
public OOBibStyle(File styleFile) throws Exception {
this(new FileReader(styleFile));
this.styleFile = styleFile;
styleFileModificationTime = (styleFile).lastModified();
}
public OOBibStyle(Reader in) throws Exception {
// Set default property values:
properties.put("Title", "Bibliography");
properties.put("SortAlgorithm", "alphanumeric");
properties.put("IsSortByPosition", Boolean.FALSE);
properties.put("IsNumberEntries", Boolean.FALSE);
properties.put("BracketBefore", "[");
properties.put("BracketAfter", "]");
properties.put("ReferenceParagraphFormat", "Default");
properties.put("ReferenceHeaderParagraphFormat", "Heading 1");
// Set default properties for the citation marker:
citProperties.put("AuthorField", "author/editor");
citProperties.put("YearField", "year");
citProperties.put("MaxAuthors", 3);
citProperties.put("MaxAuthorsFirst", -1);
citProperties.put("AuthorSeparator", ", ");
citProperties.put("AuthorLastSeparator", " & ");
citProperties.put("AuthorLastSeparatorInText", null);
citProperties.put("EtAlString", " et al.");
citProperties.put("YearSeparator", ", ");
citProperties.put("InTextYearSeparator", " ");
citProperties.put("BracketBefore", "(");
citProperties.put("BracketAfter", ")");
citProperties.put("CitationSeparator", "; ");
citProperties.put("PageInfoSeparator", "; ");
citProperties.put("GroupedNumbersSeparator", "-");
citProperties.put("MinimumGroupingCount", 3);
citProperties.put("FormatCitations", Boolean.FALSE);
citProperties.put("CitationCharacterFormat", "Default");
citProperties.put("ItalicCitations", Boolean.FALSE);
citProperties.put("BoldCitations", Boolean.FALSE);
citProperties.put("SuperscriptCitations", Boolean.FALSE);
citProperties.put("SubscriptCitations", Boolean.FALSE);
citProperties.put("MultiCiteChronological", Boolean.TRUE);
citProperties.put("BibtexKeyCitations", Boolean.FALSE);
citProperties.put("ItalicEtAl", Boolean.FALSE);
initialize(in);
}
public String getName() {
return name;
}
public File getFile() {
return styleFile;
}
public Set<String> getJournals() {
return Collections.unmodifiableSet(journals);
}
private void initialize(Reader in) throws IOException {
name = null;
readFormatFile(in);
}
/**
* If this style was initialized from a file on disk, reload the style
* if the file has been modified since it was read.
* @throws Exception
*/
public void ensureUpToDate() throws Exception {
if (!isUpToDate())
reload();
}
/**
* If this style was initialized from a file on disk, reload the style
* information.
* @throws Exception
*/
public void reload() throws Exception {
if (styleFile != null) {
styleFileModificationTime = (styleFile).lastModified();
initialize(new FileReader(styleFile));
}
}
/**
* If this style was initialized from a file on disk, check whether the file
* is unmodified since initialization.
* @return true if the file has not been modified, false otherwise.
*/
public boolean isUpToDate() {
if (styleFile != null) {
return styleFile.lastModified() == styleFileModificationTime;
}
else return true;
}
private void readFormatFile(Reader in) throws IOException {
// First read all the contents of the file:
StringBuffer sb = new StringBuffer();
int c;
while ((c = in.read()) != -1) {
sb.append((char)c);
}
// Break into separate lines:
String[] lines = sb.toString().split("\n");
int mode = NONE;
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if ((line.length() > 0) && (line.charAt(line.length()-1) == '\r'))
line = line.substring(0, line.length()-1);
// Check for empty line or comment:
if ((line.trim().length() == 0) || (line.charAt(0) == '#'))
continue;
// Check if we should change mode:
if (line.equals(NAME_MARK)) {
mode = NAME;
continue;
}
else if (line.equals(LAYOUT_MRK)) {
mode = LAYOUT;
continue;
}
else if (line.equals(PROPERTIES_MARK)) {
mode = PROPERTIES;
continue;
}
else if (line.equals(CITATION_MARK)) {
mode = CITATION;
continue;
}
else if (line.equals(JOURNALS_MARK)) {
mode = JOURNALS;
continue;
}
switch (mode) {
case NAME:
if (line.trim().length() > 0)
name = line.trim();
case LAYOUT:
handleStructureLine(line);
break;
case PROPERTIES:
handlePropertiesLine(line, properties);
break;
case CITATION:
handlePropertiesLine(line, citProperties);
break;
case JOURNALS:
handleJournalsLine(line);
}
}
// Set validity boolean based on whether we found anything interesting
// in the file:
if (mode != NONE)
valid = true;
}
/**
* After initalizing this style from a file, this method can be used to check
* whether the file appeared to be a proper style file.
* @return true if the file could be parsed as a style file, false otherwise.
*/
public boolean isValid() {
return valid;
}
/**
* Parse a line providing bibliography structure information for an entry type.
* @param line The string containing the structure description.
* @throws IOException
*/
private void handleStructureLine(String line) throws IOException {
int index = line.indexOf("=");
if ((index > 0) && (index < line.length()-1)) {
String formatString = line.substring(index+1);
//System.out.println("'"+line.substring(0, index)+"' : '"+formatString+"'");
boolean setDefault = line.substring(0, index).equals(DEFAULT_MARK);
String type = line.substring(0, index);
Short typeS;
try {
/*typeS = new Short(Short.parseShort(type));
OOBibFormatParser parser = new OOBibFormatParser(new StringReader(formatString));
PropertyValue[][] layout = parser.parse();*/
Layout layout = new LayoutHelper(new StringReader(formatString)).
getLayoutFromText(Globals.FORMATTER_PACKAGE);
if (setDefault)
defaultBibLayout = layout;
else
bibLayout.put(type.toLowerCase(), layout);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* Parse a line providing a property name and value.
* @param line The line containing the formatter names.
* @throws IOException
*/
private void handlePropertiesLine(String line, HashMap map) throws IOException {
int index = line.indexOf("=");
if ((index > 0) && (index <= line.length()-1)) {
String propertyName = line.substring(0, index).trim();
String value = line.substring(index+1);
if ((value.trim().length() > 2) && quoted.matcher(value.trim()).matches())
value = value.trim().substring(1, value.trim().length()-1);
Object toSet = value;
if (numPattern.matcher(value).matches()) {
toSet = Integer.parseInt(value);
}
else if (value.toLowerCase().trim().equals("true"))
toSet = Boolean.TRUE;
else if (value.toLowerCase().trim().equals("false"))
toSet = Boolean.FALSE;
map.put(propertyName, toSet);
}
}
/**
* Parse a line providing a journal name for which this style is valid.
* @param line
* @throws IOException
*/
private void handleJournalsLine(String line) throws IOException {
if (line.trim().length() > 0)
journals.add(line.trim());
}
public Layout getReferenceFormat(String type) {
Layout l = bibLayout.get(type.toLowerCase());
if (l != null)
return l;
else
return defaultBibLayout;
}
/**
* Get the array of elements composing the reference for a given entry type.
* @param bibType The OO type number.
* @return The format definition.
public PropertyValue[][] getReferenceFormat(short bibType) {
Object o = bibLayout.get(new Short(bibType));
if (o != null)
return (PropertyValue[][])o;
else
return defaultBibLayout;
}*/
/**
* Format a number-based citation marker for the given number.
* @param number The citation numbers.
* @return The text for the citation.
*/
public String getNumCitationMarker(int[] number, int minGroupingCount, boolean inList) {
String bracketBefore = (String)citProperties.get("BracketBefore");
if (inList && (citProperties.get("BracketBeforeInList")!=null)) {
bracketBefore = (String)citProperties.get("BracketBeforeInList");
}
String bracketAfter = (String)citProperties.get("BracketAfter");
if (inList && (citProperties.get("BracketAfterInList")!=null)) {
bracketAfter = (String)citProperties.get("BracketAfterInList");
}
// Sort the numbers:
int[] lNum = new int[number.length];
for (int i = 0; i < lNum.length; i++) {
lNum[i] = number[i];
}
//Arrays.copyOf(number, number.length);
Arrays.sort(lNum);
StringBuilder sb = new StringBuilder(bracketBefore);
int combineFrom = -1, written = 0;
for (int i = 0; i < lNum.length; i++) {
int i1 = lNum[i];
if (combineFrom < 0) {
// Check if next entry is the next in the ref list:
if ((i < lNum.length-1) && (lNum[i+1] == i1+1))
combineFrom = i1;
else {
// Add single entry:
if (i>0)
sb.append((String)citProperties.get("CitationSeparator"));
sb.append(lNum[i] > 0 ? String.valueOf(lNum[i]) : UNDEFINED_CITATION_MARKER);
written++;
}
} else {
// We are building a list of combined entries.
// Check if it ends here:
if ((i == lNum.length-1) || (lNum[i+1] != i1+1)) {
if (written>0)
sb.append((String)citProperties.get("CitationSeparator"));
if ((minGroupingCount > 0) && (i1+1-combineFrom >= minGroupingCount)) {
sb.append(combineFrom);
sb.append((String)citProperties.get("GroupedNumbersSeparator"));
sb.append(i1);
written++;
}
else {
// Either we should never group, or there aren't enough
// entries in this case to group. Output all:
for (int jj=combineFrom; jj<=i1; jj++) {
sb.append(jj);
if (jj < i1)
sb.append((String)citProperties.get("CitationSeparator"));
written++;
}
}
combineFrom = -1;
}
// If it doesn't end here, just keep iterating.
}
}
sb.append(bracketAfter);
return sb.toString();
}
/**
* Format the marker for the in-text citation according to this bib style.
*
* @param entry The JabRef BibtexEntry providing the data.
* @param inParenthesis Signals whether a parenthesized citation or an in-text citation is wanted.
* @param uniquefier String to add behind the year in case it's needed to separate similar
* entries.
* @return The formatted citation.
*/
public String getCitationMarker(BibtexEntry entry, BibtexDatabase database, boolean inParenthesis,
String uniquefier, int unlimAuthors) {
return getCitationMarker(new BibtexEntry[] {entry}, database, inParenthesis, new String[] {uniquefier},
new int[] {unlimAuthors});
}
/**
* Format the marker for the in-text citation according to this bib style. Uniquefier letters are added as
* provided by the uniquefiers argument. If successive entries within the citation are uniquefied from each other,
* this method will perform a grouping of these entries.
*
* @param entries The array of JabRef BibtexEntry providing the data.
* @param inParenthesis Signals whether a parenthesized citation or an in-text citation is wanted.
* @param uniquefiers Strings to add behind the year for each entry in case it's needed to separate similar
* entries.
* @param unlimAuthors Boolean for each entry. If true, we should not use "et al" formatting regardless
* of the number of authors. Can be null to indicate that no entries should have unlimited names.
* @return The formatted citation.
*/
public String getCitationMarker(BibtexEntry[] entries, BibtexDatabase database, boolean inParenthesis,
String[] uniquefiers, int[] unlimAuthors) {
// Look for groups of uniquefied entries that should be combined in the output.
// E.g. (Olsen, 2005a, b) should be output instead of (Olsen, 2005a; Olsen, 2005b).
int piv = -1;
String tmpMarker = null;
if (uniquefiers != null) {
for (int i = 0; i < uniquefiers.length; i++) {
if ((uniquefiers[i] != null) && (uniquefiers[i].length() > 0)) {
String authorField = (String)citProperties.get("AuthorField");
int maxAuthors = (Integer)citProperties.get("MaxAuthors");
if (piv == -1) {
piv = i;
tmpMarker = getAuthorYearParenthesisMarker(new BibtexEntry[] {entries[i]}, database,
authorField,
(String)citProperties.get("YearField"),
maxAuthors,
(String)citProperties.get("AuthorSeparator"),
(String)citProperties.get("AuthorLastSeparator"),
(String)citProperties.get("EtAlString"),
(String)citProperties.get("YearSeparator"),
(String)citProperties.get("BracketBefore"),
(String)citProperties.get("BracketAfter"),
(String)citProperties.get("CitationSeparator"), null, unlimAuthors);
//System.out.println("piv="+piv+" tmpMarker='"+tmpMarker+"'");
}
else {
// See if this entry can go into a group with the previous one:
String thisMarker = getAuthorYearParenthesisMarker(new BibtexEntry[] {entries[i]}, database,
authorField,
(String)citProperties.get("YearField"),
maxAuthors,
(String)citProperties.get("AuthorSeparator"),
(String)citProperties.get("AuthorLastSeparator"),
(String)citProperties.get("EtAlString"),
(String)citProperties.get("YearSeparator"),
(String)citProperties.get("BracketBefore"),
(String)citProperties.get("BracketAfter"),
(String)citProperties.get("CitationSeparator"), null, unlimAuthors);
String author = getCitationMarkerField(entries[i], database,
authorField);
AuthorList al = AuthorList.getAuthorList(author);
//System.out.println("i="+i+" thisMarker='"+thisMarker+"'");
int prevALim = i > 0 ? unlimAuthors[i-1] : unlimAuthors[0];
if (!thisMarker.equals(tmpMarker) ||
((al.size() > maxAuthors) && (unlimAuthors[i] != prevALim))) {
// No match. Update piv to exclude the previous entry. But first check if the
// previous entry was part of a group:
if ((piv > -1) && (i > piv+1)) {
// Do the grouping:
group(entries, uniquefiers, piv, i-1, (String)citProperties.get("UniquefierSeparator"));
}
tmpMarker = thisMarker;
piv = i;
}
}
}
else {
// This entry has no uniquefier.
// Check if we just passed a group of more than one entry with uniquefier:
if ((piv > -1) && (i > piv+1)) {
// Do the grouping:
group(entries, uniquefiers, piv, i-1, (String)citProperties.get("UniquefierSeparator"));
}
piv = -1;
}
}
// Finished with the loop. See if the last entries form a group:
if (piv >= 0) {
// Do the grouping:
group(entries, uniquefiers, piv, uniquefiers.length-1, (String)citProperties.get("UniquefierSeparator"));
}
}
if (inParenthesis)
return getAuthorYearParenthesisMarker(entries, database,
(String)citProperties.get("AuthorField"),
(String)citProperties.get("YearField"),
(Integer)citProperties.get("MaxAuthors"),
(String)citProperties.get("AuthorSeparator"),
(String)citProperties.get("AuthorLastSeparator"),
(String)citProperties.get("EtAlString"),
(String)citProperties.get("YearSeparator"),
(String)citProperties.get("BracketBefore"),
(String)citProperties.get("BracketAfter"),
(String)citProperties.get("CitationSeparator"),
uniquefiers, unlimAuthors);
else {
String authorLastSeparator = (String)citProperties.get("AuthorLastSeparator");
String alsInText = (String)citProperties.get("AuthorLastSeparatorInText");
if (alsInText != null)
authorLastSeparator = alsInText;
return getAuthorYearInTextMarker(entries, database,
(String)citProperties.get("AuthorField"),
(String)citProperties.get("YearField"),
(Integer)citProperties.get("MaxAuthors"),
(String)citProperties.get("AuthorSeparator"),
authorLastSeparator,
(String)citProperties.get("EtAlString"),
(String)citProperties.get("InTextYearSeparator"),
(String)citProperties.get("BracketBefore"),
(String)citProperties.get("BracketAfter"),
(String)citProperties.get("CitationSeparator"),
uniquefiers, unlimAuthors);
}
}
/**
* Modify entry and uniqiefier arrays to facilitate a grouped presentation of uniqiefied entries.
* @param entries The entry array.
* @param uniquefiers The uniquefier array.
* @param from The first index to group (inclusive)
* @param to The last index to group (inclusive)
* @param separator The separator for the uniquefier letters.
*/
private void group(BibtexEntry[] entries, String[] uniquefiers, int from, int to, String separator) {
StringBuilder sb = new StringBuilder(uniquefiers[from]);
for (int i=from+1; i<=to; i++) {
sb.append(separator);
sb.append(uniquefiers[i]);
entries[i] = null;
}
uniquefiers[from] = sb.toString();
}
/**
* This method produces (Author, year) style citation strings in many different forms.
*
* @param entries The array of BibtexEntry to get fields from.
* @param authorField The bibtex field providing author names, e.g. "author" or "editor".
* @param yearField The bibtex field providing the year, e.g. "year".
* @param maxA The maximum number of authors to write out in full without using etal. Set to
* -1 to always write out all authors.
* @param authorSep The String to add between author names except the last two, e.g. ", ".
* @param andString The String to add between the two last author names, e.g. " & ".
* @param etAlString The String to represent authors that are not mentioned, e.g. " et al."
* @param yearSep The String to separate authors from year, e.g. "; ".
* @param startBrace The opening parenthesis.
* @param endBrace The closing parenthesis.
* @param citationSeparator The String to separate citations from each other.
* @param uniquifiers Optional parameter to separate similar citations. Elements can be null if not needed.
* @return The formatted citation.
*/
public String getAuthorYearParenthesisMarker(BibtexEntry[] entries, BibtexDatabase database,
String authorField, String yearField,
int maxA, String authorSep,
String andString, String etAlString, String yearSep,
String startBrace, String endBrace, String citationSeparator,
String[] uniquifiers, int[] unlimAuthors) {
StringBuffer sb = new StringBuffer(startBrace);
for (int j=0; j<entries.length; j++) {
int unlimA = (unlimAuthors != null ? unlimAuthors[j] : -1);
int maxAuthors = unlimA > 0 ? unlimA : maxA;
BibtexEntry entry = entries[j];
// Check if this entry has been nulled due to grouping with the previous entry(ies):
if (entry == null)
continue;
if (j > 0)
sb.append(citationSeparator);
String author = getCitationMarkerField(entry, database, authorField);
if (author != null) {
AuthorList al = AuthorList.getAuthorList(author);
sb.append(getAuthorLastName(al, 0));
if ((al.size() > 1) && ((al.size() <= maxAuthors) || (maxAuthors < 0))) {
int i=1;
while (i < al.size()-1) {
sb.append(authorSep);
sb.append(getAuthorLastName(al, i));
i++;
}
sb.append(andString);
sb.append(getAuthorLastName(al, al.size()-1));
} else if (al.size() > maxAuthors) {
sb.append(etAlString);
}
sb.append(yearSep);
}
String year = getCitationMarkerField(entry, database, yearField);
if (year != null)
sb.append(year);
if ((uniquifiers != null) && (uniquifiers[j] != null))
sb.append(uniquifiers[j]);
}
sb.append(endBrace);
return sb.toString();
}
/**
* This method produces "Author (year)" style citation strings in many different forms.
*
* @param entries The array of BibtexEntry to get fields from.
* @param authorField The bibtex field providing author names, e.g. "author" or "editor".
* @param yearField The bibtex field providing the year, e.g. "year".
* @param maxA The maximum number of authors to write out in full without using etal. Set to
* -1 to always write out all authors.
* @param authorSep The String to add between author names except the last two, e.g. ", ".
* @param andString The String to add between the two last author names, e.g. " & ".
* @param etAlString The String to represent authors that are not mentioned, e.g. " et al."
* @param yearSep The String to separate authors from year, e.g. "; ".
* @param startBrace The opening parenthesis.
* @param endBrace The closing parenthesis.
* @param uniquefiers Optional parameters to separate similar citations. Can be null if not needed.
* @return The formatted citation.
*/
public String getAuthorYearInTextMarker(BibtexEntry[] entries, BibtexDatabase database, String authorField,
String yearField, int maxA, String authorSep,
String andString, String etAlString, String yearSep,
String startBrace, String endBrace, String citationSeparator,
String[] uniquefiers, int[] unlimAuthors) {
StringBuffer sb = new StringBuffer();
for (int i=0; i<entries.length; i++) {
int unlimA = (unlimAuthors != null ? unlimAuthors[i] : -1);
int maxAuthors = unlimA > 0 ? unlimA : maxA;
// Check if this entry has been nulled due to grouping with the previous entry(ies):
if (entries[i] == null)
continue;
if (i > 0)
sb.append(citationSeparator);
String author = getCitationMarkerField(entries[i], database, authorField);
if (author != null) {
AuthorList al = AuthorList.getAuthorList(author);
if (al.size() > 0)
sb.append(getAuthorLastName(al, 0));
if ((al.size() > 1) && ((al.size() <= maxAuthors) || (maxAuthors < 0))) {
int j=1;
while (j < al.size()-1) {
sb.append(authorSep);
sb.append(getAuthorLastName(al, j));
j++;
}
sb.append(andString);
sb.append(getAuthorLastName(al, al.size()-1));
} else if (al.size() > maxAuthors) {
sb.append(etAlString);
}
sb.append(yearSep);
}
sb.append(startBrace);
String year = getCitationMarkerField(entries[i], database, yearField);
if (year != null)
sb.append(year);
if ((uniquefiers != null) && (uniquefiers[i] != null))
sb.append(uniquefiers[i]);
sb.append(endBrace);
}
return sb.toString();
}
/**
* This method looks up a field for en entry in a database. Any number of backup fields can be used
* if the primary field is empty.
* @param entry The entry.
* @param database The database the entry belongs to.
* @param field The field, or succession of fields, to look up. If backup fields are needed, separate
* field names by /. E.g. to use "author" with "editor" as backup, specify "author/editor".
* @return The resolved field content, or an empty string if the field(s) were empty.
*/
public String getCitationMarkerField(BibtexEntry entry, BibtexDatabase database, String field) {
String[] fields = field.split("/");
for (int i = 0; i < fields.length; i++) {
String s = fields[i];
String content = BibtexDatabase.getResolvedField(s, entry, database);
if ((content != null) && (content.trim().length() > 0)) {
if (fieldFormatter != null)
content = fieldFormatter.format(content);
return content;
}
}
// No luck? Return an empty string:
return "";
}
/**
* Look up the nth author and return the proper last name for citation markers.
* @param al The author list.
* @param number The number of the author to return.
* @return The author name, or an empty String if inapplicable.
*/
public String getAuthorLastName(AuthorList al, int number) {
StringBuilder sb = new StringBuilder();
if (al.size() > number) {
AuthorList.Author a = al.getAuthor(number);
if ((a.getVon() != null) && a.getVon().length() > 0) {
String von = a.getVon();
sb.append(von);
/*sb.append(von.substring(0, 1).toUpperCase());
if (von.length() > 1)
sb.append(von.substring(1));*/
sb.append(' ');
}
sb.append(a.getLast());
}
return sb.toString();
}
/**
* Take a finished citation and insert a string at the end (but inside the end bracket)
* separated by "PageInfoSeparator"
* @param citation
* @param pageInfo
* @return
*/
public String insertPageInfo(String citation, String pageInfo) {
String bracketAfter = getStringCitProperty("BracketAfter");
if (citation.endsWith(bracketAfter)) {
String first = citation.substring(0, citation.length()-bracketAfter.length());
return first+getStringCitProperty("PageInfoSeparator")+pageInfo+bracketAfter;
}
else return citation+getStringCitProperty("PageInfoSeparator")+pageInfo;
}
/**
* Convenience method for checking the property for whether we use number citations or
* author-year citations.
* @return true if we use numbered citations, false otherwise.
*/
public boolean isNumberEntries() {
return (Boolean)getProperty("IsNumberEntries");
}
/**
* Convenience method for checking the property for whether we sort the bibliography
* according to their order of appearance in the text.
* @return true to sort by appearance, false to sort alphabetically.
*/
public boolean isSortByPosition() {
return (Boolean)getProperty("IsSortByPosition");
}
/**
* Convenience method for checking whether citation markers should be italicised.
* Will only be relevant if isFormatCitations() returns true.
* @return true to indicate that citations should be in italics.
*/
public boolean isItalicCitations() {
return (Boolean)citProperties.get("ItalicCitations");
}
/**
* Convenience method for checking whether citation markers should be bold.
* Will only be relevant if isFormatCitations() returns true.
* @return true to indicate that citations should be in bold.
*/
public boolean isBoldCitations() {
return (Boolean)citProperties.get("BoldCitations");
}
/**
* Convenience method for checking whether citation markers formatted
* according to the results of the isItalicCitations() and
* isBoldCitations() methods.
* @return true to indicate that citations should be in italics.
*/
public boolean isFormatCitations() {
return (Boolean)citProperties.get("FormatCitations");
}
public boolean isBibtexKeyCiteMarkers() {
return (Boolean)citProperties.get("BibtexKeyCitations");
}
/**
* Get boolean property.
* @param key The property key
* @return the value
*/
public boolean getBooleanCitProperty(String key) {
return (Boolean)citProperties.get(key);
}
public int getIntCitProperty(String key) {
return (Integer)citProperties.get(key);
}
public String getStringCitProperty(String key) {
return (String)citProperties.get(key);
}
public String getCitationCharacterFormat() {
return (String)citProperties.get("CitationCharacterFormat");
}
/**
* Get a style property.
* @param name The property name.
* @return The property value, or null if it doesn't exist.
*/
public Object getProperty(String name) {
return properties.get(name);
}
public int compareTo(Object o) {
OOBibStyle other = (OOBibStyle)o;
return getName().compareTo(other.getName());
}
public boolean equals(Object o) {
return styleFile.equals(((OOBibStyle)o).styleFile);
}
}