| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials! |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-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.*; |
| 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.*; |
| import org.eclipse.ui.internal.WorkbenchPlugin; |
| |
| 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 = WorkbenchPlugin.getDefault().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 = (IResource) 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 = (IResource) 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; |
| } |
| } |