package net.sf.jabref.bst; import java.util.Stack; import net.sf.jabref.AuthorList; import net.sf.jabref.AuthorList.Author; import net.sf.jabref.bst.VM.BstEntry; import net.sf.jabref.bst.VM.BstFunction; /** * From Bibtex: * * "The |built_in| function {\.{format.name\$}} pops the * top three literals (they are a string, an integer, and a string * literal, in that order). The last string literal represents a * name list (each name corresponding to a person), the integer * literal specifies which name to pick from this list, and the * first string literal specifies how to format this name, as * described in the \BibTeX\ documentation. Finally, this function * pushes the formatted name. If any of the types is incorrect, it * complains and pushes the null string." * * All the pain is encapsulated in BibtexNameFormatter. :-) * */ public class FormatNameFunction implements BstFunction { VM vm; public FormatNameFunction(VM vm) { this.vm = vm; } public void execute(BstEntry context) { Stack<Object> stack = vm.getStack(); if (stack.size() < 3) { throw new VMException("Not enough operands on stack for operation format.name$"); } Object o1 = stack.pop(); Object o2 = stack.pop(); Object o3 = stack.pop(); if (!(o1 instanceof String) && !(o2 instanceof Integer) && !(o3 instanceof String)) { // warning("A string is needed for change.case$"); stack.push(""); return; } String format = (String) o1; Integer name = (Integer) o2; String names = (String) o3; if (names != null){ AuthorList a = AuthorList.getAuthorList(names); if (name.intValue() > a.size()){ throw new VMException("Author Out of Bounds. Number " + name + " invalid for " + names); } Author author = a.getAuthor(name.intValue() - 1); stack.push(BibtexNameFormatter.formatName(author, format, vm)); } else { stack.push(""); } } }