blob: 6abfc8287d125a248a48d29f5ce6be1513ad0dfb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2014 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.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.views.markers.FilterConfigurationArea;
import org.eclipse.ui.views.markers.MarkerField;
import org.eclipse.ui.views.markers.internal.ContentGeneratorDescriptor;
import org.eclipse.ui.views.markers.internal.MarkerGroup;
import org.eclipse.ui.views.markers.internal.MarkerSupportRegistry;
import org.eclipse.ui.views.markers.internal.MarkerType;
import org.eclipse.ui.views.markers.internal.MarkerTypesModel;
import org.eclipse.ui.views.markers.internal.ProblemFilter;
import org.eclipse.ui.views.markers.internal.Util;
/**
* MarkerContentGenerator is the representation of the markerContentGenerator
* extension point.
*
* @since 3.4
*
*/
public class MarkerContentGenerator {
/**
* The IMemeto Tags
*/
private static final String TAG_COLUMN_VISIBILITY = "visible"; //$NON-NLS-1$
private static final String TAG_FILTERS_SECTION = "filterGroups"; //$NON-NLS-1$
private static final String TAG_GROUP_ENTRY = "filterGroup"; //$NON-NLS-1$
private static final String TAG_AND = "andFilters"; //$NON-NLS-1$
private static final String TAG_LEGACY_FILTER_ENTRY = "filter"; //$NON-NLS-1$
private static final String TAG_MARKER_LIMIT = "markerLimit"; //$NON-NLS-1$
private static final String TAG_MARKER_LIMIT_ENABLED = "markerLimitEnabled"; //$NON-NLS-1$
/*Use this to indicate filter change rather than a null*/
private final Collection FILTERS_CHANGED = Collections.EMPTY_SET;
//Carries the description for the generator, as coded in the given extension point
private ContentGeneratorDescriptor generatorDescriptor;
// fields
private MarkerField[] visibleFields;
// filters
private Collection enabledFilters;
private Collection filters;
private boolean andFilters = false;
private int markerLimits = 100;
private boolean markerLimitsEnabled = true;
/**
* focusResources
*
*/
private IResource[] selectedResources = MarkerSupportInternalUtilities.EMPTY_RESOURCE_ARRAY;
private Collection currentResources = Collections.EMPTY_SET;
private CachedMarkerBuilder builder;
private String viewId;
private IPropertyChangeListener filterPreferenceListener;
/**
* Create a new MarkerContentGenerator
*
* @param generatorDescriptor
* @param builder
* @param viewId
* needed for backward compatibility
*/
public MarkerContentGenerator(
ContentGeneratorDescriptor generatorDescriptor,
CachedMarkerBuilder builder, String viewId) {
this.generatorDescriptor = generatorDescriptor;
this.viewId = viewId;
setBuilder(builder);
}
/**
* Attach the generator to a builder
*
* @param builder
*/
void setBuilder(CachedMarkerBuilder builder) {
this.builder = builder;
initializePreferenceListener();
this.builder.setGenerator(this);
}
/**
* @return Returns the builder this attached to.
*/
CachedMarkerBuilder getBuilder() {
return builder;
}
/**
* If attached to a builder, request marker update.
*/
void requestMarkerUpdate() {
if (builder != null) {
builder.scheduleUpdate(0L);
}
}
/**
* Return whether or not all of {@link MarkerTypesModel} arein the
* selectedTypes.
*
* @param selectedTypes
* @return boolean
*/
boolean allTypesSelected(Collection selectedTypes) {
return generatorDescriptor.allTypesSelected(selectedTypes);
}
/**
* Get the all of the fields that this content generator is using.
*
* @return {@link MarkerField}[]
*/
MarkerField[] getAllFields() {
return generatorDescriptor.getAllFields();
}
/**
* Get the fields that this content generator is displaying.
*
* @return {@link MarkerField}[]
*/
MarkerField[] getVisibleFields() {
return visibleFields;
}
/**
* Set the visible fields.
*
* @param visible
*/
void setVisibleFields(Collection visible) {
MarkerField[] newFields = new MarkerField[visible.size()];
visible.toArray(newFields);
visibleFields = newFields;
}
/**
* Return the fields not being shown currently.
*
* @return Object[]
*/
Object[] getHiddenFields() {
MarkerField[] all = getAllFields();
MarkerField[] visible = getVisibleFields();
Collection hidden = new HashSet();
for (int i = 0; i < all.length; i++) {
hidden.add(all[i]);
}
for (int i = 0; i < visible.length; i++) {
hidden.remove(visible[i]);
}
return hidden.toArray();
}
void saveState(IMemento memento, MarkerField[] displayedFields) {
for (int i = 0; i < displayedFields.length; i++) {
memento.createChild(TAG_COLUMN_VISIBILITY, displayedFields[i]
.getConfigurationElement().getAttribute(
MarkerSupportInternalUtilities.ATTRIBUTE_ID));
}
}
void restoreState(IMemento memento) {
initDefaults();
if (memento == null) {
return;
}
Integer limits = memento.getInteger(TAG_MARKER_LIMIT);
if (limits != null) {
markerLimits = limits.intValue();
}
Boolean limitsEnabled = memento.getBoolean(TAG_MARKER_LIMIT_ENABLED);
if (limitsEnabled != null) {
markerLimitsEnabled = limitsEnabled.booleanValue();
}
if (memento.getChildren(TAG_COLUMN_VISIBILITY).length != 0) {
IMemento[] visible = memento.getChildren(TAG_COLUMN_VISIBILITY);
Collection newVisible = new ArrayList();
MarkerField[] all = getAllFields();
Hashtable allTable = new Hashtable();
for (int i = 0; i < all.length; i++) {
allTable.put(all[i].getConfigurationElement().getAttribute(
MarkerSupportInternalUtilities.ATTRIBUTE_ID), all[i]);
}
for (int i = 0; i < visible.length; i++) {
String key = visible[i].getID();
if (allTable.containsKey(key)) {
newVisible.add(allTable.get(key));
}
}
visibleFields = new MarkerField[newVisible.size()];
newVisible.toArray(visibleFields);
}
}
private void initDefaults() {
IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
.getPreferenceStore();
markerLimitsEnabled = store
.getBoolean(IDEInternalPreferences.USE_MARKER_LIMITS);
markerLimits = store.getInt(IDEInternalPreferences.MARKER_LIMITS_VALUE);
MarkerField[] initialFields = getInitialVisible();
visibleFields = new MarkerField[initialFields.length];
System.arraycopy(initialFields, 0, visibleFields, 0,
initialFields.length);
}
/**
* Return a collection of all of the configuration fields for this generator
*
* @return Collection of {@link FilterConfigurationArea}
*/
Collection createFilterConfigurationFields() {
Collection result = new ArrayList();
for (int i = 0; i < visibleFields.length; i++) {
FilterConfigurationArea area = MarkerSupportInternalUtilities
.generateFilterArea(visibleFields[i]);
if (area != null)
result.add(area);
}
return result;
}
/**
* Get the category name from the receiver.
*/
String getCategoryName() {
return generatorDescriptor.getCategoryName();
}
/**
* Return all of the filters for the receiver.
*
* @return Collection of MarkerFieldFilterGroup
*/
Collection getAllFilters() {
if (filters == null || filters == FILTERS_CHANGED) {
filters = getDeclaredFilters();
// Apply the last settings
loadFiltersPreference();
}
return filters;
}
/**
* Return the currently enabled filters.
*
* @return Collection of MarkerFieldFilterGroup
*/
Collection getEnabledFilters() {
if (enabledFilters == null || enabledFilters == FILTERS_CHANGED) {
Collection enabled = new HashSet();
Iterator filtersIterator = getAllFilters().iterator();
while (filtersIterator.hasNext()) {
MarkerFieldFilterGroup next = (MarkerFieldFilterGroup) filtersIterator
.next();
if (next.isEnabled())
enabled.add(next);
}
enabledFilters = enabled;
}
return enabledFilters;
}
/**
* Rebuild the list of filters
*/
protected void rebuildFilters() {
filters = FILTERS_CHANGED;
enabledFilters = FILTERS_CHANGED;
requestMarkerUpdate();
}
/**
* Disable all of the filters in the receiver.
*/
void disableAllFilters() {
Collection allFilters = getEnabledFilters();
Iterator enabled = allFilters.iterator();
while (enabled.hasNext()) {
MarkerFieldFilterGroup group = (MarkerFieldFilterGroup) enabled
.next();
group.setEnabled(false);
}
allFilters.clear();
writeFiltersPreference();
requestMarkerUpdate();
}
/**
* Add group to the enabled filters.
*
* @param group
*/
void toggleFilter(MarkerFieldFilterGroup group) {
Collection enabled = getEnabledFilters();
if (enabled.remove(group)) // true if it was present
group.setEnabled(false);
else {
group.setEnabled(true);
enabled.add(group);
}
writeFiltersPreference();
requestMarkerUpdate();
}
/**
* Update the filters.
*
* @param filters
* @param andFilters
*/
void updateFilters(Collection filters, boolean andFilters) {
setAndFilters(andFilters);
this.filters = filters;
enabledFilters = FILTERS_CHANGED;
writeFiltersPreference();
requestMarkerUpdate();
}
/**
* Set whether the filters are being ANDed or ORed.
*
* @param and
*/
void setAndFilters(boolean and) {
andFilters = and;
}
/**
* Return whether the filters are being ANDed or ORed.
*
* @return boolean
*/
boolean andFilters() {
return andFilters;
}
/**
* @return Returns the markerLimits.
*/
public int getMarkerLimits() {
return markerLimits;
}
/**
* @param markerLimits The markerLimits to set.
*/
public void setMarkerLimits(int markerLimits) {
this.markerLimits = markerLimits;
}
/**
* @return Returns the markerLimitsEnabled.
*/
public boolean isMarkerLimitsEnabled() {
return markerLimitsEnabled;
}
/**
* @param markerLimitsEnabled The markerLimitsEnabled to set.
*/
public void setMarkerLimitsEnabled(boolean markerLimitsEnabled) {
this.markerLimitsEnabled = markerLimitsEnabled;
}
/**
* @return Collection of declared MarkerFieldFilterGroup(s)
*/
Collection getDeclaredFilters() {
List filters = new ArrayList();
IConfigurationElement[] filterReferences = generatorDescriptor.getFilterReferences();
for (int i = 0; i < filterReferences.length; i++) {
filters.add(new MarkerFieldFilterGroup(filterReferences[i], this));
}
// Honour the deprecated problemFilters
if (viewId != null && viewId.equals(IPageLayout.ID_PROBLEM_VIEW)) {
Iterator problemFilters = MarkerSupportRegistry.getInstance()
.getRegisteredFilters().iterator();
while (problemFilters.hasNext())
filters.add(new CompatibilityMarkerFieldFilterGroup(
(ProblemFilter) problemFilters.next(), this));
}
return filters;
}
/**
* Get the name of the filters preference for the receiver,
*
* @return String
*/
private String getLegacyFiltersPreferenceName() {
if (viewId != null && viewId.equals(IPageLayout.ID_BOOKMARKS))
return IDEInternalPreferences.BOOKMARKS_FILTERS;
if (viewId != null && viewId.equals(IPageLayout.ID_TASK_LIST))
return IDEInternalPreferences.TASKS_FILTERS;
return IDEInternalPreferences.PROBLEMS_FILTERS;
}
private void loadLimitSettings(IMemento memento) {
if (memento == null)
return;
Integer limits = memento.getInteger(TAG_MARKER_LIMIT);
if (limits != null) {
markerLimits = limits.intValue();
}
Boolean limitsEnabled = memento.getBoolean(TAG_MARKER_LIMIT_ENABLED);
if (limitsEnabled != null) {
markerLimitsEnabled = limitsEnabled.booleanValue();
}
}
/**
* Load the settings from the memento.
*
* @param memento
*/
private void loadFilterSettings(IMemento memento) {
if (memento == null)
return;
Boolean andValue = memento.getBoolean(TAG_AND);
if (andValue != null)
setAndFilters(andValue.booleanValue());
IMemento children[] = memento.getChildren(TAG_GROUP_ENTRY);
for (int i = 0; i < children.length; i++) {
IMemento child = children[i];
String id = child.getString(IMemento.TAG_ID);
if (id == null)
continue;
if (!loadGroupWithID(child, id))
// Did not find a match must have been added by the user
loadUserFilter(child);
}
}
/**
* Load the filters defined in memento string.
*
* @param mementoString
*/
private void loadFiltersFrom(String mementoString) {
if (mementoString.equals(IPreferenceStore.STRING_DEFAULT_DEFAULT))
return;
try {
XMLMemento root = XMLMemento.createReadRoot(new StringReader(
mementoString));
loadLimitSettings(root);
loadFilterSettings(root);
} catch (WorkbenchException e) {
StatusManager.getManager().handle(e.getStatus());
}
}
/**
* Load the filters preference.
*/
private void loadFiltersPreference() {
loadFiltersFrom(IDEWorkbenchPlugin.getDefault().getPreferenceStore()
.getString(getMementoPreferenceName()));
String legacyFilters = getLegacyFiltersPreferenceName();
String migrationPreference = legacyFilters
+ MarkerSupportInternalUtilities.MIGRATE_PREFERENCE_CONSTANT;
if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
migrationPreference))
return;// Already migrated
// Load any defined in a pre 3.4 workbench
loadLegacyFiltersFrom(IDEWorkbenchPlugin.getDefault()
.getPreferenceStore().getString(legacyFilters));
// Mark as migrated
IDEWorkbenchPlugin.getDefault().getPreferenceStore().setValue(
migrationPreference, true);
}
/**
* @return preferenceName
*/
private String getMementoPreferenceName() {
return CachedMarkerBuilder.getMementoPreferenceName(viewId);
}
/**
* Load the group with id from the child if there is a matching system group
* registered.
*
* @param child
* @param id
* @return <code>true</code> if a matching group was found
*/
private boolean loadGroupWithID(IMemento child, String id) {
Iterator groups = getAllFilters().iterator();
while (groups.hasNext()) {
MarkerFieldFilterGroup group = (MarkerFieldFilterGroup) groups
.next();
if (id.equals(group.getID())) {
group.loadSettings(child);
return true;
}
}
return false;
}
/**
* Load the legacy filter into the system.
*
* @param child
*/
private void loadLegacyFilter(IMemento child) {
MarkerFieldFilterGroup newGroup = new MarkerFieldFilterGroup(null, this);
newGroup.legacyLoadSettings(child);
getAllFilters().add(newGroup);
}
/**
* Load the pre-3.4 filters.
*
* @param mementoString
*/
private void loadLegacyFiltersFrom(String mementoString) {
if (mementoString.equals(IPreferenceStore.STRING_DEFAULT_DEFAULT))
return;
IMemento memento;
try {
memento = XMLMemento
.createReadRoot(new StringReader(mementoString));
restoreLegacyFilters(memento);
} catch (WorkbenchException e) {
StatusManager.getManager().handle(e.getStatus());
return;
}
}
/**
* Load the user supplied filter
*
* @param child
*/
private void loadUserFilter(IMemento child) {
MarkerFieldFilterGroup newGroup = new MarkerFieldFilterGroup(null, this);
newGroup.loadSettings(child);
getAllFilters().add(newGroup);
}
/**
* Restore the pre-3.4 filters.
*
* @param memento
*/
private void restoreLegacyFilters(IMemento memento) {
IMemento[] sections = null;
if (memento != null)
sections = memento.getChildren(TAG_LEGACY_FILTER_ENTRY);
for (int i = 0; i < sections.length; i++) {
IMemento child = sections[i];
String id = child.getString(IMemento.TAG_ID);
if (id == null)
continue;
loadLegacyFilter(child);
}
}
/**
*
*/
private void writeFiltersPreference() {
XMLMemento memento = XMLMemento.createWriteRoot(TAG_FILTERS_SECTION);
writeLimitSettings(memento);
writeFiltersSettings(memento);
StringWriter writer = new StringWriter();
try {
memento.save(writer);
} catch (IOException e) {
IDEWorkbenchPlugin.getDefault().getLog().log(Util.errorStatus(e));
}
// TODO: We need to migrate this the current class
IDEWorkbenchPlugin.getDefault().getPreferenceStore().putValue(
getMementoPreferenceName(),
writer.toString());
IDEWorkbenchPlugin.getDefault().savePluginPreferences();
}
/**
* Create a preference listener for any preference updates.
*/
private void initializePreferenceListener() {
if (filterPreferenceListener == null) {
filterPreferenceListener = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(getMementoPreferenceName())) {
rebuildFilters();
}
}
};
IDEWorkbenchPlugin.getDefault().getPreferenceStore()
.addPropertyChangeListener(filterPreferenceListener);
}
}
private void writeLimitSettings(XMLMemento memento) {
memento.putInteger(TAG_MARKER_LIMIT, markerLimits);
memento.putBoolean(TAG_MARKER_LIMIT_ENABLED, markerLimitsEnabled);
}
/**
* Write the settings for the filters to the memento.
*
* @param memento
*/
private void writeFiltersSettings(XMLMemento memento) {
memento.putBoolean(TAG_AND, andFilters());
Iterator groups = getAllFilters().iterator();
while (groups.hasNext()) {
MarkerFieldFilterGroup group = (MarkerFieldFilterGroup) groups
.next();
IMemento child = memento
.createChild(TAG_GROUP_ENTRY, group.getID());
group.saveFilterSettings(child);
}
}
/**
* Return the id of the receiver.
*
* @return String
*/
public String getId() {
return generatorDescriptor.getId();
}
/**
* @param viewId
* if attached to a view
*/
void setViewID(String viewId) {
this.viewId = viewId;
}
/**
* @return Returns the viewId of view it is attached to or null otherwise.
*/
public Object getViewId() {
return viewId;
}
/**
* Get the list of initially visible fields
*
* @return {@link MarkerField}[]
*/
MarkerField[] getInitialVisible() {
return generatorDescriptor.getInitialVisible();
}
/**
* Get the group called groupName from the receiver
*
* @param groupName
* @return MarkerGroup or <code>null</code>
*/
MarkerGroup getMarkerGroup(String groupName) {
Iterator groups = getMarkerGroups().iterator();
while (groups.hasNext()) {
MarkerGroup group = (MarkerGroup) groups.next();
if (group.getId().equals(groupName))
return group;
}
return null;
}
/**
* Get the markerGroups associated with the receiver.
*
* @return Collection of {@link MarkerGroup}
*/
Collection getMarkerGroups() {
return generatorDescriptor.getMarkerGroups();
}
/**
* Return the markerTypes for the receiver.
*
* @return Collection of {@link MarkerType}
*/
public Collection getMarkerTypes() {
return generatorDescriptor.getMarkerTypes();
}
/**
* Return the markerTypes for the receiver.
*
* @return Array of type Ids
*/
public String[] getTypes() {
Collection types = getMarkerTypes();
String[] ids = new String[types.size()];
Iterator iterator = types.iterator();
int i = 0;
while (iterator.hasNext()) {
ids[i++] = ((MarkerType) iterator.next()).getId();
}
return ids;
}
/**
* Return the name for the receiver.
*
* @return String
*/
String getName() {
return generatorDescriptor.getName();
}
/**
* Return the type for typeId.
*
* @param typeId
* @return {@link MarkerType} or <code>null</code> if it is not found.
*/
MarkerType getType(String typeId) {
return generatorDescriptor.getType(typeId);
}
/**
* Select the given MarkerEntry
* @return <code>true</code> if it matches all enabled filters
*/
boolean select(MarkerEntry entry) {
try {
return select(entry, getSelectedResources(), getEnabledFilters(), andFilters());
} finally {
entry.clearCache();
}
}
boolean select(MarkerEntry entry, IResource[] selResources,
Collection enabledFilters, boolean andFilters) {
if (enabledFilters.size() > 0) {
Iterator filtersIterator = enabledFilters.iterator();
if (andFilters) {
while (filtersIterator.hasNext()) {
MarkerFieldFilterGroup group = (MarkerFieldFilterGroup) filtersIterator
.next();
if (!group.selectByScope(entry, selResources)
|| !group.selectByFilters(entry)) {
return false;
}
}
return true;
}
while (filtersIterator.hasNext()) {
MarkerFieldFilterGroup group = (MarkerFieldFilterGroup) filtersIterator
.next();
if (group.selectByScope(entry, selResources)
&& group.selectByFilters(entry)) {
return true;
}
}
return false;
}
return true;
}
/**
* Update the focus resources from list. If there is an update required
* return <code>true</code>. This method assumes that there are filters on
* resources enabled.
*
* @param elements
*/
void internalUpdateSelectedElements(Object[] elements) {
Collection resourceCollection = new ArrayList();
for (int i = 0; i < elements.length; i++) {
if (elements[i] instanceof IResource) {
resourceCollection.add(elements[i]);
} else {
MarkerResourceUtil.addResources(resourceCollection,
((ResourceMapping) elements[i]));
}
}
IResource[] newSelection = new IResource[resourceCollection.size()];
resourceCollection.toArray(newSelection);
selectedResources = newSelection;
}
/**
* Update the receiver for a change in selection.
*
* @param newElements
* @param forceUpdate <code>true</code> if update must be done, <code>false</code> to only update when needed
*/
void updateSelectedResource(Object[] newElements, boolean forceUpdate) {
if (forceUpdate || updateNeededForSelection(newElements)) {
internalUpdateSelectedElements(newElements);
// See comments below and Bug 296695
// if (contentChanged()) {
requestMarkerUpdate();
// }
}
}
/**
* Return whether or not the list contains a resource that will require
* update.
*
* @return boolean <code>true</code> if update is required.
*/
boolean updateNeededForSelection(Object[] newElements) {
Iterator filters = getEnabledFilters().iterator();
while (filters.hasNext()) {
MarkerFieldFilterGroup filter = (MarkerFieldFilterGroup) filters
.next();
int scope = filter.getScope();
if (scope == MarkerFieldFilterGroup.ON_ANY
|| scope == MarkerFieldFilterGroup.ON_WORKING_SET)
continue;
if (newElements == null || newElements.length < 1)
continue;
if (selectedResources.length == 0)
return true; // We had nothing now we have something
if (Arrays.equals(selectedResources, newElements))
continue;
if (scope == MarkerFieldFilterGroup.ON_ANY_IN_SAME_CONTAINER) {
Collection oldProjects = MarkerResourceUtil
.getProjectsAsCollection(selectedResources);
Collection newProjects = MarkerResourceUtil
.getProjectsAsCollection(newElements);
if (oldProjects.size() == newProjects.size()
&& newProjects.containsAll(oldProjects))
continue;
return true;// Something must be different
}
return true;
}
return false;
}
/**
* @return list of selected resources
*/
IResource[] getSelectedResources() {
IResource[] selected=selectedResources;
IResource[] resources = new IResource[selected.length];
System.arraycopy(selected, 0, resources, 0,
selected.length);
return resources;
}
/**
* Note:As opposed to the previous scheme, the reason we gather markers only
* for the "effective"(ored/anded) resource collection is because collecting
* for individual filters and then adding them to a Set to remove duplicates
* is a lot more time-consuming than collecting only once,filtering once and
* adding to a list once.As a pre-filtering step, the
* MarkerFieldFilterGroup#selectByScope uses IPath comparison for selection,
* which happens real quickly.Also when filters are Anded we get a chance to
* gather only on resources that actually matter.And we get a tool to check
* at various places.
*
* @return list of resource we want to collect markers for taking various
* enabled filters into account.
*
*/
Collection getResourcesForBuild() {
currentResources = MarkerResourceUtil.computeResources(
getSelectedResources(), getEnabledFilters(), andFilters());
return currentResources;
}
/*
* See Bug 296695: This method is trickier than it may seem/appears to be.If
* it is ever desired to use this, it would need to be *RE-IMPLEMENTED* and
* would need a good amount of testing with various combination of filters
* and scopes. The key here is to understand and getting it right how filter
* scope and our trimmed, optimized resources and selected resource elements
* interact.
* Another possible way to check if content has changed is by
* comparing the markers gathered freshly with the previously gathered
* markers(cache them when an update is not canceled), whether this up to a
* visible limit, or completely, or selected filters we have to see. I am
* assuming that this takes little time to do. If this is done prior to
* sorting a good amount of time can be saved; we still save the UI time if
* checked after sorting. In the sorted case we can use a Binary search as
* well.Anyhow if this does take up time, we should skip this method.
*/
// /**
// * Change in markers itself is taken care of by the IResourceChangeListener,
// * We can think about change in the resource content when filters have
// * changed or selections have changed and the particular update we perform
// * manually is not required at all since nothing had changed.This is
// * particularly useful when a filter is set to 'On Selected element scope'.A
// * change in a filter is a combination of both its scope and other settings.
// *
// *
// * @return true if the resource-content has changed due to change in filter
// * settings or selection. false if content has not change or an
// * update has cleared the changes.
// */
// boolean contentChanged() {
// if (enabledFilters == null || enabledFilters == FILTERS_CHANGED) {
// /*
// * TODO:Find a more narrowing way to check if active filters have
// * actually changed.Right now the update filter method set the
// * enabled filters to null. TODO: We should use a preference
// * listener for this We can 'optimally' use it for filter change
// * only on fixing the above.
// */
// return true;
// }
// Collection current = MarkerResourceUtil.computeResources(
// getSelectedResources(), getEnabledFilters(), andFilters());
// Collection activeResources = currentResources;
// if (current.size() != activeResources.size()) {
// // changed
// return true;
// }
// Iterator iterator = activeResources.iterator();
// boolean needsUpdate = false;
// while (!needsUpdate && iterator.hasNext()) {
// Object object = iterator.next();
// if (!current.contains(object)) {
// needsUpdate = true;
// }
// }
// return needsUpdate;
// }
/**
* Refresh gathered markers entries
*
* @param monitor
*/
Collection generateMarkerEntries(IProgressMonitor monitor) {
List result = new LinkedList();
String[] typeIds = getTypes();
boolean includeSubTypes = builder.includeMarkerSubTypes();
boolean cancelled = gatherMarkers(typeIds, includeSubTypes, result,
monitor);
if (cancelled) {
result.clear();
}
return result;
}
/**
* Refresh gathered markers entries
* @param result
* @param monitor
*/
boolean generateMarkerEntries(Collection result,IProgressMonitor monitor) {
String[] typeIds = getTypes();
boolean includeSubTypes = builder.includeMarkerSubTypes();
return gatherMarkers(typeIds, includeSubTypes, result, monitor);
}
/**
* Gather markers into result.
* @param typeIds
* @param includeSubTypes
* @param result
* @param monitor
*/
boolean gatherMarkers(String[] typeIds, boolean includeSubTypes,
Collection result, IProgressMonitor monitor) {
try {
Collection resources = getResourcesForBuild();
if (includeSubTypes) {
// Optimize and calculate super types
String[] superTypes = MarkerResourceUtil
.getMutuallyExclusiveSupersIds(typeIds);
if (monitor.isCanceled()) {
return false;
}
for (int i = 0; i < superTypes.length; i++) {
boolean success = internalGatherMarkers(resources,superTypes[i],
includeSubTypes, result, monitor);
if (!success || monitor.isCanceled()) {
return false;
}
}
} else {
for (int i = 0; i < typeIds.length; i++) {
boolean success = internalGatherMarkers(resources,typeIds[i],
includeSubTypes, result, monitor);
if (!success || monitor.isCanceled()) {
return false;
}
}
}
} catch (Exception e) {
//do not propagate but do show the error
MarkerSupportInternalUtilities.showViewError(e);
return false;
} finally {
}
return true;
}
/**
* A helper to the
* {@link #gatherMarkers(String[], boolean, Collection, IProgressMonitor)}
*
* @param resources
* @param typeId
* @param includeSubTypes
* @param result
* @param monitor
*/
private boolean internalGatherMarkers(Collection resources, String typeId,
boolean includeSubTypes, Collection result, IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return false;
}
IResource[] selected = getSelectedResources();
Collection filters = getEnabledFilters();
boolean andFilters = andFilters();
Iterator iterator = resources.iterator();
while (iterator.hasNext()) {
IMarker[] markers = null;
try {
IResource resource = (IResource) iterator.next();
if (!resource.isAccessible()) {
continue;
}
markers = resource.findMarkers(typeId, includeSubTypes,
IResource.DEPTH_INFINITE);
} catch (CoreException e) {
MarkerSupportInternalUtilities.logViewError(e);
}
if (markers == null) {
continue;
}
if (monitor.isCanceled()) {
return false;
}
MarkerEntry entry = null;
int lenght = markers.length;
for (int i = 0; i < lenght; i++) {
entry = new MarkerEntry(markers[i]);
if (select(entry, selected, filters, andFilters)) {
result.add(entry);
}
entry.clearCache();
if (i % 500 == 0) {
if (monitor.isCanceled()) {
return false;
}
}
}
}
return true;
}
void dispose() {
if (filterPreferenceListener != null) {
IDEWorkbenchPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(filterPreferenceListener);
filterPreferenceListener = null;
}
}
}