1 /******************************************************************************* 2 * Copyright (c) 2005, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.ui.views.markers.internal; 15 16 import java.util.ArrayList; 17 import java.util.Collection; 18 import java.util.HashMap; 19 import java.util.HashSet; 20 import java.util.Iterator; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Map.Entry; 24 import java.util.Set; 25 26 import org.eclipse.core.resources.IMarker; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IConfigurationElement; 29 import org.eclipse.core.runtime.IExtension; 30 import org.eclipse.core.runtime.IExtensionPoint; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.Platform; 33 import org.eclipse.core.runtime.Status; 34 import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; 35 import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; 36 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; 37 import org.eclipse.osgi.util.NLS; 38 import org.eclipse.ui.PlatformUI; 39 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; 40 import org.eclipse.ui.internal.ide.Policy; 41 import org.eclipse.ui.internal.views.markers.MarkerSupportInternalUtilities; 42 import org.eclipse.ui.views.markers.MarkerField; 43 44 /** 45 * The ProblemFilterRegistryReader is the registry reader for declarative 46 * problem filters. See the org.eclipse.ui.markerSupport extension point. 47 * 48 * @since 3.2 49 * 50 */ 51 public class MarkerSupportRegistry implements IExtensionChangeHandler { 52 53 private static final String DESCRIPTION = "onDescription"; //$NON-NLS-1$ 54 55 /** 56 * The enabled attribute. 57 */ 58 public static final String ENABLED = "enabled"; //$NON-NLS-1$ 59 60 private static final Object ERROR = "ERROR";//$NON-NLS-1$ 61 62 private static final Object INFO = "INFO";//$NON-NLS-1$ 63 64 private static final Object WARNING = "WARNING";//$NON-NLS-1$ 65 66 private static final String MARKER_ID = "markerId"; //$NON-NLS-1$ 67 68 /** 69 * Filter enablement : A zero/negative integer implies that the limit is 70 * disabled. 71 */ 72 public static final String FILTER_LIMIT = "filterLimit"; //$NON-NLS-1$ 73 74 /** 75 * The tag for the marker support extension 76 */ 77 public static final String MARKER_SUPPORT = "markerSupport";//$NON-NLS-1$ 78 79 private static final Object ON_ANY = "ON_ANY"; //$NON-NLS-1$ 80 81 private static final Object ON_ANY_IN_SAME_CONTAINER = "ON_ANY_IN_SAME_CONTAINER";//$NON-NLS-1$ 82 83 private static final Object ON_SELECTED_AND_CHILDREN = "ON_SELECTED_AND_CHILDREN";//$NON-NLS-1$ 84 85 private static final Object ON_SELECTED_ONLY = "ON_SELECTED_ONLY"; //$NON-NLS-1$ 86 87 private static final Object PROBLEM_FILTER = "problemFilter";//$NON-NLS-1$ 88 89 private static final String SCOPE = "scope"; //$NON-NLS-1$ 90 91 private static final String SELECTED_TYPE = "selectedType"; //$NON-NLS-1$ 92 93 private static final String SEVERITY = "severity";//$NON-NLS-1$ 94 95 /** 96 * The key for marker type references. 97 */ 98 public static final String MARKER_TYPE_REFERENCE = "markerTypeReference"; //$NON-NLS-1$ 99 100 private static final String MARKER_CATEGORY = "markerTypeCategory";//$NON-NLS-1$ 101 102 /** 103 * The markerAttributeMapping element. 104 */ 105 public static final String ATTRIBUTE_MAPPING = "markerAttributeMapping"; //$NON-NLS-1$ 106 107 /** 108 * The tag for marker grouping. 109 */ 110 public static final String MARKER_GROUPING = "markerGrouping"; //$NON-NLS-1$ 111 /** 112 * The value attribute. 113 */ 114 public static final String VALUE = "value"; //$NON-NLS-1$ 115 116 /** 117 * The label attribute 118 */ 119 public static final String LABEL = "label"; //$NON-NLS-1$ 120 121 /** 122 * The attribute grouping element name. 123 */ 124 public static final String MARKER_ATTRIBUTE_GROUPING = "markerAttributeGrouping";//$NON-NLS-1$ 125 126 /** 127 * The constant for grouping entries. 128 */ 129 public static final String MARKER_GROUPING_ENTRY = "markerGroupingEntry"; //$NON-NLS-1$ 130 131 private static final Object SEVERITY_ID = "org.eclipse.ui.ide.severity";//$NON-NLS-1$ 132 133 /** 134 * The tag for content generators. 135 */ 136 static final String MARKER_CONTENT_GENERATOR = "markerContentGenerator"; //$NON-NLS-1$ 137 138 /** 139 * The tag for content generator. 140 */ 141 private static final String MARKER_CONTENT_GENERATOR_EXTENSION = "markerContentGeneratorExtension"; //$NON-NLS-1$ 142 143 private static final String MARKER_FIELD = "markerField"; //$NON-NLS-1$ 144 145 private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$ 146 /** 147 * The bookmarks generator. 148 */ 149 public static final String BOOKMARKS_GENERATOR = "org.eclipse.ui.ide.bookmarksGenerator"; //$NON-NLS-1$ 150 /** 151 * The tasks generator. 152 */ 153 public static final String TASKS_GENERATOR = "org.eclipse.ui.ide.tasksGenerator"; //$NON-NLS-1$ 154 155 /** 156 * The problems generator. 157 */ 158 public static final String PROBLEMS_GENERATOR = "org.eclipse.ui.ide.problemsGenerator"; //$NON-NLS-1$ 159 160 161 /** 162 * The all markers generator. 163 */ 164 public static final String ALL_MARKERS_GENERATOR = "org.eclipse.ui.ide.allMarkersGenerator"; //$NON-NLS-1$ 165 166 /** 167 * The id for the new markers view. 168 */ 169 public static final String MARKERS_ID = "org.eclipse.ui.ide.MarkersView"; //$NON-NLS-1$; 170 171 private static final String ATTRIBUTE_GENERATOR_ID = "generatorId"; //$NON-NLS-1$ 172 173 private static MarkerSupportRegistry singleton; 174 175 /** 176 * Get the instance of the registry. 177 * 178 * @return MarkerSupportRegistry 179 */ getInstance()180 public static synchronized MarkerSupportRegistry getInstance() { 181 if (singleton == null) { 182 singleton = new MarkerSupportRegistry(); 183 } 184 return singleton; 185 } 186 187 private Map<String, ProblemFilter> registeredFilters = new HashMap<>(); 188 189 private Map<String, MarkerGroup> markerGroups = new HashMap<>(); 190 191 private Map<String, String> categories = new HashMap<>(); 192 193 private Map<String, TableComparator> hierarchyOrders = new HashMap<>(); 194 195 private MarkerType rootType; 196 197 private Map<String, ContentGeneratorDescriptor> generators = new HashMap<>(); 198 199 private Map<String, MarkerField> fields = new HashMap<>(); 200 201 /** 202 * Create a new instance of the receiver and read the registry. 203 */ MarkerSupportRegistry()204 private MarkerSupportRegistry() { 205 IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker(); 206 IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(IDEWorkbenchPlugin.IDE_WORKBENCH, 207 MARKER_SUPPORT); 208 if (point == null) { 209 return; 210 } 211 IExtension[] extensions = point.getExtensions(); 212 // initial population 213 Map<String, Collection<MarkerGroupingEntry>> groupingEntries = new HashMap<>(); 214 Map<String, Collection<IConfigurationElement>> generatorExtensions = new HashMap<>(); 215 Map<String, MarkerGroupingEntry> entryIDsToEntries = new HashMap<>(); 216 Set<AttributeMarkerGrouping> attributeMappings = new HashSet<>(); 217 for (IExtension extension : extensions) { 218 processExtension(tracker, extension, groupingEntries, 219 entryIDsToEntries, attributeMappings, generatorExtensions); 220 } 221 postProcessExtensions(groupingEntries, entryIDsToEntries, attributeMappings, generatorExtensions); 222 tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(point)); 223 } 224 225 /** 226 * Process the extension and register the result with the tracker. Fill the 227 * map of groupingEntries and attribueMappings processed for post 228 * processing. 229 * 230 * @param tracker 231 * @param extension 232 * @param groupIDsToEntries 233 * Mapping of group names to the markerGroupingEntries registered 234 * for them 235 * @param entryIDsToEntries 236 * Mapping of entry ids to entries 237 * @param attributeMappings 238 * the markerAttributeGroupings found 239 * @param generatorExtensions 240 * the markerContentGenerator extensions keyed on group id 241 * @see #postProcessExtensions(Map, Map, Collection, Map) 242 */ processExtension(IExtensionTracker tracker, IExtension extension, Map<String, Collection<MarkerGroupingEntry>> groupIDsToEntries, Map<String, MarkerGroupingEntry> entryIDsToEntries, Collection<AttributeMarkerGrouping> attributeMappings, Map<String, Collection<IConfigurationElement>> generatorExtensions)243 private void processExtension(IExtensionTracker tracker, IExtension extension, 244 Map<String, Collection<MarkerGroupingEntry>> groupIDsToEntries, 245 Map<String, MarkerGroupingEntry> entryIDsToEntries, 246 Collection<AttributeMarkerGrouping> attributeMappings, 247 Map<String, Collection<IConfigurationElement>> generatorExtensions) { 248 IConfigurationElement[] elements = extension.getConfigurationElements(); 249 250 for (IConfigurationElement element : elements) { 251 if (element.getName().equals(PROBLEM_FILTER)) { 252 ProblemFilter filter = newFilter(element); 253 registeredFilters.put(filter.getId(), filter); 254 tracker.registerObject(extension, filter, IExtensionTracker.REF_STRONG); 255 continue; 256 } 257 258 if (element.getName().equals(MARKER_GROUPING)) { 259 MarkerGroup group = MarkerGroup.createMarkerGroup(element); 260 markerGroups.put(group.getId(), group); 261 tracker.registerObject(extension, group, IExtensionTracker.REF_STRONG); 262 continue; 263 } 264 265 if (element.getName().equals(MARKER_GROUPING_ENTRY)) { 266 MarkerGroupingEntry entry = new MarkerGroupingEntry(element); 267 String groupName = element.getAttribute(MARKER_GROUPING); 268 Collection<MarkerGroupingEntry> entries = groupIDsToEntries.get(groupName); 269 if (entries == null) { 270 entries = new HashSet<>(); 271 } 272 273 entries.add(entry); 274 groupIDsToEntries.put(groupName, entries); 275 entryIDsToEntries.put(entry.getId(), entry); 276 277 tracker.registerObject(extension, entry, IExtensionTracker.REF_STRONG); 278 continue; 279 } 280 281 if (element.getName().equals(MARKER_ATTRIBUTE_GROUPING)) { 282 AttributeMarkerGrouping grouping = new AttributeMarkerGrouping(element); 283 attributeMappings.add(grouping); 284 tracker.registerObject(extension, grouping, IExtensionTracker.REF_STRONG); 285 continue; 286 } 287 288 if (element.getName().equals(MARKER_CATEGORY)) { 289 String[] markerTypes = getMarkerTypes(element); 290 String categoryName = element.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_NAME); 291 for (String markerType : markerTypes) { 292 categories.put(markerType, categoryName); 293 } 294 tracker.registerObject(extension, categoryName, IExtensionTracker.REF_STRONG); 295 continue; 296 } 297 298 if (element.getName().equals(MARKER_CONTENT_GENERATOR_EXTENSION)) { 299 String generatorName = element.getAttribute(ATTRIBUTE_GENERATOR_ID); 300 Collection<IConfigurationElement> extensionCollection = generatorExtensions.get(generatorName); 301 if (extensionCollection == null) { 302 extensionCollection = new ArrayList<>(); 303 } 304 305 extensionCollection.add(element); 306 generatorExtensions.put(generatorName, extensionCollection); 307 tracker.registerObject(extension, element, IExtensionTracker.REF_STRONG); 308 continue; 309 } 310 311 if (element.getName().equals(MARKER_CONTENT_GENERATOR)) { 312 ContentGeneratorDescriptor generatorDesc = new ContentGeneratorDescriptor(element); 313 generators.put(generatorDesc.getId(), generatorDesc); 314 tracker.registerObject(extension, generatorDesc, IExtensionTracker.REF_STRONG); 315 continue; 316 } 317 318 if (element.getName().equals(MARKER_FIELD)) { 319 processMarkerField(tracker, extension, element); 320 continue; 321 } 322 } 323 } 324 325 /** 326 * Create a table of MarkerFields 327 * 328 * @param tracker 329 * @param extension 330 * @param element 331 */ processMarkerField(IExtensionTracker tracker, IExtension extension, IConfigurationElement element)332 private void processMarkerField(IExtensionTracker tracker, IExtension extension, IConfigurationElement element) { 333 MarkerField field = null; 334 try { 335 field = (MarkerField) IDEWorkbenchPlugin.createExtension(element, ATTRIBUTE_CLASS); 336 field.setConfigurationElement(element); 337 } catch (CoreException e) { 338 Policy.handle(e); 339 } 340 341 if (field != null) { 342 fields.put(element.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID), field); 343 } 344 tracker.registerObject(extension, field, IExtensionTracker.REF_STRONG); 345 } 346 347 /** 348 * Process the cross references after all of the extensions have been read. 349 * 350 * @param groupIDsToEntries 351 * Mapping of group names to the markerGroupingEntries registered 352 * for them 353 * @param entryIDsToEntries 354 * Mapping of entry names to the mappings for them 355 * @param attributeMappings 356 * the markerAttributeGroupings found 357 * @param generatorExtensions 358 * map of generator id to generator descriptors 359 */ postProcessExtensions(Map<String, Collection<MarkerGroupingEntry>> groupIDsToEntries, Map<String, MarkerGroupingEntry> entryIDsToEntries, Collection<AttributeMarkerGrouping> attributeMappings, Map<String, Collection<IConfigurationElement>> generatorExtensions)360 private void postProcessExtensions(Map<String, Collection<MarkerGroupingEntry>> groupIDsToEntries, 361 Map<String, MarkerGroupingEntry> entryIDsToEntries, Collection<AttributeMarkerGrouping> attributeMappings, 362 Map<String, Collection<IConfigurationElement>> generatorExtensions) { 363 processGroupingEntries(groupIDsToEntries); 364 processAttributeMappings(entryIDsToEntries, attributeMappings); 365 postProcessContentGenerators(generatorExtensions); 366 } 367 368 /** 369 * Set up the fields and filters 370 * 371 * @param generatorExtensions 372 * the extensions to the generators, 373 */ postProcessContentGenerators(Map<String, Collection<IConfigurationElement>> generatorExtensions)374 private void postProcessContentGenerators(Map<String, Collection<IConfigurationElement>> generatorExtensions) { 375 Iterator<ContentGeneratorDescriptor> generatorIterator = generators.values().iterator(); 376 while (generatorIterator.hasNext()) { 377 ContentGeneratorDescriptor generatorDesc = generatorIterator.next(); 378 generatorDesc.initializeFromConfigurationElement(this); 379 Collection<IConfigurationElement> extensions = generatorExtensions.get(generatorDesc.getId()); 380 if (extensions != null) { 381 generatorDesc.addExtensions(extensions); 382 } 383 } 384 385 } 386 387 /** 388 * Process the grouping entries into thier required grouping entries. 389 * 390 * @param groupingEntries 391 */ processGroupingEntries(Map<String, Collection<MarkerGroupingEntry>> groupingEntries)392 private void processGroupingEntries(Map<String, Collection<MarkerGroupingEntry>> groupingEntries) { 393 for (Entry<String, Collection<MarkerGroupingEntry>> entry : groupingEntries.entrySet()) { 394 String nextGroupId = entry.getKey(); 395 MarkerGroup group = markerGroups.get(nextGroupId); 396 if (group != null) { 397 for (MarkerGroupingEntry markerGroupingEntry : entry.getValue()) { 398 markerGroupingEntry.setGroup(group); 399 } 400 } else { 401 for (MarkerGroupingEntry markerGroupingEntry : entry.getValue()) { 402 IDEWorkbenchPlugin.log(NLS.bind("markerGroupingEntry {0} defines invalid group {1}", //$NON-NLS-1$ 403 new String[] { markerGroupingEntry.getId(), nextGroupId })); 404 } 405 } 406 } 407 } 408 409 /** 410 * Process the attribute mappings into thier required grouping entries. 411 * 412 * @param entryIDsToEntries 413 * @param attributeMappings 414 */ processAttributeMappings(Map<String, MarkerGroupingEntry> entryIDsToEntries, Collection<AttributeMarkerGrouping> attributeMappings)415 private void processAttributeMappings(Map<String, MarkerGroupingEntry> entryIDsToEntries, 416 Collection<AttributeMarkerGrouping> attributeMappings) { 417 Iterator<AttributeMarkerGrouping> mappingsIterator = attributeMappings.iterator(); 418 while (mappingsIterator.hasNext()) { 419 AttributeMarkerGrouping attributeGrouping = mappingsIterator.next(); 420 String defaultEntryId = attributeGrouping.getDefaultGroupingEntry(); 421 if (defaultEntryId != null) { 422 MarkerGroupingEntry entry = entryIDsToEntries.get(defaultEntryId); 423 if (entry != null) { 424 entry.setAsDefault(attributeGrouping.getMarkerType()); 425 } else { 426 IDEWorkbenchPlugin.log(NLS.bind( 427 "Reference to invalid markerGroupingEntry {0}",//$NON-NLS-1$ 428 defaultEntryId)); 429 } 430 } 431 IConfigurationElement[] mappings = attributeGrouping.getElement().getChildren(ATTRIBUTE_MAPPING); 432 433 for (IConfigurationElement mapping : mappings) { 434 String entryId = mapping.getAttribute(MARKER_GROUPING_ENTRY); 435 436 MarkerGroupingEntry entry = entryIDsToEntries.get(entryId); 437 if (entry != null) { 438 entry.getMarkerGroup().mapAttribute(attributeGrouping, entry, mapping.getAttribute(VALUE)); 439 } else { 440 IDEWorkbenchPlugin.log(NLS.bind( 441 "Reference to invaild markerGroupingEntry {0}", //$NON-NLS-1$ 442 defaultEntryId)); 443 } 444 } 445 } 446 } 447 448 /** 449 * Get the markerTypes defined in element. 450 * 451 * @param element 452 * @return String[] 453 */ getMarkerTypes(IConfigurationElement element)454 private String[] getMarkerTypes(IConfigurationElement element) { 455 IConfigurationElement[] types = element 456 .getChildren(MARKER_TYPE_REFERENCE); 457 String[] ids = new String[types.length]; 458 for (int i = 0; i < ids.length; i++) { 459 ids[i] = types[i].getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_ID); 460 } 461 return ids; 462 } 463 464 @Override addExtension(IExtensionTracker tracker, IExtension extension)465 public void addExtension(IExtensionTracker tracker, IExtension extension) { 466 Map<String, Collection<MarkerGroupingEntry>> groupIDsToEntries = new HashMap<>(); 467 Map<String, MarkerGroupingEntry> entryIDsToEntries = new HashMap<>(); 468 Map<String, Collection<IConfigurationElement>> generatorExtensions = new HashMap<>(); 469 Set<AttributeMarkerGrouping> attributeMappings = new HashSet<>(); 470 processExtension(tracker, extension, groupIDsToEntries, entryIDsToEntries, attributeMappings, generatorExtensions); 471 postProcessExtensions(groupIDsToEntries, entryIDsToEntries, attributeMappings, generatorExtensions); 472 } 473 474 /** 475 * Get the collection of currently registered filters. 476 * 477 * @return Collection of ProblemFilter 478 */ getRegisteredFilters()479 public Collection<ProblemFilter> getRegisteredFilters() { 480 Collection<ProblemFilter> filteredFilters = new ArrayList<>(); 481 Iterator<ProblemFilter> registeredIterator = registeredFilters.values().iterator(); 482 while (registeredIterator.hasNext()) { 483 ProblemFilter next = registeredIterator.next(); 484 if (next.isFilteredOutByActivity()) { 485 continue; 486 } 487 filteredFilters.add(next); 488 } 489 return filteredFilters; 490 } 491 492 /** 493 * Get the constant for scope from element. Return -1 if there is no value. 494 * 495 * @param element 496 * @return int one of MarkerView#ON_ANY MarkerView#ON_SELECTED_ONLY 497 * MarkerView#ON_SELECTED_AND_CHILDREN 498 * MarkerView#ON_ANY_IN_SAME_CONTAINER 499 */ getScopeValue(IConfigurationElement element)500 private int getScopeValue(IConfigurationElement element) { 501 String scope = element.getAttribute(SCOPE); 502 if (scope == null) { 503 return -1; 504 } 505 if (scope.equals(ON_ANY)) { 506 return MarkerFilter.ON_ANY; 507 } 508 if (scope.equals(ON_SELECTED_ONLY)) { 509 return MarkerFilter.ON_SELECTED_ONLY; 510 } 511 if (scope.equals(ON_SELECTED_AND_CHILDREN)) { 512 return MarkerFilter.ON_SELECTED_AND_CHILDREN; 513 } 514 if (scope.equals(ON_ANY_IN_SAME_CONTAINER)) { 515 return MarkerFilter.ON_ANY_IN_SAME_CONTAINER; 516 } 517 return -1; 518 } 519 520 /** 521 * Get the constant for scope from element. Return -1 if there is no value. 522 * 523 * @param element 524 * @return int one of MarkerView#ON_ANY MarkerView#ON_SELECTED_ONLY 525 * MarkerView#ON_SELECTED_AND_CHILDREN 526 * MarkerView#ON_ANY_IN_SAME_CONTAINER 527 */ getSeverityValue(IConfigurationElement element)528 private int getSeverityValue(IConfigurationElement element) { 529 String severity = element.getAttribute(SEVERITY); 530 if (severity == null) { 531 return -1; 532 } 533 if (severity.equals(INFO)) { 534 return ProblemFilter.SEVERITY_INFO; 535 } 536 if (severity.equals(WARNING)) { 537 return ProblemFilter.SEVERITY_WARNING; 538 } 539 if (severity.equals(ERROR)) { 540 return ProblemFilter.SEVERITY_ERROR; 541 } 542 return -1; 543 } 544 545 /** 546 * Read the problem filters in the receiver. 547 * 548 * @param element 549 * the filter element 550 * @return ProblemFilter 551 */ newFilter(IConfigurationElement element)552 private ProblemFilter newFilter(IConfigurationElement element) { 553 ProblemFilter filter = new ProblemFilter(element.getAttribute(MarkerSupportInternalUtilities.ATTRIBUTE_NAME)); 554 555 filter.createContributionFrom(element); 556 557 String enabledValue = element.getAttribute(ENABLED); 558 filter.setEnabled(enabledValue == null || Boolean.parseBoolean(enabledValue)); 559 560 int scopeValue = getScopeValue(element); 561 if (scopeValue >= 0) { 562 filter.setOnResource(scopeValue); 563 } 564 565 String description = element.getAttribute(DESCRIPTION); 566 if (description != null) { 567 boolean contains = true; 568 if (description.charAt(0) == '!') {// does not contain flag 569 description = description.substring(1, description.length()); 570 contains = false; 571 } 572 filter.setContains(contains); 573 filter.setDescription(description); 574 } 575 576 int severityValue = getSeverityValue(element); 577 if (severityValue > 0) { 578 filter.setSelectBySeverity(true); 579 filter.setSeverity(severityValue); 580 } else { 581 filter.setSelectBySeverity(false); 582 } 583 584 List<MarkerType> selectedTypes = new ArrayList<>(); 585 for (IConfigurationElement type : element.getChildren(SELECTED_TYPE)) { 586 String markerId = type.getAttribute(MARKER_ID); 587 if (markerId != null) { 588 MarkerType markerType = filter.getMarkerType(markerId); 589 if (markerType == null) { 590 IStatus status = new Status(IStatus.WARNING, IDEWorkbenchPlugin.IDE_WORKBENCH, IStatus.WARNING, 591 NLS.bind(MarkerMessages.ProblemFilterRegistry_nullType, 592 new Object[] { markerId, filter.getName() }), 593 null); 594 IDEWorkbenchPlugin.getDefault().getLog().log(status); 595 } else { 596 selectedTypes.add(markerType); 597 } 598 } 599 } 600 601 if (selectedTypes.size() > 0) { 602 // specified 603 filter.setSelectedTypes(selectedTypes); 604 } 605 return filter; 606 } 607 608 @Override removeExtension(IExtension extension, Object[] objects)609 public void removeExtension(IExtension extension, Object[] objects) { 610 611 for (Object object : objects) { 612 if (object instanceof ProblemFilter) { 613 registeredFilters.remove(object); 614 continue; 615 } 616 617 if (object instanceof MarkerGroup) { 618 markerGroups.remove(((MarkerGroup) object).getId()); 619 continue; 620 } 621 622 if (object instanceof MarkerGroupingEntry) { 623 MarkerGroupingEntry entry = (MarkerGroupingEntry) object; 624 entry.getMarkerGroup().remove(entry); 625 continue; 626 } 627 628 if (object instanceof AttributeMarkerGrouping) { 629 AttributeMarkerGrouping entry = (AttributeMarkerGrouping) object; 630 entry.unmap(); 631 continue; 632 } 633 634 if (object instanceof String) { 635 removeValues((String) object, categories); 636 continue; 637 } 638 639 if (object instanceof MarkerField) { 640 fields.remove(MarkerSupportInternalUtilities.getId((MarkerField) object)); 641 continue; 642 } 643 644 if (object instanceof ContentGeneratorDescriptor) { 645 generators.remove(((ContentGeneratorDescriptor) object).getId()); 646 continue; 647 } 648 649 if (object instanceof IConfigurationElement) { 650 IConfigurationElement element = (IConfigurationElement) object; 651 ContentGeneratorDescriptor generatorDesc = generators.get(element.getAttribute(ATTRIBUTE_GENERATOR_ID)); 652 generatorDesc.removeExtension(element); 653 continue; 654 } 655 } 656 } 657 658 /** 659 * Remove the value from all of the collection sets in cache. If the 660 * collection is empty remove the key as well. 661 * 662 * @param value 663 * @param cache 664 */ removeValues(String value, Map<String, String> cache)665 private void removeValues(String value, Map<String, String> cache) { 666 Collection<String> keysToRemove = new ArrayList<>(); 667 for (Entry<String, String> entry : cache.entrySet()) { 668 if (entry.getValue().equals(value)) { 669 keysToRemove.add(entry.getKey()); 670 } 671 } 672 for (String toRemove : keysToRemove) { 673 cache.remove(toRemove); 674 } 675 } 676 677 /** 678 * Get the category associated with marker. Return <code>null</code> if 679 * there are none. 680 * 681 * @param marker 682 * @return String or <code>null</code> 683 */ getCategory(IMarker marker)684 public String getCategory(IMarker marker) { 685 try { 686 return getCategory(marker.getType()); 687 } catch (CoreException e) { 688 Policy.handle(e); 689 } 690 return null; 691 } 692 693 /** 694 * Get the category associated with markerType. Return <code>null</code> 695 * if there are none. 696 * 697 * @param markerType 698 * @return String or <code>null</code> 699 */ getCategory(String markerType)700 public String getCategory(String markerType) { 701 return categories.get(markerType); 702 } 703 704 /** 705 * Return the TableSorter that corresponds to type. 706 * 707 * @param type 708 * @return TableSorter 709 */ getSorterFor(String type)710 public TableComparator getSorterFor(String type) { 711 TableComparator sorter = hierarchyOrders.get(type); 712 if (sorter != null) { 713 return sorter; 714 } 715 716 sorter = findSorterInChildren(type, getRootType()); 717 if (sorter == null) { 718 return new TableComparator(new IField[0], new int[0], new int[0]); 719 } 720 return sorter; 721 } 722 723 /** 724 * Return the list of root marker types. 725 * 726 * @return List of MarkerType. 727 */ getRootType()728 private MarkerType getRootType() { 729 if (rootType == null) { 730 rootType = (MarkerTypesModel.getInstance()).getType(IMarker.PROBLEM); 731 } 732 return rootType; 733 } 734 735 /** 736 * Find the best match sorter for typeName in the children. If it cannot be 737 * found then return <code>null</code>. 738 * 739 * @param typeName 740 * @param type 741 * @return TableSorter or <code>null</code>. 742 */ findSorterInChildren(String typeName, MarkerType type)743 private TableComparator findSorterInChildren(String typeName, MarkerType type) { 744 for (MarkerType markerSubType : type.getAllSubTypes()) { 745 MarkerType[] subtypes = markerSubType.getAllSubTypes(); 746 for (MarkerType subtype : subtypes) { 747 TableComparator sorter = findSorterInChildren(typeName, subtype); 748 if (sorter != null) { 749 return sorter; 750 } 751 } 752 } 753 return hierarchyOrders.get(type.getId()); 754 } 755 756 /** 757 * Return the FieldMarkerGroups in the receiver. 758 * 759 * @return Collection of {@link MarkerGroup} 760 */ getMarkerGroups()761 public Collection<MarkerGroup> getMarkerGroups() { 762 return markerGroups.values(); 763 } 764 765 /** 766 * Return the default groupfield. 767 * 768 * @return IField 769 */ getDefaultGroupField()770 IField getDefaultGroupField() { 771 return markerGroups.get(SEVERITY_ID).getField(); 772 } 773 774 /** 775 * Get the generator descriptor for id 776 * 777 * @param id 778 * @return ContentGeneratorDescriptor or <code>null</code>. 779 */ getContentGenDescriptor(String id)780 public ContentGeneratorDescriptor getContentGenDescriptor (String id) { 781 if (id != null) { 782 return generators.get(id); 783 } 784 return null; 785 } 786 787 /** 788 * Return the default content generator descriptor. 789 * 790 * @return ContentGeneratorDescriptor 791 */ getDefaultContentGenDescriptor()792 public ContentGeneratorDescriptor getDefaultContentGenDescriptor () { 793 return generators.get(PROBLEMS_GENERATOR); 794 } 795 796 /** 797 * Get the markerGroup associated with categoryName 798 * 799 * @param categoryName 800 * @return FieldMarkerGroup or <code>null</code> 801 */ getMarkerGroup(String categoryName)802 public MarkerGroup getMarkerGroup(String categoryName) { 803 return markerGroups.get(categoryName); 804 } 805 806 /** 807 * Return the field that maps to id. 808 * 809 * @param id 810 * @return {@link MarkerField} or <code>null</code> 811 */ getField(String id)812 public MarkerField getField(String id) { 813 return fields.get(id); 814 } 815 816 } 817