Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2007 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.ide.markers.compatibility.internal; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.resources.mapping.ResourceMappingContext; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.operation.IRunnableWithProgress; 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.PlatformUI; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.ide.markers.compatibility.api.FilterConfigurationArea; import org.eclipse.ui.ide.markers.compatibility.api.MarkerField; import org.eclipse.ui.ide.markers.compatibility.api.MarkerItem; import org.eclipse.ui.internal.ide.IDEInternalPreferences; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.ide.StatusUtil; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import org.eclipse.ui.statushandlers.StatusManager; import org.eclipse.ui.views.markers.internal.MarkerMessages; import org.eclipse.ui.views.markers.internal.MarkerSupportRegistry; import org.eclipse.ui.views.markers.internal.MarkerType; import org.eclipse.ui.views.markers.internal.ProblemFilter; import org.eclipse.ui.views.markers.internal.Util; /** * The CachedMarkerBuilder is the object that generates the list of markers from * a generator. * * @since 3.4 * */ public class CachedMarkerBuilder { private static final MarkerCategory[] EMPTY_CATEGORY_ARRAY = new MarkerCategory[0]; private static final MarkerEntry[] EMPTY_ENTRY_ARRAY = new MarkerEntry[0]; private static final int SHORT_DELAY = 100;// The 100 ms short delay for // scheduling private static final int TIME_OUT = 30000;// The 30s long delay to run 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_CATEGORY_GROUP = "categoryGroup"; //$NON-NLS-1$ private static final String VALUE_NONE = "none"; //$NON-NLS-1$ private static final String TAG_LEGACY_FILTER_ENTRY = "filter"; //$NON-NLS-1$ private boolean building = true;// Start with nothing until we have // something private MarkerCategory[] categories; private MarkerMap currentMap = null; private MarkerContentGenerator generator; // The MarkerContentGenerator we // are // building for private Job markerProcessJob; private IWorkbenchSiteProgressService progressService; private Job updateJob; private MarkerGroup categoryGroup; private Collection enabledFilters; private Collection filters; private IResource[] focusResources = MarkerSupportInternalUtilities.EMPTY_RESOURCE_ARRAY; private MarkerField[] visibleFields; private boolean andFilters = false; private MarkerComparator comparator; private IMemento memento; private String viewId; // The time the build started. A -1 indicates no build in progress. private long preBuildTime = -1; // without a builder update /** * Create a new instance of the receiver. Update using the updateJob. * * @param contentGenerator * @param id * id of the view we are building for */ CachedMarkerBuilder(MarkerContentGenerator contentGenerator, String id, IMemento memento) { this.generator = contentGenerator; this.viewId = id; initialiseVisibleFields(); initializePreferenceListener(); this.memento = memento; if (memento == null) setDefaultCategoryGroup(contentGenerator); else { // Set up the category group if it has been set or set a default. String categoryGroupID = memento.getString(TAG_CATEGORY_GROUP); if (categoryGroupID == null) setDefaultCategoryGroup(contentGenerator); else { if (categoryGroupID.equals(VALUE_NONE)) this.categoryGroup = null; else { MarkerGroup newGroup = contentGenerator.getMarkerGroup(categoryGroupID); if (newGroup == null) setDefaultCategoryGroup(contentGenerator); else this.categoryGroup = newGroup; } } } createMarkerProcessJob(); // Hook up to the resource changes after all widget have been created ResourcesPlugin.getWorkspace().addResourceChangeListener(getUpdateListener(), IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_BUILD | IResourceChangeEvent.POST_BUILD); } /** * Create a preference listener for any preference updates. */ private void initializePreferenceListener() { IDEWorkbenchPlugin.getDefault().getPreferenceStore() .addPropertyChangeListener(new IPropertyChangeListener() { /* * (non-Javadoc) * * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(getMementoPreferenceName())) { rebuildFilters(); } } }); } /** * Rebuild the list of filters */ protected void rebuildFilters() { filters = null; enabledFilters = null; scheduleMarkerUpdate(); } /** * Add the resources in resourceMapping to the resourceCollection * * @param resourceCollection * @param resourceMapping */ private void addResources(Collection resourceCollection, ResourceMapping resourceMapping) { try { ResourceTraversal[] traversals = resourceMapping.getTraversals(ResourceMappingContext.LOCAL_CONTEXT, new NullProgressMonitor()); for (int i = 0; i < traversals.length; i++) { ResourceTraversal traversal = traversals[i]; IResource[] result = traversal.getResources(); for (int j = 0; j < result.length; j++) { resourceCollection.add(result[j]); } } } catch (CoreException e) { MarkerSupportInternalUtilities.handle(e); } } /** * Return whether the filters are being ANDed or ORed. * * @return boolean */ boolean andFilters() { return andFilters; } /** * Build all of the markers in the receiver. * * @param monitor */ void buildAllMarkers(IProgressMonitor monitor) { building = true; MarkerMap newMarkers; try { monitor.beginTask(MarkerMessages.MarkerView_19, 60); monitor.subTask(MarkerMessages.MarkerView_waiting_on_changes); if (monitor.isCanceled()) return; monitor.subTask(MarkerMessages.MarkerView_searching_for_markers); SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10); newMarkers = generator.generateFilteredMarkers(subMonitor, andFilters(), focusResources, getEnabledFilters()); if (monitor.isCanceled()) return; sortAndMakeCategories(new SubProgressMonitor(monitor, 30), newMarkers); monitor.done(); } finally { building = false; } } /** * Break the marker up into categories * * @param markers * @param start * the start index in the markers * @param end * the last index to check * @param sortIndex - * the parent of the field * @return MarkerCategory[] or <code>null</code> if we are at the bottom * of the tree */ MarkerCategory[] buildHierarchy(MarkerMap markers, int start, int end, int sortIndex) { MarkerComparator sorter = getComparator(); if (sortIndex > 0) { return null;// Are we out of categories? } Collection categories = new ArrayList(); Object previous = null; int categoryStart = start; Object[] elements = markers.toArray(); for (int i = start; i <= end; i++) { if (previous != null) { // Are we at a category boundary? if (sorter.compareCategory(previous, elements[i]) != 0) { categories.add(new MarkerCategory(this, categoryStart, i - 1, getCategoryGroup().getMarkerField().getValue(markers.elementAt(categoryStart)))); categoryStart = i; } } previous = elements[i]; } if (end >= categoryStart) { categories.add(new MarkerCategory(this, categoryStart, end, getCategoryGroup().getMarkerField().getValue(markers.elementAt(categoryStart)))); } MarkerCategory[] nodes = new MarkerCategory[categories.size()]; categories.toArray(nodes); return nodes; } /** * Cancel the pending jobs in the receiver. */ private void cancelJobs() { markerProcessJob.cancel(); updateJob.cancel(); } /** * 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 = visibleFields[i].generateFilterArea(); if (area != null) result.add(area); } return result; } /** * Create the job for updating the markers. */ private void createMarkerProcessJob() { markerProcessJob = new Job(MarkerMessages.MarkerView_processUpdates) { /* * (non-Javadoc) * * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object) */ public boolean belongsTo(Object family) { return MarkerContentGenerator.CACHE_UPDATE_FAMILY == family; } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ protected IStatus run(IProgressMonitor monitor) { updateJob.cancel(); buildAllMarkers(monitor); updateJob.schedule(); return Status.OK_STATUS; } /* * (non-Javadoc) * * @see org.eclipse.ui.progress.WorkbenchJob#shouldRun() */ public boolean shouldRun() { // Hold off while everything is active if (preBuildTime > 0 && System.currentTimeMillis() - preBuildTime < TIME_OUT) return false; // Clear it if we are past the time out. preBuildTime = -1; // Do not run if the change came in before there is a viewer return PlatformUI.isWorkbenchRunning(); } }; markerProcessJob.setSystem(true); } /** * 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(); scheduleMarkerUpdate(); } /** * Return all of the filters for the receiver. * * @return Collection of MarkerFieldFilterGroup */ Collection getAllFilters() { if (filters == null) { filters = new ArrayList(); IConfigurationElement[] filterReferences = generator.getFilterReferences(); for (int i = 0; i < filterReferences.length; i++) { filters.add(new MarkerFieldFilterGroup(filterReferences[i], this)); } // Honour the deprecated problemFilters if (viewId.equals(IPageLayout.ID_PROBLEM_VIEW)) { Iterator problemFilters = MarkerSupportRegistry.getInstance().getRegisteredFilters().iterator(); while (problemFilters.hasNext()) filters.add( new CompatibilityMarkerFieldFilterGroup((ProblemFilter) problemFilters.next(), this)); } // Apply the last settings loadFiltersPreference(); } return filters; } /** * Return the categories for the receiver. * * @return MarkerCategory[] or <code>null</code> if there are no * categories. */ MarkerCategory[] getCategories() { if (building) { return null; } return categories; } /** * Return the group used to generate categories. * * @return MarkerGroup or <code>null</code>. */ MarkerGroup getCategoryGroup() { return categoryGroup; } /** * Return a new instance of the receiver with the field * * @return MarkerComparator */ MarkerComparator getComparator() { if (comparator == null) { MarkerField field = null; if (getCategoryGroup() != null) field = getCategoryGroup().getMarkerField(); comparator = new MarkerComparator(field, generator.getAllFields()); comparator.restore(this.memento); } return comparator; } /** * Return the elements in the adapter. * * @return Object[] */ MarkerItem[] getElements() { if (refreshingMarkers()) { return MarkerSupportInternalUtilities.EMPTY_MARKER_ITEM_ARRAY; } if (isShowingHierarchy() && categories != null) { return categories; } return currentMap.toArray(); } /** * Return the currently enabled filters. * * @return Collection of MarkerFieldFilterGroup */ Collection getEnabledFilters() { if (enabledFilters == null) { enabledFilters = new HashSet(); Iterator filtersIterator = getAllFilters().iterator(); while (filtersIterator.hasNext()) { MarkerFieldFilterGroup next = (MarkerFieldFilterGroup) filtersIterator.next(); if (next.isEnabled()) enabledFilters.add(next); } } return enabledFilters; } /** * Return the generator for the receiver. * * @return MarkerContentGenerator */ MarkerContentGenerator getGenerator() { return generator; } /** * Get the name of the filters preference for the receiver, * * @return String */ private String getLegacyFiltersPreferenceName() { if (viewId.equals(IPageLayout.ID_BOOKMARKS)) return IDEInternalPreferences.BOOKMARKS_FILTERS; if (viewId.equals(IPageLayout.ID_TASK_LIST)) return IDEInternalPreferences.TASKS_FILTERS; return IDEInternalPreferences.PROBLEMS_FILTERS; } /** * Get the raw list of marker entries. * * @return list of MarkerEntry */ MarkerEntry[] getMarkerEntries() { if (refreshingMarkers()) return EMPTY_ENTRY_ARRAY; return currentMap.toArray(); } /** * Get the MarkerItem that matches marker. * * @param marker * @return MarkerItem or <code>null<code> if it cannot be found */ MarkerItem getMarkerItem(IMarker marker) { if (refreshingMarkers()) return null; return currentMap.getMarkerItem(marker); } /** * Get the name for the preferences for the receiver. * * @return String */ private String getMementoPreferenceName() { return getClass().getName() + viewId; } /** * Return the primary sort field * * @return MarkerField */ MarkerField getPrimarySortField() { return getComparator().getPrimarySortField(); } /** * Get the sort direction of field * * @param field * @return int one of {@link MarkerComparator#ASCENDING} or * {@link MarkerComparator#DESCENDING} */ int getSortDirection(MarkerField field) { if (getComparator().descendingFields.contains(field)) return MarkerComparator.DESCENDING; return MarkerComparator.ASCENDING; } /** * Return the total number of markers. * * @return int */ int getTotalMarkerCount() { MarkerItem[] elements = getElements(); if (elements.length == 0 || elements[0].isConcrete()) return elements.length; int length = 0; for (int i = 0; i < elements.length; i++) { length += elements[i].getChildren().length; } return length; } /** * Return the resource listener for the builder * * @return IResourceChangeListener */ private IResourceChangeListener getUpdateListener() { return new IResourceChangeListener() { /** * Returns whether or not the given even contains marker deltas for * this view. * * @param event * the resource change event * @return <code>true</code> if the event contains at least one * relevant marker delta * @since 3.3 */ private boolean hasMarkerDelta(IResourceChangeEvent event) { Iterator markerTypes = generator.getMarkerTypes().iterator(); while (markerTypes.hasNext()) { MarkerType type = (MarkerType) markerTypes.next(); if (event.findMarkerDeltas(type.getId(), true).length > 0) return true; } return false; } /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent event) { if (!hasMarkerDelta(event)) return; if (event.getType() == IResourceChangeEvent.PRE_BUILD) { preBuild(); return; } if (event.getType() == IResourceChangeEvent.POST_BUILD) { postBuild(); scheduleMarkerUpdate(); return; } // After 30 seconds do updates anyways if (progressService == null) markerProcessJob.schedule(TIME_OUT); else progressService.schedule(markerProcessJob, TIME_OUT); } }; } /** * Get the fields that this content generator is displaying. * * @return {@link MarkerField}[] */ MarkerField[] getVisibleFields() { return visibleFields; } /** * Return whether or not the receiver has markers without scheduling * anything if it doesn't. * * @return boolean <code>true</code> if the markers have not been * calculated. */ boolean hasNoMarkers() { return currentMap == null; } /** * Initialise the visible fields based pm */ private void initialiseVisibleFields() { MarkerField[] initialFields = getGenerator().getInitialVisible(); visibleFields = new MarkerField[initialFields.length]; System.arraycopy(initialFields, 0, visibleFields, 0, initialFields.length); } /** * Return whether or not the receiver is building. * * @return boolean */ boolean isBuilding() { return building; } /** * Return whether or not we are showing a hierarchy,. * * @return <code>true</code> if a hierarchy is being shown. */ boolean isShowingHierarchy() { return categoryGroup != null; } /** * 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 { loadFilterSettings(XMLMemento.createReadRoot(new StringReader(mementoString))); } 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); } /** * 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); } /** * Post build has happened. Let it all run. */ protected void postBuild() { preBuildTime = -1; } /** * We are in a pre build state. Do not update until the post build happens. */ protected void preBuild() { preBuildTime = System.currentTimeMillis(); } /** * Refresh the sort order and categories of the receiver. * * @param service * The service to run the operation in. */ void refreshContents(IWorkbenchSiteProgressService service) { try { service.busyCursorWhile(new IRunnableWithProgress() { /* * (non-Javadoc) * * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) { // Let the build finish before trying to sort if (refreshingMarkers()) return; sortAndMakeCategories(monitor, currentMap); } }); } catch (InvocationTargetException e) { StatusManager.getManager().handle(StatusUtil.newStatus(IStatus.ERROR, e.getLocalizedMessage(), e)); } catch (InterruptedException e) { StatusManager.getManager().handle(StatusUtil.newStatus(IStatus.ERROR, e.getLocalizedMessage(), e)); } } /** * Check if the markers are still being built. If so schedule an update. * * @return <code>true</code> if the map is empty. */ private boolean refreshingMarkers() { if (currentMap == null) {// First time? scheduleMarkerUpdate(); return true; } return building; } /** * 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); } } /** * Save the state of the receiver to memento * * @param memento */ void saveState(IMemento memento) { getComparator().saveState(memento); if (categoryGroup == null) memento.putString(TAG_CATEGORY_GROUP, VALUE_NONE); else memento.putString(TAG_CATEGORY_GROUP, getCategoryGroup().getId()); } /** * Schedule an update of the markers with a delay. * */ void scheduleMarkerUpdate() { cancelJobs(); currentMap = null; building = true; progressService.schedule(markerProcessJob, SHORT_DELAY); } /** * Set whether the filters are being ANDed or ORed. * * @param and */ void setAndFilters(boolean and) { andFilters = and; } /** * Set the category group. * * @param group * {@link MarkerGroup} or <code>null</code>. */ void setCategoryGroup(MarkerGroup group) { this.categoryGroup = group; comparator = null; scheduleMarkerUpdate(); } /** * Categorise by the default setting for contentGenerator. * * @param contentGenerator */ private void setDefaultCategoryGroup(MarkerContentGenerator contentGenerator) { String categoryName = contentGenerator.getCategoryName(); if (categoryName != null) { MarkerGroup group = contentGenerator.getMarkerGroup(categoryName); if (group != null) categoryGroup = group; } } /** * Set the generator and update the contents. * * @param generator */ void setGenerator(MarkerContentGenerator generator) { this.generator = generator; scheduleMarkerUpdate(); } /** * Set the primary sort field for the receiver. * * @param field */ void setPrimarySortField(MarkerField field) { getComparator().setPrimarySortField(field); } /** * Set the progress service for the receiver. * * @param service */ void setProgressService(IWorkbenchSiteProgressService service) { progressService = service; if (service != null) { service.showBusyForFamily(ResourcesPlugin.FAMILY_MANUAL_BUILD); service.showBusyForFamily(ResourcesPlugin.FAMILY_AUTO_BUILD); service.showBusyForFamily(MarkerContentGenerator.CACHE_UPDATE_FAMILY); } } /** * Set the updateJob for the receiver. * * @param job */ void setUpdateJob(Job job) { updateJob = job; } /** * Sort the newMarkers and build categories if required. * * @param monitor * @param newMarkers */ void sortAndMakeCategories(IProgressMonitor monitor, MarkerMap newMarkers) { // Allow the keys to get regenerated Arrays.sort(newMarkers.toArray(), getComparator()); monitor.worked(50); if (newMarkers.getSize() == 0) { categories = EMPTY_CATEGORY_ARRAY; currentMap = newMarkers; monitor.done(); return; } monitor.subTask(MarkerMessages.MarkerView_queueing_updates); if (monitor.isCanceled()) return; if (isShowingHierarchy()) { MarkerCategory[] newCategories = buildHierarchy(newMarkers, 0, newMarkers.getSize() - 1, 0); if (monitor.isCanceled()) return; categories = newCategories; } monitor.worked(50); currentMap = newMarkers; } /** * 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(); scheduleMarkerUpdate(); } /** * 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 updateFocusElements(Object[] elements) { Collection resourceCollection = new ArrayList(); for (int i = 0; i < elements.length; i++) { if (elements[i] instanceof IResource) { resourceCollection.add(elements[i]); } else { addResources(resourceCollection, ((ResourceMapping) elements[i])); } } focusResources = new IResource[resourceCollection.size()]; resourceCollection.toArray(focusResources); } /** * Update the receiver for a change in selection. * * @param newElements */ void updateForNewSelection(Object[] newElements) { if (updateNeeded(newElements)) { updateFocusElements(newElements); scheduleMarkerUpdate(); } } /** * Update the receiver from the dialog. * * @param dialog */ void updateFrom(FiltersConfigurationDialog dialog) { setAndFilters(dialog.andFilters()); filters = dialog.getFilters(); enabledFilters = null; writeFiltersPreference(); scheduleMarkerUpdate(); } /** * Return whether or not the list contains a resource that will require * regeneration. * * @return boolean <code>true</code> if regeneration is required. */ boolean updateNeeded(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 (focusResources.length == 0) return true; // We had nothing now we have something if (Arrays.equals(focusResources, newElements)) continue; if (scope == MarkerFieldFilterGroup.ON_ANY_IN_SAME_CONTAINER) { Collection oldProjects = MarkerFieldFilterGroup.getProjectsAsCollection(focusResources); Collection newProjects = MarkerFieldFilterGroup.getProjectsAsCollection(newElements); if (oldProjects.size() == newProjects.size() && newProjects.containsAll(oldProjects)) continue; return true;// Something must be different } return true; } return false; } /** * */ private void writeFiltersPreference() { XMLMemento memento = XMLMemento.createWriteRoot(TAG_FILTERS_SECTION); writeFiltersSettings(memento); StringWriter writer = new StringWriter(); try { memento.save(writer); } catch (IOException e) { IDEWorkbenchPlugin.getDefault().getLog().log(Util.errorStatus(e)); } IDEWorkbenchPlugin.getDefault().getPreferenceStore().putValue(getMementoPreferenceName(), writer.toString()); IDEWorkbenchPlugin.getDefault().savePluginPreferences(); } /** * 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); } } }