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 }