b363528281a8fbf9656b61ecc4762d8c38ff6a9a
[debian/jabref.git] / src / java / net / sf / jabref / EntryComparator.java
1 /*
2 Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
3
4 All programs in this directory and
5 subdirectories are published under the GNU General Public License as
6 described below.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or (at
11 your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA
22
23 Further information about the GNU GPL is available at:
24 http://www.gnu.org/copyleft/gpl.ja.html
25
26 */
27
28 package net.sf.jabref;
29
30 import java.util.Comparator;
31
32 /**
33  * This implementation of Comparator takes care of most of the details of sorting BibTeX entries in JabRef.
34  * It is structured as a node in a linked list of comparators, where each node can contain a link to a
35  * new comparator that decides the ordering (by recursion) if this one can't find a difference. The next
36  * node, if any, is given at construction time, and an arbitrary number of nodes can be included.
37  * If the entries are equal by this comparator, and there is no next entry, the entries' unique IDs will
38  * decide the ordering. Consequently, this comparator can never return 0 unless the entries are the same
39  * object.
40  */
41 public class EntryComparator implements Comparator {
42
43     String sortField;
44     boolean descending, binary=false;
45     Comparator next;
46
47     public EntryComparator(boolean binary, boolean desc, String field, Comparator next) {
48         this.binary = binary;
49         this.sortField = field;
50         this.descending = desc;
51         this.next = next;
52     }
53
54     public EntryComparator(boolean binary, boolean desc, String field) {
55         this.binary = binary;
56         this.sortField = field;
57         this.descending = desc;
58         this.next = null;
59     }
60
61
62     public int compare(Object o1, Object o2) throws ClassCastException {
63       //if (o1 == null) Util.pr("o1 == null");
64      //if (o2 == null) Util.pr("o2 == null");
65
66     /*  The explicit instanceof test is unnecessary, since the
67          explicit casts below will throw ClassCastException anyway
68          if there is trouble.
69
70      if (!(o1 instanceof BibtexEntry) || !(o2 instanceof BibtexEntry))
71        throw new ClassCastException("Trouble comparing objects: "+o1.toString()+"\n\n"+o2.toString());*/
72
73     BibtexEntry e1 = (BibtexEntry)o1,
74         e2 = (BibtexEntry)o2;
75
76     if (e1 == e2)
77         return 0;
78
79     //Util.pr("EntryComparator: "+e1+" : "+e2);
80     Object f1 = e1.getField(sortField),
81         f2 = e2.getField(sortField);
82
83     if (binary) {
84         // We just separate on set and unset fields:
85         if (f1 != null)
86             return (f2 == null) ? -1 :
87                     (next != null ? next.compare(o1, o2) : idCompare(e1, e2));
88         else
89             return (f2 == null) ? (next != null ? next.compare(o1, o2) : idCompare(e1, e2))
90                     : 1;
91     }
92
93     // If the field is author or editor, we rearrange names so they are
94     // sorted according to last name.
95     if (sortField.equals("author") || sortField.equals("editor")) {
96         if (f1 != null)
97         f1 = AuthorList.fixAuthorForAlphabetization((String)f1);
98                 //ImportFormatReader.fixAuthor_lastNameFirst((String)f1);
99         if (f2 != null)
100         f2 = AuthorList.fixAuthorForAlphabetization((String)f2);
101                 //ImportFormatReader.fixAuthor_lastNameFirst((String)f2);
102     } else if (sortField.equals(GUIGlobals.TYPE_HEADER)) {
103           // Sort by type.
104           f1 = e1.getType().getName();
105           f2 = e2.getType().getName();
106         }
107
108         if ((f1 == null) && (f2 == null)) return (next != null ? next.compare(o1, o2) : idCompare(e1, e2));
109         if ((f1 != null) && (f2 == null)) return -1;
110         if ((f1 == null) && (f2 != null)) return 1;
111
112         int result = 0;
113
114         //String ours = ((String)e1.getField(sortField)).toLowerCase(),
115         //    theirs = ((String)e2.getField(sortField)).toLowerCase();
116         if ((f1 instanceof Integer) && (f2 instanceof Integer)) {
117                 result = -(((Integer) f1).compareTo((Integer) f2));
118         } else if (f2 instanceof Integer) {
119                 Integer f1AsInteger = new Integer(f1.toString());
120                 result = -((f1AsInteger).compareTo((Integer) f2));
121         } else if (f1 instanceof Integer) {
122                 Integer f2AsInteger = new Integer(f2.toString());
123                 result = -(((Integer) f1).compareTo(f2AsInteger));
124         } else {
125                 String ours = ((String) f1).toLowerCase(),
126                 theirs = ((String) f2).toLowerCase();
127                 int comp = ours.compareTo(theirs);
128                 result = -comp;
129         }
130         if (result != 0)
131             return (descending ? result : -result); // Primary sort.
132         if (next != null)
133             return next.compare(o1, o2); // Secondary sort if existent.
134         else {
135
136         return idCompare(e1, e2); // If still equal, we use the unique IDs.
137     }
138     }
139
140     private int idCompare(BibtexEntry b1, BibtexEntry b2) {
141     return ((String)(b1.getId())).compareTo((String)(b2.getId()));
142     }
143
144 }