| Some notes about the CNF in attempt to understand things. |
| |
| 30 Nov 08 FRU |
| |
| Documentation notes: |
| |
| There is some good text potentially for the docs in: |
| |
| https://bugs.eclipse.org/bugs/show_bug.cgi?id=195595 |
| |
| |
| |
| Navigator Content |
| |
| The purpose of the navigatorContent extension (NCE) is to bind a content provider |
| and label provider to the navigator under the right circumstances depending |
| on what is selected. |
| |
| A navigator content descriptor has a one-to-one correspondence with the |
| navigator content extension, which is the higher level object representing |
| the navigator content. |
| |
| Overriding |
| |
| An NCE may specify that it overrides another through the user of the override |
| mechanism where it specifies the NCE extension ID of the extension to override. |
| |
| When doing the processing associated with the label and content provider, it is possible |
| that multiple NCEs meet the criteria for processing based on their triggerPoints and/or |
| possibleChildren. When this happens, the NCEs are ordered in a tree based |
| on the overrides specification, and then with that based on priority. |
| The first NCE in the tree that provides the answer (label or content) being |
| sought is used. |
| |
| When the NCE is bound to the viewer (using the contentExtension element) it may |
| specify that that NCE serves as "root content" for that viewer, which allows |
| the viewer to start with an initial set of NCEs to process the root(s) [why exactly -- |
| I understand intuitively but can't put it into words]. |
| |
| |
| Pipelining |
| |
| In some cases, it is desirable to have multiple NCEs be invoked during |
| content provider processing to modify the objects to be returned by the |
| content provider. This is done using the pipelining mechanism where each NCE |
| in the tree has the opportunity to modify the objects to be returned by the |
| content provider. There are also hooks for these pipelined NCEs to |
| be invoked at the Add/Remove/Update/Refresh methods on the viewer. |
| |
| |
| Selecting a Content Extension (NCE) |
| |
| This is done either through the possibleChildren or triggerPoints expression |
| on the NCE. The enablement expression expression specifies the same expression |
| for both triggerPoints and possibleChildren. |
| |
| The triggerPoints expression is used: |
| |
| - by the NavigatorContentServiceContentProvider |
| to find extensions for getElements() (through the root content extensions) |
| or getChildren(). Given a parent node, that content extension is used |
| to determine what children to provide. |
| - by the NavigatorPipelineService for ??? |
| |
| The possibleChildren expression is used for all other cases, which include: |
| |
| - Label/icon/description provider |
| - Selecting the NCE for a drop |
| |
| The current documentation on these uses is incorrect, in particular for |
| the label provides, it says that the triggerPoints expression is used, but |
| it's not. |
| |
| |
| |
| |
| |
| |
| Dependency |
| |
| Questions/Issues: |
| |
| 1) In NavigatorContentServicedLabelProvider, seems that we look for |
| label providers by looking for matching NCEs by possibleChild. |
| However the documentation is clear that content and label providers |
| are found by triggerPoint, possibleChild is used only in the content |
| provider getParent() case. |
| |
| <mde>The API documentation for label providers is wrong. It has always been |
| the case that label providers rely on the possibleChildren; we should |
| correct the doc since actual implementations are relying on the |
| behavior of label providers using possible children (but only in |
| cases where the framework can't determine which extension contributed |
| the content with its short term memory mechanism). |
| Other parts of the framework (like the DND Drop Handlers) also rely on |
| possible children to determine which content extension's handlers |
| should be invoked when processing a drop operation. </mde> |
| |
| |
| 2) In NavigatorContentServiceLabel provider, there seems to be special |
| processing to handle overriding instead of using the normal processing |
| to get only the relevant NCEs. Also, the way to get the NCEs is |
| different depending on whether doing a getImage() or getForeground() |
| for example and I don't understand why. Also |
| NavigatorContentServiceDescriptionProvider does not seem to consider |
| overrides at all. This all seems wrong. |
| |
| <mde> |
| The content extension has alot of complexity because it has to |
| determine the overrides for each individual child along the path. |
| Labels are a bit simpler because only one value can be returned. |
| The override logic recursively walks the override path by the highest |
| priority label provider. Overriding label providers can opt not to |
| return a label (e.g. null), and the framework will fall back on the |
| base label provider to provide a value. |
| |
| The getForeground()/getFont() cases weren't retrofitted for |
| overriding values. This was just a legacy/point in time and |
| is arguably a bug. The Font and Color providers were added to |
| support the Team providers (they weren't part of the original product |
| framework). If anything, the getFont()/Foreground/Background() |
| methods should be retrofitted to follow the patter in getText/Image(). |
| </mde> |
| |
| |
| 3) The triggerPoints and possibleChildren descriptions in the exsd are |
| confusing: |
| |
| "The triggerPoints expression defines the nodes in a tree that should |
| cause this extension to be invoked for children." |
| |
| "The possibleChildren expression defines the nodes in a tree that |
| could be contributed by this extension. Clients should describes when |
| this content extension could provide a parent for elements that match |
| the expression." |
| |
| I think a clearer description is: |
| |
| The triggerPoints expression defines the tree nodes for which this |
| extension (and associated content/label providers) is to be invoked. |
| |
| <mde>Remove "label providers" and we're good. </mde> |
| |
| The possibleChildren expression defines the content provider to be |
| selected when processing the ITreeContentProvider.getParent() call. |
| |
| <mde>As well as the DND Drop Handler and Action Providers.</mde> |
| |
| 4) Why is the overridden tree computed only on |
| findDescriptorsForPossibleChild and not for |
| findDescriptorsForTriggerPoint? The extension point documentation for |
| the overrides element says that the overrides only applied to |
| triggerpoints, it does not mention possibleChildren (except in |
| reference to the OnlySuppressedifExtVisibleAndActive option is set, |
| but it still seems to say that only triggerPoints is actually used). |
| |
| <mde>It might be worth setting up an hour to go through a deep dive |
| for this material. If I recall correctly, there was a challenge in |
| computing all of the triggerpoint overrides a priori, but the |
| overrides are used. The NavigatorContentServiceContentProvider |
| processes a given element for children (e.g. getChildren()), |
| and then invokes the overridden providers directly (from within |
| the Service content provider) to compute the overridden tree. |
| The possible children through doesn't have a use case like this, |
| and so these can be computed and returned as needed.</mde> |
| |
| 5) More confusion (from the overrides exsd): |
| |
| "InvokeAlwaysRegardlessOfSuppressedExt (default): Indicates that this |
| extension is a first class extension; it should be given opportunities |
| to contribute content regardless if its suppressedExtensionId is |
| visible or active to the viewer. Thus, the extension is a first-class |
| extension and an overriding extension. It will be invoked whenever its |
| triggerPoints expression is matched. When the suppressed extension and |
| its triggerPoints extension is matched, it will be invoked with the |
| contributed items from its suppressed extension; the suppressed |
| extension will not be given an opportunity to directly contribute." |
| |
| The last sentence of this is unclear. I think it would be better (and |
| consistent with the rest of the explanations) if the suppressed |
| extension was just suppressed, it is never invoked at all. |
| |
| <mde>The use cases here are as follows: |
| |
| 1. I want to contribute my stuff, and I want to specialize an existing provider |
| like Java, and |
| |
| 2. I want to just specialize another provider, and if it's not turned on, I don't |
| even need to be considered. |
| |
| So in neither case is it completely suppressed, but rather in case 2 it acts |
| like a domino of its source provider. I just want to make sure we don't |
| lose this meaning in the update of the documentation </mde> |
| |
| |
| 6) Should the NCE class and NavigatorContentDescriptor classes be |
| combined? They seem to be one-to-one and there is a lot of code that |
| seems to convert from one to another for no good reason. |
| |
| <mde>The Descriptor/Extension pattern is used for every part of the framework, here's why: |
| |
| A Manager handles Descriptors; Managers are singletons, and each known extension |
| has exactly one Descriptor. The state associated with a Descriptor is just an API |
| convenience layer on top of the IConfigurationElement API. These are relatively |
| lightweight, and their lifecycle is the lifecycle of the Manager, which is |
| effectively the lifecycle of the workbench. |
| |
| A Service handles Extensions; Services are 1 instance per Common Navigator viewer |
| (or whatever client is using the Service). Each Service creates an Extension |
| and manages a map from Descriptor (1 instance for each extension for all |
| viewers) to its Extension (1 instance for each instance viewer). The Extension |
| instance creates instances of classes defined by the plugin extension metadata; |
| each of these instances has an associated lifecycle (init .. do work .. dispose) |
| and can hold on to system resources (label providers can hold Fonts or Colors, |
| content providers might talk to a data source across a network). Most of these |
| classes aren't necessarily designed to be re-entrant (they make assumptions |
| about the current state of a given viewer, like whether to show |
| Packages as hierarchical or flattened). So if I create a Project Explorer, |
| and then separately create a MyCustomView and bind Java to each of them, |
| I'll have 1 Java Descriptor, and 2 Java Extensions in memory. |
| |
| Collapsing Descriptors into Extensions would be a fundamental change to the |
| framework, eliminate the assumption that there's 1 content |
| provider/label provider/etc for each view instance, and make it hard or |
| impossible to know when each of the instantiated classes from each |
| plugin extension can be disposed. I would not recommend this. |
| </mde> |
| |
| |
| 7) There are substantial chunks of duplicate code where only one |
| line is different between the similar methods. |
| |
| <mde>If you can provide a few examples, I might be able to provide some |
| insights here; in many cases, I tried to use the same simple patterns |
| throughout the frameworks to keep the overall complexity down, which |
| can lead to this kind of pattern.</mde> |
| |
| |