/*******************************************************************************
* Copyright (c) 2004, 2009 Tasktop Technologies and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tasktop Technologies - initial API and implementation
* Frank Becker - improvements for bug 231336
* Julio Gesser - fixes for bug 303509
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.util;
import java.util.Comparator;
import java.util.Date;
import org.eclipse.mylyn.internal.tasks.ui.util.SortCriterion.SortKey;
import org.eclipse.mylyn.internal.tasks.ui.views.TaskKeyComparator;
import org.eclipse.mylyn.tasks.core.IRepositoryElement;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.ui.IMemento;
/**
* @author Mik Kersten
* @author Frank Becker
*/
public class TaskComparator implements Comparator<ITask> {
private final SortCriterion[] sortCriteria;
public static final int DEFAULT_SORT_DIRECTION = 1;
private static final SortKey DEFAULT_SORT_INDEX = SortKey.PRIORITY;
private static final SortKey DEFAULT_SORT_INDEX2 = SortKey.RANK;
private static final SortKey DEFAULT_SORT_INDEX3 = SortKey.DATE_CREATED;
private static final String MEMENTO_KEY_SORT = "sort"; //$NON-NLS-1$
/**
* Return a array of values to pass to taskKeyComparator.compare() for sorting
*
* @param element
* the element to sort
* @return String array[component, taskId, summary]
*/
public static String[] getSortableFromElement(IRepositoryElement element) {
final String a[] = new String[] { "", null, element.getSummary() }; //$NON-NLS-1$
if (element instanceof ITask) {
ITask task1 = (ITask) element;
if (task1.getTaskKey() != null) {
a[1] = task1.getTaskKey();
}
}
return a;
}
private final TaskKeyComparator taskKeyComparator = new TaskKeyComparator();
public static final int CRITERIA_COUNT = SortKey.values().length - 1;
public TaskComparator() {
sortCriteria = new SortCriterion[CRITERIA_COUNT];
for (int index = 0; index < CRITERIA_COUNT; index++) {
sortCriteria[index] = new SortCriterion();
}
sortCriteria[0].setKey(DEFAULT_SORT_INDEX);
sortCriteria[1].setKey(DEFAULT_SORT_INDEX2);
sortCriteria[2].setKey(DEFAULT_SORT_INDEX3);
}
public int compare(ITask element1, ITask element2) {
for (SortCriterion key : sortCriteria) {
int result;
switch (key.getKey()) {
case DATE_CREATED:
result = sortByDate(element1, element2, key.getDirection());
break;
case RANK:
result = sortByRank(element1, element2, key.getDirection());
break;
case PRIORITY:
result = sortByPriority(element1, element2, key.getDirection());
break;
case SUMMARY:
result = sortBySummary(element1, element2, key.getDirection());
break;
case TASK_ID:
result = sortByID(element1, element2, key.getDirection());
break;
case TASK_TYPE:
result = compare(element1.getTaskKind(), element2.getTaskKind(), key.getDirection());
break;
case DUE_DATE:
result = sortByDueDate(element1, element2, key.getDirection());
break;
case MODIFICATION_DATE:
result = sortByModificationDate(element1, element2, key.getDirection());
break;
default: // NONE
return 0;
}
if (result != 0) {
return result;
}
}
return 0;
}
public SortCriterion getSortCriterion(int index) {
return sortCriteria[index];
}
public void restoreState(IMemento memento) {
if (memento != null) {
for (int index = 0; index < CRITERIA_COUNT; index++) {
IMemento child = memento.getChild(MEMENTO_KEY_SORT + index);
if (child != null && sortCriteria[index] != null) {
sortCriteria[index].restoreState(child);
}
}
}
}
public void saveState(IMemento memento) {
if (memento != null) {
for (int index = 0; index < CRITERIA_COUNT; index++) {
IMemento child = memento.createChild(MEMENTO_KEY_SORT + index);
if (child != null && sortCriteria[index] != null) {
sortCriteria[index].saveState(child);
}
}
}
}
private int sortByDate(ITask element1, ITask element2, int sortDirection) {
Date date1 = element1.getCreationDate();
Date date2 = element2.getCreationDate();
if (date1 == null) {
return (date2 != null) ? sortDirection : 0;
} else if (date2 == null) {
return -sortDirection;
}
return sortDirection * date1.compareTo(date2);
}
private int sortByDueDate(ITask element1, ITask element2, int sortDirection) {
Date date1 = element1.getDueDate();
Date date2 = element2.getDueDate();
return compare(date1, date2, sortDirection);
}
private int sortByModificationDate(ITask element1, ITask element2, int sortDirection) {
Date date1 = element1.getModificationDate();
Date date2 = element2.getModificationDate();
return compare(date1, date2, sortDirection);
}
private <T> int compare(Comparable<T> key1, T key2, int sortDirection) {
if (key1 == null) {
return (key2 != null) ? sortDirection : 0;
} else if (key2 == null) {
return -sortDirection;
}
return sortDirection * key1.compareTo(key2);
}
private int sortByID(ITask element1, ITask element2, int sortDirection) {
String key1 = element1.getTaskKey();
String key2 = element2.getTaskKey();
if (key1 == null) {
return (key2 != null) ? sortDirection : 0;
} else if (key2 == null) {
return -sortDirection;
}
return sortDirection * taskKeyComparator.compare2(key1, key2);
}
private int sortByRank(ITask element1, ITask element2, int sortDirection) {
if (element1.getConnectorKind() != null && element2.getConnectorKind() != null
&& element1.getConnectorKind().equals(element2.getConnectorKind())) {
// only compare rank of elements from the same connector
if (element1.getRepositoryUrl() != null && element2.getRepositoryUrl() != null
&& element1.getRepositoryUrl().equals(element2.getRepositoryUrl())) {
// only compare the rank of elements in the same repository
String rankString1 = element1.getAttribute(TaskAttribute.RANK);
String rankString2 = element2.getAttribute(TaskAttribute.RANK);
try {
Double rank1 = rankString1 == null || rankString1.length() == 0
? Double.valueOf(0)
: Double.valueOf(rankString1);
Double rank2 = rankString2 == null || rankString2.length() == 0
? Double.valueOf(0)
: Double.valueOf(rankString2);
return compare(rank1, rank2, sortDirection);
} catch (NumberFormatException e) {
// ignore, means that there is no rank on one of the elements
}
}
}
return 0;
}
private int sortByPriority(ITask element1, ITask element2, int sortDirection) {
return sortDirection * element1.getPriority().compareToIgnoreCase(element2.getPriority());
}
private int sortBySummary(ITask element1, ITask element2, int sortDirection) {
String key1 = element1.getSummary();
String key2 = element2.getSummary();
if (key1 == null) {
return (key2 != null) ? sortDirection : 0;
} else if (key2 == null) {
return -sortDirection;
}
return sortDirection * key1.compareToIgnoreCase(key2);
}
}