001 // This file is part of AceWiki.
002 // Copyright 2008-2012, AceWiki developers.
003 //
004 // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005 // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006 // the License, or (at your option) any later version.
007 //
008 // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010 // Lesser General Public License for more details.
011 //
012 // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013 // not, see http://www.gnu.org/licenses/.
014
015 package ch.uzh.ifi.attempto.preditor;
016
017 import java.util.Comparator;
018 import java.util.HashSet;
019 import java.util.Set;
020
021 /**
022 * This class represents the default comparator to sort menu items in the menus of the predictive
023 * editor. Prefixes can be set that are ignored for comparison. By default, these prefixes are
024 * "the ", "a " and "and " plus their capizalized versions.
025 *
026 * @author Tobias Kuhn
027 */
028 public class DefaultMenuItemComparator implements Comparator<MenuItem> {
029
030 private Set<String> prefixes = new HashSet<String>();
031
032 /**
033 * Creates a new default comparator for menu items.
034 */
035 public DefaultMenuItemComparator() {
036 prefixes.add("the ");
037 prefixes.add("The ");
038 prefixes.add("a ");
039 prefixes.add("A ");
040 prefixes.add("an ");
041 prefixes.add("An ");
042 }
043
044 public int compare(MenuItem m1, MenuItem m2) {
045 String s1 = m1.getText();
046 String s2 = m2.getText();
047
048 // Special menu items come before other items:
049 if (m1 instanceof SpecialMenuItem && !(m2 instanceof SpecialMenuItem)) {
050 return -1;
051 } else if (!(m1 instanceof SpecialMenuItem) && m2 instanceof SpecialMenuItem) {
052 return 1;
053 }
054
055 // Highlighted items come before others:
056 if (m1.isHighlighted() && !m2.isHighlighted()) {
057 return -1;
058 } else if (!m1.isHighlighted() && m2.isHighlighted()) {
059 return 1;
060 }
061
062 // Special menu items are not examined further:
063 if (m1 instanceof SpecialMenuItem && m2 instanceof SpecialMenuItem) {
064 return s1.compareToIgnoreCase(s2);
065 }
066
067 // Certain prefixes are ignored for comparison:
068 String s1n = null;
069 String s2n = null;
070 String p1 = "";
071 String p2 = "";
072 for (String p : prefixes) {
073 if (s1.startsWith(p)) {
074 if (s1n == null || s1n.length() > s1.length() - p.length()) {
075 p1 = s1.substring(0, p.length());
076 s1n = s1.substring(p.length());
077 }
078 }
079 if (s2.startsWith(p)) {
080 if (s2n == null || s2n.length() > s2.length() - p.length()) {
081 p2 = s2.substring(0, p.length());
082 s2n = s2.substring(p.length());
083 }
084 }
085 }
086 if (s1n != null) s1 = s1n;
087 if (s2n != null) s2 = s2n;
088
089 int comp;
090
091 // For items that are equal apart from trailing digits, the integer value of these trailing
092 // digits is used for comparison:
093 if (s1.replaceFirst("[0-9]*$", "").equals(s2.replaceFirst("[0-9]*$", ""))) {
094 int i1 = 0;
095 int i2 = 0;
096 try {
097 i1 = Integer.parseInt(s1.replaceFirst("^.*?([0-9]*)$", "$1"));
098 } catch (NumberFormatException ex) {}
099 try {
100 i2 = Integer.parseInt(s2.replaceFirst("^.*?([0-9]*)$", "$1"));
101 } catch (NumberFormatException ex) {}
102 comp = i1 - i2;
103 } else {
104 comp = s1.compareToIgnoreCase(s2);
105 }
106
107 if (comp == 0) {
108 return p1.compareToIgnoreCase(p2);
109 } else {
110 return comp;
111 }
112 }
113
114 /**
115 * Adds a prefix.
116 *
117 * @param prefix The prefix to be added.
118 */
119 public void addPrefix(String prefix) {
120 prefixes.add(prefix);
121 }
122
123 /**
124 * Sets the prefixes.
125 *
126 * @param prefixes The set of prefixes.
127 */
128 public void setPrefixes(Set<String> prefixes) {
129 this.prefixes.clear();
130 this.prefixes.addAll(prefixes);
131 }
132
133 }