| /******************************************************************************* |
| * 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; |
| } |
| } |
| } |