org.eclipse.ui.internal.views.markers.MarkerContentGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.internal.views.markers.MarkerContentGenerator.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2010 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() {

                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
     */
    void updateSelectedResource(Object[] newElements) {
        if (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;
        }
    }
}