/******************************************************************************* * Copyright (c) 2000, 2006 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 * Cagatay Kavukcuoglu <cagatayk@acm.org> - Filter for markers in same project *******************************************************************************/ package org.eclipse.ui.views.tasklist; import java.util.Arrays; import java.util.HashSet; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.ui.IContainmentAdapter; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPersistable; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; class TasksFilter extends ViewerFilter implements Cloneable { public static final String[] ROOT_TYPES = new String[] { IMarker.PROBLEM, IMarker.TASK }; // Filter on resource constants static final int ON_ANY_RESOURCE = 0; static final int ON_SELECTED_RESOURCE_ONLY = 1; static final int ON_SELECTED_RESOURCE_AND_CHILDREN = 2; static final int ON_ANY_RESOURCE_OF_SAME_PROJECT = 3; // added by cagatayk@acm.org static final int ON_WORKING_SET = 4; // Description filter kind constants static final int FILTER_CONTAINS = 0; static final int FILTER_DOES_NOT_CONTAIN = 1; //final static int MINIMUM_MARKER_LIMIT = 10; final static int DEFAULT_MARKER_LIMIT = 2000; //final static int MAXIMUM_MARKER_LIMIT = 20000; String[] types; int onResource; IWorkingSet workingSet; boolean filterOnDescription; int descriptionFilterKind; String descriptionFilter; boolean filterOnSeverity; int severityFilter; boolean filterOnPriority; int priorityFilter; boolean filterOnCompletion; int completionFilter; private boolean filterOnMarkerLimit = true; private int markerLimit = DEFAULT_MARKER_LIMIT; private static final String TAG_ID = "id"; //$NON-NLS-1$ private static final String TAG_TYPE = "type"; //$NON-NLS-1$ private static final String TAG_ON_RESOURCE = "onResource"; //$NON-NLS-1$ private static final String TAG_WORKING_SET = "workingSet"; //$NON-NLS-1$ private static final String TAG_FILTER_ON_DESCRIPTION = "filterOnDescription"; //$NON-NLS-1$ private static final String TAG_DESCRIPTION_FILTER_KIND = "descriptionFilterKind"; //$NON-NLS-1$ private static final String TAG_DESCRIPTION_FILTER = "descriptionFilter"; //$NON-NLS-1$ private static final String TAG_FILTER_ON_SEVERITY = "filterOnSeverity"; //$NON-NLS-1$ private static final String TAG_SEVERITY_FILTER = "severityFilter"; //$NON-NLS-1$ private static final String TAG_FILTER_ON_PRIORITY = "filterOnPriority"; //$NON-NLS-1$ private static final String TAG_PRIORITY_FILTER = "priorityFilter"; //$NON-NLS-1$ private static final String TAG_FILTER_ON_COMPLETION = "filterOnCompletion"; //$NON-NLS-1$ private static final String TAG_COMPLETION_FILTER = "completionFilter"; //$NON-NLS-1$ private static final String TAG_FILTER_ON_MARKER_LIMIT = "filterOnMarkerLimit"; //$NON-NLS-1$ private static final String TAG_MARKER_LIMIT = "markerLimit"; //$NON-NLS-1$ public TasksFilter() { reset(); } boolean getFilterOnMarkerLimit() { return filterOnMarkerLimit; } void setFilterOnMarkerLimit(boolean filterOnMarkerLimit) { this.filterOnMarkerLimit = filterOnMarkerLimit; } int getMarkerLimit() { return markerLimit; } void setMarkerLimit(int markerLimit) { if (markerLimit < 1) { markerLimit = TasksFilter.DEFAULT_MARKER_LIMIT; } //if (markerLimit < TasksFilter.MINIMUM_MARKER_LIMIT) { // markerLimit = TasksFilter.MINIMUM_MARKER_LIMIT; //} else if (markerLimit > TasksFilter.MAXIMUM_MARKER_LIMIT) { // markerLimit = TasksFilter.MAXIMUM_MARKER_LIMIT; //} this.markerLimit = markerLimit; } boolean checkDescription(String desc) { if (desc == null) { // be paranoid desc = ""; //$NON-NLS-1$ } boolean contains = containsSubstring(desc, descriptionFilter); return descriptionFilterKind == FILTER_CONTAINS ? contains : !contains; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new Error(); // shouldn't happen } } boolean containsSubstring(String string, String substring) { int strLen = string.length(); int subLen = substring.length(); int len = strLen - subLen; for (int i = 0; i <= len; ++i) { if (string.regionMatches(true, i, substring, 0, subLen)) { return true; } } return false; } /** * Returns if the given resource is enclosed by a working set element. * The IContainmentAdapter of each working set element is used for the * containment test. If there is no IContainmentAdapter for a working * set element, a simple resource based test is used. * * @param element resource to test for enclosure by a working set * element * @return true if element is enclosed by a working set element and * false otherwise. */ private boolean isEnclosed(IResource element) { IPath elementPath = element.getFullPath(); IAdaptable[] workingSetElements = workingSet.getElements(); if (elementPath.isEmpty() || elementPath.isRoot()) { return false; } for (int i = 0; i < workingSetElements.length; i++) { IAdaptable workingSetElement = workingSetElements[i]; IContainmentAdapter containmentAdapter = (IContainmentAdapter) workingSetElement .getAdapter(IContainmentAdapter.class); // if there is no IContainmentAdapter defined for the working // set element type fall back to using resource based // containment check if (containmentAdapter != null) { if (containmentAdapter.contains(workingSetElement, element, IContainmentAdapter.CHECK_CONTEXT | IContainmentAdapter.CHECK_IF_CHILD | IContainmentAdapter.CHECK_IF_DESCENDANT)) { return true; } } else if (isEnclosedResource(element, elementPath, workingSetElement)) { return true; } } return false; } /** * Returns if the given resource is enclosed by a working set element. * A resource is enclosed if it is either a parent of a working set * element, a child of a working set element or a working set element * itself. * Simple path comparison is used. This is only guaranteed to return * correct results for resource working set elements. * * @param element resource to test for enclosure by a working set * element * @param elementPath full, absolute path of the element to test * @return true if element is enclosed by a working set element and * false otherwise. */ private boolean isEnclosedResource(IResource element, IPath elementPath, IAdaptable workingSetElement) { IResource workingSetResource = null; if (workingSetElement.equals(element)) { return true; } if (workingSetElement instanceof IResource) { workingSetResource = (IResource) workingSetElement; } else { workingSetResource = (IResource) workingSetElement .getAdapter(IResource.class); } if (workingSetResource != null) { IPath resourcePath = workingSetResource.getFullPath(); if (resourcePath.isPrefixOf(elementPath)) { return true; } } return false; } public void reset() { types = ROOT_TYPES; onResource = ON_ANY_RESOURCE; filterOnDescription = false; descriptionFilter = ""; //$NON-NLS-1$ filterOnSeverity = false; severityFilter = 0; filterOnPriority = false; priorityFilter = 0; filterOnCompletion = false; completionFilter = 0; filterOnMarkerLimit = true; markerLimit = DEFAULT_MARKER_LIMIT; } /** * @see IPersistable */ public void restoreState(IMemento memento) { IMemento children[] = memento.getChildren(TAG_TYPE); types = new String[children.length]; for (int i = 0; i < children.length; i++) { types[i] = children[i].getString(TAG_ID); } Integer ival = memento.getInteger(TAG_ON_RESOURCE); onResource = ival == null ? ON_ANY_RESOURCE : ival.intValue(); restoreWorkingSet(memento.getString(TAG_WORKING_SET)); ival = memento.getInteger(TAG_FILTER_ON_DESCRIPTION); filterOnDescription = ival != null && ival.intValue() == 1; ival = memento.getInteger(TAG_DESCRIPTION_FILTER_KIND); descriptionFilterKind = ival == null ? FILTER_CONTAINS : ival .intValue(); descriptionFilter = memento.getString(TAG_DESCRIPTION_FILTER); if (descriptionFilter == null) { descriptionFilter = ""; //$NON-NLS-1$ } ival = memento.getInteger(TAG_FILTER_ON_SEVERITY); filterOnSeverity = ival != null && ival.intValue() == 1; ival = memento.getInteger(TAG_SEVERITY_FILTER); severityFilter = ival == null ? 0 : ival.intValue(); ival = memento.getInteger(TAG_FILTER_ON_PRIORITY); filterOnPriority = ival != null && ival.intValue() == 1; ival = memento.getInteger(TAG_PRIORITY_FILTER); priorityFilter = ival == null ? 0 : ival.intValue(); ival = memento.getInteger(TAG_FILTER_ON_COMPLETION); filterOnCompletion = ival != null && ival.intValue() == 1; ival = memento.getInteger(TAG_COMPLETION_FILTER); completionFilter = ival == null ? 0 : ival.intValue(); ival = memento.getInteger(TAG_FILTER_ON_MARKER_LIMIT); filterOnMarkerLimit = ival == null || ival.intValue() == 1; ival = memento.getInteger(TAG_MARKER_LIMIT); markerLimit = ival == null ? DEFAULT_MARKER_LIMIT : ival.intValue(); } /** * Restores the saved working set, if any. * * @param the saved working set name or null */ private void restoreWorkingSet(String workingSetName) { if (workingSetName != null) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() .getWorkingSetManager(); IWorkingSet workingSet = workingSetManager .getWorkingSet(workingSetName); if (workingSet != null) { this.workingSet = workingSet; } } } /** * Saves the object state within a memento. * * @param memento a memento to receive the object state */ public void saveState(IMemento memento) { for (int i = 0; i < types.length; i++) { memento.createChild(TAG_TYPE).putString(TAG_ID, types[i]); } memento.putInteger(TAG_ON_RESOURCE, onResource); if (workingSet != null) { memento.putString(TAG_WORKING_SET, workingSet.getName()); } memento.putInteger(TAG_FILTER_ON_DESCRIPTION, filterOnDescription ? 1 : 0); memento.putInteger(TAG_DESCRIPTION_FILTER_KIND, descriptionFilterKind); memento.putString(TAG_DESCRIPTION_FILTER, descriptionFilter); memento.putInteger(TAG_FILTER_ON_SEVERITY, filterOnSeverity ? 1 : 0); memento.putInteger(TAG_SEVERITY_FILTER, severityFilter); memento.putInteger(TAG_FILTER_ON_PRIORITY, filterOnPriority ? 1 : 0); memento.putInteger(TAG_PRIORITY_FILTER, priorityFilter); memento .putInteger(TAG_FILTER_ON_COMPLETION, filterOnCompletion ? 1 : 0); memento.putInteger(TAG_COMPLETION_FILTER, completionFilter); memento.putInteger(TAG_FILTER_ON_MARKER_LIMIT, filterOnMarkerLimit ? 1 : 0); memento.putInteger(TAG_MARKER_LIMIT, markerLimit); } public boolean select(Viewer viewer, Object parentElement, Object element) { return select((IMarker) element); } public boolean select(IMarker marker) { // resource settings are handled by the content provider return selectByType(marker) && selectByAttributes(marker) && selectByWorkingSet(marker); } public boolean select(IMarkerDelta markerDelta) { // resource settings are handled by the content provider return selectByType(markerDelta) && selectByAttributes(markerDelta) && selectByWorkingSet(markerDelta); } private boolean selectByType(IMarker marker) { for (int i = 0; i < types.length; ++i) { if (MarkerUtil.isMarkerType(marker, types[i])) { return true; } } return false; } private boolean selectByType(IMarkerDelta markerDelta) { for (int i = 0; i < types.length; ++i) { if (markerDelta.isSubtypeOf(types[i])) { return true; } } return false; } /** * Returns whether the specified marker should be filter out or not. * * @param marker the marker to test * @return * true=the marker should not be filtered out * false=the marker should be filtered out */ private boolean selectByWorkingSet(IMarker marker) { if (workingSet == null || onResource != ON_WORKING_SET) { return true; } IResource resource = marker.getResource(); if (resource != null) { return isEnclosed(resource); } return false; } /** * Returns whether the specified marker delta should be filter out * or not. * * @param markerDelta the marker delta to test * @return * true=the marker delta should not be filtered out * false=the marker delta should be filtered out */ private boolean selectByWorkingSet(IMarkerDelta markerDelta) { if (workingSet == null || onResource != ON_WORKING_SET) { return true; } IResource resource = markerDelta.getResource(); if (resource != null) { return isEnclosed(resource); } return false; } /* * WARNING: selectByAttributes(IMarker) and selectByAttributes(IMarkerDelta) must correspond. */ private boolean selectByAttributes(IMarker marker) { // severity filter applies only to problems if (filterOnSeverity && MarkerUtil.isMarkerType(marker, IMarker.PROBLEM)) { int sev = MarkerUtil.getSeverity(marker); if ((severityFilter & (1 << sev)) == 0) { return false; } } // priority and completion filters apply only to tasks // avoid doing type check more than once if ((filterOnPriority || filterOnCompletion) && MarkerUtil.isMarkerType(marker, IMarker.TASK)) { if (filterOnPriority) { int pri = MarkerUtil.getPriority(marker); if ((priorityFilter & (1 << pri)) == 0) { return false; } } if (filterOnCompletion) { boolean complete = MarkerUtil.isComplete(marker); if ((completionFilter & (complete ? 2 : 1)) == 0) { return false; } } } // description applies to all markers if (filterOnDescription) { String desc = MarkerUtil.getMessage(marker); if (!checkDescription(desc)) { return false; } } return true; } private boolean selectByAttributes(IMarkerDelta markerDelta) { // severity filter applies only to problems if (filterOnSeverity && markerDelta.isSubtypeOf(IMarker.PROBLEM)) { int sev = markerDelta.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); if ((severityFilter & (1 << sev)) == 0) { return false; } } // priority and completion filters apply only to tasks // avoid doing type check more than once if ((filterOnPriority || filterOnCompletion) && markerDelta.isSubtypeOf(IMarker.TASK)) { if (filterOnPriority) { int pri = markerDelta.getAttribute(IMarker.PRIORITY, IMarker.PRIORITY_NORMAL); if ((priorityFilter & (1 << pri)) == 0) { return false; } } if (filterOnCompletion) { boolean complete = markerDelta .getAttribute(IMarker.DONE, false); if ((completionFilter & (complete ? 2 : 1)) == 0) { return false; } } } // description applies to all markers if (filterOnDescription) { String desc = markerDelta.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$ if (!checkDescription(desc)) { return false; } } return true; } /** * Returns whether the filter is including all markers. * * @return <code>true</code> if the filter includes all markers, <code>false</code> if not */ public boolean isShowingAll() { if (filterOnDescription || filterOnSeverity || filterOnPriority || filterOnCompletion) { return false; } if (onResource != ON_ANY_RESOURCE) { return false; } HashSet set = new HashSet(Arrays.asList(types)); if (set.size() != ROOT_TYPES.length) { return false; } for (int i = 0; i < ROOT_TYPES.length; ++i) { if (!set.contains(ROOT_TYPES[i])) { return false; } } return true; } }