/* * Created on Mar 29, 2003 * * @author henkel@cs.colorado.edu * */ package bibtex.expansions; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import bibtex.dom.BibtexAbstractEntry; import bibtex.dom.BibtexAbstractValue; import bibtex.dom.BibtexEntry; import bibtex.dom.BibtexFile; import bibtex.dom.BibtexString; /** * This expander expands the crossreferences defined by the crossref fields - * you should run the MacroReferenceExpander first. * * @author henkel */ public final class CrossReferenceExpander extends AbstractExpander implements Expander { /** Equivalent to CrossReferenceExpander(true) */ public CrossReferenceExpander() { this(true); } /** * @param throwAllExpansionExceptions * Setting this to true means that all exceptions will be thrown * immediately. Otherwise, the expander will skip over things it * can't expand and you can use getExceptions to retrieve the * exceptions later */ public CrossReferenceExpander(boolean throwAllExpansionExceptions) { super(throwAllExpansionExceptions); } /** * Note: If you don't use the MacroReferenceExpander first, this function * may lead to inconsistent macro references. * * If you use the flag throwAllExpansionExceptions set to false, you can * retrieve all the exceptions using getExceptions() * * @param bibtexFile */ public void expand(BibtexFile bibtexFile) throws ExpansionException { HashMap entryKey2Entry = new HashMap(); ArrayList entriesWithCrossReference = new ArrayList(); for (Iterator entryIt = bibtexFile.getEntries().iterator(); entryIt.hasNext();) { BibtexAbstractEntry abstractEntry = (BibtexAbstractEntry) entryIt.next(); if (!(abstractEntry instanceof BibtexEntry)) continue; BibtexEntry entry = (BibtexEntry) abstractEntry; entryKey2Entry.put(entry.getEntryKey().toLowerCase(), abstractEntry); if (entry.getFields().containsKey("crossref")) { entriesWithCrossReference.add(entry); } } for (Iterator entryIt = entriesWithCrossReference.iterator(); entryIt.hasNext();) { BibtexEntry entry = (BibtexEntry) entryIt.next(); String crossrefKey = ((BibtexString) entry.getFields().get("crossref")).getContent().toLowerCase(); entry.undefineField("crossref"); BibtexEntry crossrefEntry = (BibtexEntry) entryKey2Entry.get(crossrefKey); if (crossrefEntry == null) throwExpansionException("Crossref key not found: \"" + crossrefKey + "\""); if (crossrefEntry.getFields().containsKey("crossref")) throwExpansionException( "Nested crossref: \"" + crossrefKey + "\" is crossreferenced but crossreferences itself \"" + ((BibtexString) crossrefEntry.getFields().get("crossref")).getContent() + "\""); Map entryFields = entry.getFields(); Map crossrefFields = crossrefEntry.getFields(); for (Iterator fieldIt = crossrefFields.keySet().iterator(); fieldIt.hasNext();) { String key = (String) fieldIt.next(); if (!entryFields.containsKey(key)) { entry.setField(key, (BibtexAbstractValue) crossrefFields.get(key)); } } } finishExpansion(); } }