/* 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; import java.util.Comparator; /** * This implementation of Comparator takes care of most of the details of sorting BibTeX entries in JabRef. * It is structured as a node in a linked list of comparators, where each node can contain a link to a * new comparator that decides the ordering (by recursion) if this one can't find a difference. The next * node, if any, is given at construction time, and an arbitrary number of nodes can be included. * If the entries are equal by this comparator, and there is no next entry, the entries' unique IDs will * decide the ordering. Consequently, this comparator can never return 0 unless the entries are the same * object. */ public class EntryComparator implements Comparator<BibtexEntry> { String sortField; boolean descending, binary=false, numeric; Comparator<BibtexEntry> next; public EntryComparator(boolean binary, boolean desc, String field, Comparator<BibtexEntry> next) { this.binary = binary; this.sortField = field; this.descending = desc; this.next = next; this.numeric = BibtexFields.isNumeric(sortField); } public EntryComparator(boolean binary, boolean desc, String field) { this.binary = binary; this.sortField = field; this.descending = desc; this.next = null; this.numeric = BibtexFields.isNumeric(sortField); } public int compare(BibtexEntry e1, BibtexEntry e2) throws ClassCastException { if (e1 == e2) return 0; //Util.pr("EntryComparator: "+e1+" : "+e2); Object f1 = e1.getField(sortField), f2 = e2.getField(sortField); if (binary) { // We just separate on set and unset fields: if (f1 != null) return (f2 == null) ? -1 : (next != null ? next.compare(e1, e2) : idCompare(e1, e2)); else return (f2 == null) ? (next != null ? next.compare(e1, e2) : idCompare(e1, e2)) : 1; } // If the field is author or editor, we rearrange names so they are // sorted according to last name. if (sortField.equals("author") || sortField.equals("editor")) { if (f1 != null) f1 = AuthorList.fixAuthorForAlphabetization((String)f1).toLowerCase(); //ImportFormatReader.fixAuthor_lastNameFirst((String)f1); if (f2 != null) f2 = AuthorList.fixAuthorForAlphabetization((String)f2).toLowerCase(); //ImportFormatReader.fixAuthor_lastNameFirst((String)f2); } else if (sortField.equals(GUIGlobals.TYPE_HEADER)) { // Sort by type. f1 = e1.getType().getName(); f2 = e2.getType().getName(); } else if (numeric) { try { Integer i1 = Integer.parseInt((String)f1); Integer i2 = Integer.parseInt((String)f2); // Ok, parsing was successful. Update f1 and f2: f1 = i1; f2 = i2; } catch (NumberFormatException ex) { // Parsing failed. Give up treating these as numbers. // TODO: should we check which of them failed, and sort based on that? } } if ((f1 == null) && (f2 == null)) return (next != null ? next.compare(e1, e2) : idCompare(e1, e2)); if ((f1 != null) && (f2 == null)) return -1; if ((f1 == null) && (f2 != null)) return 1; int result = 0; //String ours = ((String)e1.getField(sortField)).toLowerCase(), // theirs = ((String)e2.getField(sortField)).toLowerCase(); if ((f1 instanceof Integer) && (f2 instanceof Integer)) { result = -(((Integer) f1).compareTo((Integer) f2)); } else if (f2 instanceof Integer) { Integer f1AsInteger = new Integer(f1.toString()); result = -((f1AsInteger).compareTo((Integer) f2)); } else if (f1 instanceof Integer) { Integer f2AsInteger = new Integer(f2.toString()); result = -(((Integer) f1).compareTo(f2AsInteger)); } else { String ours = ((String) f1).toLowerCase(), theirs = ((String) f2).toLowerCase(); int comp = ours.compareTo(theirs); result = -comp; } if (result != 0) return (descending ? result : -result); // Primary sort. if (next != null) return next.compare(e1, e2); // Secondary sort if existent. else { return idCompare(e1, e2); // If still equal, we use the unique IDs. } } private int idCompare(BibtexEntry b1, BibtexEntry b2) { return ((b1.getId())).compareTo((b2.getId())); } }