/*
* 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.Normalizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.musicmount.builder.model.Titled;
public class CollectionSection<T extends Titled> implements Comparable<CollectionSection<T>> {
private static final Character NON_LETTER_SECTION_KEY = '#';
private static final Character UNTITLED_SECTION_KEY = '?';
/**
* Partition items into index sections (capital letters plus '#').
* @param <T> titled type
* @param items items to be indexed
* @param comparator used to compare items
* @return sections ('A', ..., 'Z', '#', '?')
*/
public static <T extends Titled> Iterable<CollectionSection<T>> createIndex(Iterable<? extends T> items, TitledComparator<T> comparator) {
Map<Character, CollectionSection<T>> sectionMap = new HashMap<Character, CollectionSection<T>>();
for (T item : items) {
Character sectionKey = null;
if (item.getTitle() != null && item.getTitle().trim().length() > 0) {
char first = Normalizer.normalize(comparator.sortTitle(item), Normalizer.Form.NFD).charAt(0);
if (Character.isLetter(first) && first < 128) {
sectionKey = Character.toUpperCase(first);
} else {
sectionKey = NON_LETTER_SECTION_KEY;
}
} else { // untitled
sectionKey = UNTITLED_SECTION_KEY;
}
CollectionSection<T> section = sectionMap.get(sectionKey);
if (section == null) {
sectionMap.put(sectionKey, section = new CollectionSection<T>(sectionKey.toString()));
}
section.getItems().add(item);
}
List<CollectionSection<T>> sections = new ArrayList<CollectionSection<T>>();
for (Map.Entry<Character, CollectionSection<T>> entry : sectionMap.entrySet()) {
Collections.sort(entry.getValue().getItems(), comparator);
if (!entry.getKey().equals(NON_LETTER_SECTION_KEY) && !entry.getKey().equals(UNTITLED_SECTION_KEY)) { // append those later
sections.add(entry.getValue());
}
}
Collections.sort(sections);
if (sectionMap.containsKey(NON_LETTER_SECTION_KEY)) {
sections.add(sectionMap.get(NON_LETTER_SECTION_KEY));
}
if (sectionMap.containsKey(UNTITLED_SECTION_KEY)) {
sections.add(sectionMap.get(UNTITLED_SECTION_KEY));
}
return sections;
}
private final String title;
private final ArrayList<T> items = new ArrayList<T>();
public CollectionSection(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public ArrayList<T> getItems() {
return items;
}
public int compareTo(CollectionSection<T> o) {
if (title == o.title) {
return 0;
}
if (title == null) {
return -1;
}
if (o.title == null) {
return +1;
}
return title.compareTo(o.title);
}
}