/* * Copyright 2013-2014 Odysseus Software GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.musicmount.builder.impl; import java.text.CollationKey; import java.text.Collator; import java.util.Comparator; import java.util.HashMap; import org.musicmount.builder.model.Titled; /** *Comparator for <code>Titled</code> objects. * * @param <T> titled type */ public class TitledComparator<T extends Titled> implements Comparator<T> { private final Collator collator; private final String[] sortTitlePrefixes; private final String defaultTitle; private final Comparator<? super T> secondaryItemComparator; private final HashMap<T, CollationKey> collationKeys = new HashMap<>(); /** * @param localStrings locale and sort title prefixes ('a', 'the', ...) * @param defaultTitle used when <code>titled.getTitle() == null</code> * @param secondaryItemComparator used to compare items with equal titles (may be <code>null</code>) */ public TitledComparator(LocalStrings localStrings, final String defaultTitle, final Comparator<? super T> secondaryItemComparator) { this.collator = Collator.getInstance(localStrings.getLocale()); this.collator.setStrength(Collator.SECONDARY); this.collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); this.sortTitlePrefixes = localStrings.getSortTitlePrefixes(); this.defaultTitle = defaultTitle; this.secondaryItemComparator = secondaryItemComparator; } @Override public int compare(T o1, T o2) { int result = collationKey(o1).compareTo(collationKey(o2)); if (result == 0 && secondaryItemComparator != null) { result = secondaryItemComparator.compare(o1, o2); } return result; } String calculateSortTitle(T titled) { String title = titled.getTitle() == null ? defaultTitle : titled.getTitle(); for (String prefix : sortTitlePrefixes) { if (title.length() > prefix.length() && title.toUpperCase().startsWith(prefix.toUpperCase())) { String suffix = title.substring(prefix.length()).trim(); if (suffix.length() > 0) { title = suffix + ", " + title.substring(0, prefix.length()).trim(); break; } } } int letterOrDigit = 0; while (letterOrDigit < title.length()) { char c = title.charAt(letterOrDigit); if (Character.isLetter(c) || Character.isDigit(c)) { break; } letterOrDigit++; } return letterOrDigit < title.length() ? title.substring(letterOrDigit) : title; } CollationKey collationKey(T titled) { CollationKey collationKey = collationKeys.get(titled); if (collationKey == null) { collationKeys.put(titled, collationKey = collator.getCollationKey(calculateSortTitle(titled))); } return collationKey; } public String sortTitle(T titled) { return collationKey(titled).getSourceString(); } }