blob: 47ce0db675f579bd2ea5d5cc6925a4cd25c45916 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.views.markers;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.views.markers.MarkerField;
import org.eclipse.ui.views.markers.MarkerItem;
/**
* The MarkerComparator is the class that handles the comparison of markers for
* a specific content provider.
*
* @since 3.4
*
*/
class MarkerComparator implements Comparator<MarkerItem> {
private MarkerField category;
// These fields are in sort order
private MarkerField[] fields;
/**
* Constant to indicate an ascending sort direction.
*/
public static final int ASCENDING = 1;
/**
* Constant to indicate an descending sort direction.
*/
public static final int DESCENDING = -1;
private static final String PRIMARY_SORT_FIELD_TAG = "PRIMARY_SORT_FIELD"; //$NON-NLS-1$
private static final String DESCENDING_FIELDS = "DESCENDING_FIELDS"; //$NON-NLS-1$
// The fields with reversed direction
HashSet<MarkerField> descendingFields = new HashSet<>();
/**
* Create a new instance of the receiver categorised by categoryField
*
* @param categoryField
* May be <code>null/<code>
* @param mainFields in order of compare significance
*/
public MarkerComparator(MarkerField categoryField, MarkerField[] mainFields) {
category = categoryField;
fields = mainFields;
}
/**
* Compare the two objects to see if they have the same category value
*
* @param object1
* @param object2
* @return int
* @see Comparable#compareTo(Object)
*/
public int compareCategory(MarkerItem object1, MarkerItem object2) {
if (category == null) {
return 0;
}
return category.compare(object1, object2);
}
/**
* Comparator to compare the two MarkerEntry(s) to see if they have the same
* category value
*
* @return Comparator
*/
Comparator<MarkerItem> getCategoryComparator() {
return new Comparator<MarkerItem>() {
@Override
public int compare(MarkerItem o1, MarkerItem o2) {
return compareCategory(o1, o2);
}
};
}
@Override
public int compare(MarkerItem arg0, MarkerItem arg1) {
// Sort by category first
int value = compareCategory(arg0, arg1);
if (value == 0) {
value=compareFields(arg0, arg1);
}
return value ;
}
/**
* Compare the two objects by various fields
*
* @param item0
* @param item1
* @return int
*/
public int compareFields(MarkerItem item0, MarkerItem item1) {
int value = 0;
for (int i = 0; i < fields.length; i++) {
if (descendingFields.contains(fields[i])) {
value = fields[i].compare(item1, item0);
} else {
value = fields[i].compare(item0, item1);
}
if (value != 0) {
break;
}
}
return value;
}
/**
* Comparator to compare the two MarkerEntry(s) by various fields
*
* @return Comparator
*/
Comparator<MarkerItem> getFieldsComparator() {
return new Comparator<MarkerItem>() {
@Override
public int compare(MarkerItem o1, MarkerItem o2) {
return compareFields(o1, o2);
}
};
}
/**
* Switch the priority of the field from ascending to descending or vice
* versa.
*
* @param field
*/
public void reversePriority(MarkerField field) {
if (descendingFields.remove(field)) {
return;
}
descendingFields.add(field);
}
/**
* Set field to be the first sort field.
*
* @param field
*/
void setPrimarySortField(MarkerField field) {
if (fields[0] == field) {
reversePriority(field);
return;
}
int insertionIndex = 1;
MarkerField[] newFields = new MarkerField[fields.length];
newFields[0] = field;
for (int i = 0; i < newFields.length; i++) {
if (fields[i] == field) {
continue;
}
newFields[insertionIndex] = fields[i];
insertionIndex++;
}
fields = newFields;
}
/**
* Restore the receiver's state from memento.
*
* @param memento
*/
void restore(IMemento memento) {
if (memento == null) {
return;
}
String primaryField = memento.getString(PRIMARY_SORT_FIELD_TAG);
if (primaryField == null || primaryField.equals(MarkerSupportInternalUtilities.getId(fields[0]))) {
return;
}
for (int i = 1; i < fields.length; i++) {
if (MarkerSupportInternalUtilities.getId(fields[i]).equals(primaryField)) {
setPrimarySortField(fields[i]);
break;
}
}
IMemento[] descending = memento.getChildren(DESCENDING_FIELDS);
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < descending.length; j++) {
if (descending[j].getID().equals(MarkerSupportInternalUtilities.getId(fields[i]))) {
descendingFields.add(fields[i]);
continue;
}
}
}
}
/**
* Save the current sort field in the memento.
*
* @param memento
*/
void saveState(IMemento memento) {
memento.putString(PRIMARY_SORT_FIELD_TAG, MarkerSupportInternalUtilities.getId(fields[0]));
Iterator<MarkerField> descendingIterator = descendingFields.iterator();
while (descendingIterator.hasNext()) {
memento.createChild(DESCENDING_FIELDS, (MarkerSupportInternalUtilities.getId(descendingIterator.next())));
}
}
/**
* Get the field that is the main sort field
*
* @return MarkerField
*/
MarkerField getPrimarySortField() {
return fields[0];
}
/**
* Set the category field without changing other sort orders.
* @param category or <code>null</code>
*/
void setCategory(MarkerField category) {
this.category = category;
}
}