content: // This file is part of AceWiki.
  // Copyright 2008-2013, AceWiki developers.
  // 
  // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
  // Lesser General Public License as published by the Free Software Foundation, either version 3 of
  // the License, or (at your option) any later version.
  // 
  // AceWiki 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
  // Lesser General Public License for more details.
  // 
  // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
  // not, see http://www.gnu.org/licenses/.
  
  package ch.uzh.ifi.attempto.preditor;
  
  import java.text.Collator;
  import java.util.Comparator;
  import java.util.HashSet;
  import java.util.Set;
  
  import ch.uzh.ifi.attempto.echocomp.LocaleResources;
  
  /**
   * This class represents the default comparator to sort menu items in the menus of the predictive
   * editor. Prefixes can be set that are ignored for comparison. By default, these prefixes are
   * "the ", "a " and "and " plus their capizalized versions.
   * 
   * @author Tobias Kuhn
   */
  public class DefaultMenuItemComparator implements Comparator<MenuItem> {
  	
  	private Set<String> prefixes = new HashSet<String>();
  	private Collator collator;
  	
  	/**
  	 * Creates a new default comparator for menu items.
  	 */
  	public DefaultMenuItemComparator() {
  		collator = LocaleResources.getCollator();
  		prefixes.add("the ");
  		prefixes.add("The ");
  		prefixes.add("a ");
  		prefixes.add("A ");
  		prefixes.add("an ");
  		prefixes.add("An ");
  	}
  
  	public int compare(MenuItem m1, MenuItem m2) {
  		String s1 = m1.getText();
  		String s2 = m2.getText();
  		
  		// Special menu items come before other items:
  		if (m1 instanceof SpecialMenuItem && !(m2 instanceof SpecialMenuItem)) {
  			return -1;
  		} else if (!(m1 instanceof SpecialMenuItem) && m2 instanceof SpecialMenuItem) {
  			return 1;
  		}
  		
  		// Highlighted items come before others:
  		if (m1.isHighlighted() && !m2.isHighlighted()) {
  			return -1;
  		} else if (!m1.isHighlighted() && m2.isHighlighted()) {
  			return 1;
  		}
  		
  		// Special menu items are not examined further:
  		if (m1 instanceof SpecialMenuItem && m2 instanceof SpecialMenuItem) {
  			return collator.compare(s1, s2);
  		}
  		
  		// Certain prefixes are ignored for comparison:
  		String s1n = null;
  		String s2n = null;
  		String p1 = "";
  		String p2 = "";
  		for (String p : prefixes) {
  			if (s1.startsWith(p)) {
  				if (s1n == null || s1n.length() > s1.length() - p.length()) {
  					p1 = s1.substring(0, p.length());
  					s1n = s1.substring(p.length());
  				}
  			}
  			if (s2.startsWith(p)) {
  				if (s2n == null || s2n.length() > s2.length() - p.length()) {
  					p2 = s2.substring(0, p.length());
  					s2n = s2.substring(p.length());
  				}
  			}
  		}
  		if (s1n != null) s1 = s1n;
  		if (s2n != null) s2 = s2n;
  		
  		int comp;
  		
  		// For items that are equal apart from trailing digits, the integer value of these trailing
  		// digits is used for comparison:
  		if (s1.replaceFirst("[0-9]*$", "").equals(s2.replaceFirst("[0-9]*$", ""))) {
  			int i1 = 0;
  			int i2 = 0;
  			try {
  				i1 = Integer.parseInt(s1.replaceFirst("^.*?([0-9]*)$", "$1"));
  			} catch (NumberFormatException ex) {}
  			try {
  				i2 = Integer.parseInt(s2.replaceFirst("^.*?([0-9]*)$", "$1"));
  			} catch (NumberFormatException ex) {}
  			comp = i1 - i2;
  		} else {
  			comp = collator.compare(s1, s2);
  		}
  		
  		if (comp == 0) {
  			return collator.compare(p1, p2);
  		} else {
  			return comp;
  		}
  	}
  	
  	/**
  	 * Adds a prefix.
  	 * 
  	 * @param prefix The prefix to be added.
  	 */
  	public void addPrefix(String prefix) {
  		prefixes.add(prefix);
  	}
  	
  	/**
  	 * Sets the prefixes.
  	 * 
  	 * @param prefixes The set of prefixes.
  	 */
  	public void setPrefixes(Set<String> prefixes) {
  		this.prefixes.clear();
  		this.prefixes.addAll(prefixes);
  	}
  
  }
  