39.1
Resolver hooks

Note Resolvers have quite a history in QF-Test. In version 2.0 SWT support was added to QF-Test. The ComponentNameResolver interface of previous QF-Test versions had been built for AWT/Swing Components and was not portable. It was replaced with the more generic NameResolver interface and associated ResolverRegistry methods.

With QF-Test version 3.1, both NameResolver and FeatureResolver were replaced with more elegant versions named - for lack of alternatives - NameResolver2 and FeatureResolver2. These modern versions pass the default name or feature determined by QF-Test directly to the resolver's method which greatly simplifies implementation of the interface.

Similarly, the old ItemNameResolver that was only available for Swing was replaced with the new ItemNameResolver2 with a matching ItemValueResolver2, which work for all engines. For backwards compatibility all the old interfaces and methods are still available and will continue to work, but they should no longer be used in new tests and are no longer documented here.

39.1.1
Overview over the supported kinds of resolvers

This extension API lets you install hooks that can modify the way QF-Test recognizes and records components and items. This is a very powerful feature that gives you fine-grained control over QF-Test's component management. It is far less complicated than it looks. Using the resolvers module described in subsection 39.1.10, a full featured resolver can be implemented and installed with a minimum of code.

The following kinds of hooks are currently provided:

Multiple resolvers with different tasks can be created and registered at run-time. The respective interfaces can be implemented directly by Java classes. However, this would make the code of your application depend on QF-Test classes. The preferred alternative is to implement the resolver interfaces in Jython or Groovy, ideally via the Jython resolvers module or the Groovy Resolvers class. That way the whole mechanism can be strictly separated from the SUT and will not interfere with the build process.

Before we explain how to (un-)register resolvers, we'll take a look at their interfaces.

3.1+39.1.2
The ClassNameResolver interface

The de.qfs.apps.qftest.extensions.ClassNameResolver interface consists of a single method:

 
 
String getClassName(Object element, String name)
Determine the name of the class of a GUI element.
Parameters
element The element to determine the class name for.
name The original class name that QF-Test would use without a resolver.
Returns The class name to use or null if the element is not handled by this resolver.
 
 

After QF-Test determines the class name of a GUI element the registered ClassNameResolvers get a chance to override this class name. The first resolver that returns a non-null value determines the outcome. If no resolvers are registered or all of them return null the original class name is used.

For Swing and SWT applications classes are matched based on actual class hierarchy, so the ClassNameResolver is restricted to the actual class of the element or any of its base classes. It can still be useful in case you don't want to activate the option Record system class only but still record a system class or some other general base class for certain components. Swing and SWT classes are not cached so the resolver is called every time QF-Test needs the class of an element.

For web applications QF-Test uses a pseudo class hierarchy which is described in section 6.4. The resolver is free to return any arbitrary class name, which QF-Test then treats like a sub-class of the element's pseudo class. For performance reasons classes are cached for web elements so the resolver will only be called at most once for each element.

3.1+39.1.3
The NameResolver2 interface

The de.qfs.apps.qftest.extensions.NameResolver2 interface consists of a single method:

 
 
String getName(Object element, String name)
Determine the name of a GUI element.
Parameters
element The element to determine the name for.
name The original name that QF-Test would use without a resolver.
Returns The name to use or null if the element is not handled by this resolver. Returning an empty string suppresses the original name.
 
 

After QF-Test determines the name of a GUI element the registered NameResolvers get a chance to override or suppress this name. The first resolver that returns a non-null value determines the outcome. If no resolvers are registered or all of them return null the original name is used.

In some cases it may be desirable to suppress an element's name, for example for names which are not unique or which - even worse - vary depending on the situation. To do so, getName should return the empty string.

Web39.1.4
The IdResolver interface

The de.qfs.apps.qftest.extensions.IdResolver interface consists of a single method:

 
 
String getId(DomNode node, String id)
Determine the ID of a DomNode. The resolved ID will be cached and can later be retrieved via node.getId(), whereas node.getAttribute("id") always returns the original, unmodified ID.
Parameters
node The DomNode to determine the ID for.
id The "id" attribute that QF-Test has determined, possibly with suppressed numerals, depending on the setting of the option Eliminate all numerals from 'id' attributes. To implement the resolver based on the original "id" attribute, simply fetch this with node.getAttribute("id").
Returns The ID or null if the element is not handled by this resolver. Returning an empty string will suppress or hide the node's actual ID.
 
 

When QF-Test registers the nodes of a web page's DOM it also caches the "id" attribute of those nodes. Since many web applications are based on automatically generated IDs, some processing is often required, similar to the suppression of numerals that QF-Test does automatically, depending on the option Eliminate all numerals from 'id' attributes.

The "id" attribute of a node can show up in multiple places, most notably as the node's 'Name' (depending on the option Turn 'id' attribute into name where "unique enough"), its 'Feature' and an 'Extra feature'. Thus it is much more efficient to implement an IdResolver to modify the ID once, than to implement separate Name-, Feature- and ExtraFeatureResolvers. More importantly, changing a node's "id" attribute can have a major impact on whether the attribute is unique and QF-Test's mechanism for using an ID as a 'Name' takes uniqueness into account, so an IdResolver is allowed to return non-unique IDs whereas a NameResolver2 is not.

3.1+39.1.5
The FeatureResolver2 interface

The de.qfs.apps.qftest.extensions.FeatureResolver2 interface consists of a single method:

 
 
String getFeature(Object element, String feature)
Determine the feature of a GUI element.
Parameters
element The element to determine the feature for.
feature The original feature that QF-Test would use without a resolver.
Returns The feature to use or null if the element is not handled by this resolver. Returning an empty string suppresses the original feature.
 
 

After QF-Test determines the feature of a GUI element the registered FeatureResolvers get a chance to override or suppress this feature. The first resolver that returns a non-null value determines the outcome. If no resolvers are registered or all of them return null the original feature is used.

To suppress an element's feature, getFeature should return the empty string.

39.1.6
The ExtraFeatureResolver interface

The de.qfs.apps.qftest.extensions.ExtraFeatureResolver interface consists of a single method:

 
 
ExtraFeatureSet getExtraFeatures(Object element, ExtraFeatureSet features)
Determine extra features for a GUI element.
Parameters
element The element to determine the extra features for.
features The extra features determined by QF-Test itself, an empty set in case there are none. These can be modified in place or ignored and a different ExtraFeatureSet returned.
ReturnsThe original features modified in place or a different set, null if the element is not handled by this resolver. To suppress all the element's original extra features return an empty ExtraFeatureSet.
 
 

After QF-Test has determined the extra features for a GUI element, the registered ExtraFeatureResolvers will get a chance to override these features. In contrast to other resolvers, QF-Test does not stop when the first resolver returns a non-null value. Instead it passes its result as input to the next resolver which makes it possible to register several ExtraFeatureResolvers that handle different extra features. If no resolvers are registered or all of them return null, QF-Test will proceed to use the original set.

Of course, in order to be able to implement the getExtraFeatures method properly, you need to know the details for the API of the classes involved, namely ExtraFeature and ExtraFeatureSet. These are explained below. For an example implementation please see example 39.6.

Instances of the class de.qfs.apps.qftest.shared.data.ExtraFeature represent one extra feature for a GUI element, comprising its name and value along with information about whether the feature is expected to match, whether it is a regular expression and whether the match should be negated. For possible states the class defines the constants STATE_IGNORE, STATE_SHOULD_MATCH and STATE_MUST_MATCH.

 
 
ExtraFeature (String name, String value)
Create a new ExtraFeature with the default state STATE_IGNORE.
Parameters
nameThe name of the ExtraFeature.
valueThe value of the ExtraFeature.
 
ExtraFeature (int state, String name, String value)
Create a new ExtraFeature with a given state.
Parameters
state The state of the ExtraFeature. Possible values are STATE_IGNORE, STATE_SHOULD_MATCH, STATE_MUST_MATCH.
nameThe name of the ExtraFeature.
valueThe value of the ExtraFeature.
 
int getState()
Get the state of the ExtraFeature.
ReturnsThe state of the ExtraFeature.
 
void setState(int state)
Set the state of the ExtraFeature.
Parameters
stateThe state to set.
 
String getName()
Get the name of the ExtraFeature.
ReturnsThe name of the ExtraFeature.
 
void setName(String name)
Set the name of the ExtraFeature.
Parameters
nameThe name to set.
 
String getValue()
Get the value of the ExtraFeature.
ReturnsThe value of the ExtraFeature.
 
void setValue(String value)
Set the value of the ExtraFeature.
Parameters
valueThe value to set.
 
boolean getRegexp()
Get the regexp state of the ExtraFeature.
ReturnsWhether the ExtraFeature's value is a regular expression.
 
void setRegexp(boolean regexp)
Set the regexp state of the ExtraFeature.
Parameters
regexpThe regexp state to set.
 
boolean getNegate()
Get the negate state of the ExtraFeature.
ReturnsThe negate state of the ExtraFeature.
 
void setNegate(boolean negate)
Set the negate state of the ExtraFeature.
Parameters
negateThe negate state to set.
 
 

The class de.qfs.apps.qftest.shared.data.ExtraFeatureSet collects ExtraFeatures into set:

 
 
ExtraFeatureSet ()
Create a new, empty ExtraFeatureSet.
 
void add(ExtraFeature extraFeature)
Add an extra feature to the set, potentially replacing a feature with the same name.
Parameters
extraFeatureThe extra feature to add.
 
ExtraFeature get(String name)
Get an extra feature from the set.
Parameters
nameThe name of the extra feature to get.
Returns The extra feature or null if no feature by that name is stored in the set.
 
ExtraFeature remove(String name)
Remove an extra feature from the set.
Parameters
nameThe name of the extra feature to remove.
Returns The extra feature that was removed or null if no feature by that name was stored in the set.
 
ExtraFeature[] toArray()
Get all extra features in the set.
ReturnsAn array of the contained extra features, sorted by name.
 
 
3.1+39.1.7
The ItemNameResolver2 interface

Note Unless you use the resolvers module described in subsection 39.1.10, an ItemNameResolver2 must be registered with the ItemRegistry described in subsection 39.2.4 and not the ResolverRegistry.

The de.qfs.apps.qftest.extensions.items.ItemNameResolver2 interface consists of a single method:

 
 
String getItemName(Object element, Object item, String name)
Determine the name of an item of a complex GUI element that will be used for the textual representation of the item's index.
Parameters
element The GUI element to which the item belongs.
item The item to get the name for. Its type depends on the GUI element and the registered ItemResolvers as described in subsection 39.2.5.
name The original name that QF-Test would use without a resolver.
Returns The name to use or null if the resolver does not handle this element or item.
 
 

After QF-Test determines the name for an item's index the registered ItemNameResolvers get a chance to override. The first resolver that returns a non-null value determines the outcome. If no resolvers are registered or all of them return null the original name is used.

3.1+39.1.8
The ItemValueResolver2 interface

Note Unless you use the resolvers module described in subsection 39.1.10, an ItemValueResolver2 must be registered with the ItemRegistry described in subsection 39.2.4 and not the ResolverRegistry.

The de.qfs.apps.qftest.extensions.items.ItemValueResolver2 interface consists of a single method:

 
 
String getItemValue(Object element, Object item, String value)
Determine the value of an item of a complex GUI element that will be used for its textual representation in a 'Check text' or a 'Fetch text' node.
Parameters
element The GUI element to which the item belongs.
item The item to get the value for. Its type depends on the GUI element and the registered ItemResolvers as described in subsection 39.2.5.
value The original value that QF-Test would use without a resolver.
Returns The value to use or null if the resolver does not handle this element or item.
 
 

After QF-Test determines the value for an item's index the registered ItemValueResolvers get a chance to override. The first resolver that returns a non-null value determines the outcome. If no resolvers are registered or all of them return null the original value is used.

39.1.9
The TreeTableResolver interface

Note This interface is irrelevant for SWT. Multi-column SWT trees are automatically supported by QF-Test.

A de.qfs.apps.qftest.extensions.TreeTableResolver must implement the following two methods:

 
 
JTree getTree(JTable table)
Determine the tree component used to implement a TreeTable.
Parameters
table The JTable component to determine the tree for.
Returns The tree or null if the JTable is a plain table and not a TreeTable.
 
int getTreeColumn(JTable table)
Determine the column index of the tree component in a TreeTable. Most implementations place the tree in the first column, in which case the index is 0.
Parameters
table The JTable component to determine the tree's column index for.
Returns The column index or -1 if the JTable is a plain table and not a TreeTable. The column index must always be given in the table's model coordinates, not in view coordinates.
 
 

Most TreeTableResolvers are trivial to implement. The following Jython example works well for the org.openide.explorer.view.TreeTable component used in the popular netBeans IDE, provided that the resolver is registered for the TreeTable class:

class TTResolver(TreeTableResolver):
    def getTree(self, table):
        return table.getCellRenderer(0,0)

    def getTreeColumn(self, table):
        return 0
Example 39.1:  TreeTableResolver for the netBeans IDE.
39.1.10
Simplified resolver creation with the resolvers module

Resolvers of all kinds can be implemented in Java, Jython or Groovy and then registered with the ResolverRegistry. Before describing this relatively complex process in detail in the following section, we'll show some resolver examples implemented with the help of the resolvers module provided with QF-Test. Unless you want to understand how the resolvers module itself works or want to implement a resolver in Java, these examples should be sufficient to get you going and skip the following sections.

Except for the more complex ItemResolver and Checker interfaces described in the following sections, which are not supported by the resolvers module, a resolver consists of a single method that needs to be implemented (one and a half in case of the TreeTableResolver). What makes resolvers difficult at Java level is the need for describing such a method as an interface that has to implemented by a class. Then an instance of that class has to be created and registered for use by QF-Test. If you don't get it right on first try, that instance has to be deregistered before a new instance from a new class can be created and instance thereof registered, otherwise there may be interference between the two versions of the resolver. Add some code for error handling and you've got many times more glue code than actual "flesh".

Fortunately, methods are first level objects in Jython, as are Groovy closures. This and the fact that the glue code is practically the same for all resolvers make it possible to move the tedious parts out of the way into a module and concentrate on the actual task at hand. Following is an example of a NameResolver2 for JMenuItems that promotes the label of a menu item to a component name for menus that have no name of their own:

def getName(menuItem, name):
    if not name:
        return menuItem.getLabel()
resolvers.addNameResolver2("menuItems", getName,
                           "javax.swing.JMenuItem")
Example 39.2:  Simple Jython NameResolver2 for JMenuItems

As you see it took only four lines of code to do that. The first three lines define a getName method for the resolver. The fourth line calls the addNameResolver2 function of the resolvers module which is always automatically available in Jython 'SUT script' nodes. The three parameters are an identifier for the resolver, the actual method and one or more optional targets, in this case the class name of the components for which we want to register the resolver.

Give it a try. Copy the example above into an 'SUT script' node and execute it. If your application is based on SWT instead of Swing, replace getLabel() with getText() and javax.swing.JMenuItem with org.eclipse.swt.MenuItem. Then record some menu actions into a new, empty test-suite. You'll find that all recorded menu item components without their own name will now have names set according to their labels. If setName is not used in your application and the labels of menu items are more or less static while the structure of the items changes often, this could even be a very useful thing. To install the resolver permanently, just move the 'SUT script' node right after the 'Wait for client to connect' node of your SUT startup sequence.

The same can be done in Groovy via the resolvers object that is also always available and has the same API. It expects a closure to create a resolver from as follows:

def getName = {menuItem, name ->
    if (name == null) {
        return menuItem.getLabel()
    }
}
resolvers.addNameResolver2("menuItems", getName,
                           "javax.swing.JMenuItem")
Example 39.3:  Simple Groovy NameResolver2 for JMenuItems

It is possible to register a resolver for multiple component classes at once:

def getName(com, name):
    return com.getLabel()
resolvers.addNameResolver2("labels", getName, "javax.swing.JLabel",
                           "javax.swing.AbstractButton")
Example 39.4:  Registering a NameResolver2 for multiple target classes

The other resolvers work similarly. Following is an example for an ItemNameResolver2 that makes the ID of a JTable column available as an item index:

def getColumnId(table, item, name):
    if item[1] < 0:  # whole column addressed
    id = table.getColumnModel().getColumn(i).getIdentifier()
    if id:
        return str(id)
resolvers.addItemNameResolver2("tableColumnId", getColumnId,
                               "javax.swing.table.TableColumn")
Example 39.5:  ItemNameResolver for JTable columns

FeatureResolvers and ExtraFeatureResolvers are handled just like NameResolvers, but ExtraFeatureResolvers are a bit more complex, though not overly so, as the following example shows:

from de.qfs.apps.qftest.shared.data import ExtraFeature, ExtraFeatureSet
def getExtraFeatures(node, features):
    features.add(ExtraFeature(ExtraFeature.STATE_SHOULD_MATCH,
                              "myname", "myvalue"))
    return features
resolvers.addExtraFeatureResolver("silly example", getExtraFeatures,
                                  "INPUT")
Example 39.6:   ExtraFeatureResolver that adds an extra feature to all INPUT nodes

TreeTableResolvers for Swing TreeTables are created and registered in a slightly different way:

def getTree(table):
    return table.getTree()
def getColumn(table):
    return 0
resolvers.addTreeTableResolver("treeTable", getTree, getColumn,
                               "my.package.TreeTable")
Example 39.7:   TreeTableResolver for Swing TreeTable with optional getColumn method

The above example shows a typical TreeTableResolver. Since almost all TreeTables display the tree in the first column of the table, the getColumn method is optional. If none is provided a default implementation for the first column is used:

def getTree(table):
    return table.getTree()
resolvers.addTreeTableResolver("treeTable", getTree, None,
                               "my.package.TreeTable")
Example 39.8:  Simplified TreeTableResolver

If no dedicated getTree method is available, the cell renderer of the column containing the tree (typically 0) might work, as it is typically derived from JTree.

def getTree(table):
    return table.getCellRenderer(0,0)
resolvers.addTreeTableResolver("treeTable", getTree,
                               "my.package.TreeTable")
Example 39.9:  Simple TreeTableResolver using getCellRenderer method

Following is the complete API of the resolvers module:

 
 
addNameResolver2(String name, Method method, Object target=None, ...)
Register a NameResolver2 for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getName() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addIdResolver(String name, Method method, Object target=None, ...)
Register an IdResolver for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getId() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addFeatureResolver2(String name, Method method, Object target=None, ...)
Register a FeatureResolver2 for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getFeature() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addExtraFeatureResolver(String name, Method method, Object target=None, ...)
Register an ExtraFeatureResolver for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getExtraFeature() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addItemNameResolver2(String name, Method method, Object target=None, ...)
Register an ItemNameResolver2 for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getItemName() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addItemValueResolver2(String name, Method method, Object target=None, ...)
Register an ItemValueResolver2 for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getItemValue() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addTreeTableResolver(String name, Method getTable, Method getColumn=None, Object target=None)
Register a TreeTableResolver for the given target(s), based on the given methods. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
getTableThe method that implements the resolver's getTable() method.
getColumnThe method that implements the resolver's getColumn() method.
target One optional target to register the resolver for. It can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
addClassNameResolver(String name, Method method, Object target=None, ...)
Register a ClassNameResolver for the given target(s), based on the given method. If another resolver was previously registered under the given name, unregister that first.
Parameters
nameThe name under which to register the resolver.
methodThe method that implements the resolver's getClassName() method.
target One or more optional targets to register the resolver for. Each can be any of the following:
  • An individual component
  • The fully qualified name of a class
If no target is given a global resolver for all components is registered.
 
removeResolver(String name)
Unregister a resolver from all the targets it was registered to.
Parameters
nameThe name under which the resolver was registered.
 
 
39.1.11
The ResolverRegistry

Now it is time to take a look at the Java API for registering resolvers on which the resolvers module is built. The singleton class de.qfs.apps.qftest.extensions.ResolverRegistry is the central agent for registering and removing name resolvers.

All kinds of resolvers can be registered on individual components or on classes. Resolvers registered on a component will only be called if their service is required for that specific component. Resolvers registered on a class will be called for every object of that class or a class derived from it.

NameResolvers, FeatureResolvers and TreeTableResolvers can also be registered globally so they will be called for each and every name or feature. This is similar to but more efficient than registering them on the java.lang.Object class.

If multiple resolvers are registered globally or registered on the same object or class, the resolver added last will be called first.

The ResolverRegistry API is pretty straightforward:

 
 
static ResolverRegistry instance()
There can only ever be one ResolverRegistry object and this is the method to get hold of this singleton instance.
ReturnsThe singleton ResolverRegistry instance.
 
static String getElementName(Object element)
This static method should be used instead of com.getName() or widget.getData() by resolvers that need to operate based on existing names of elements, except for a NameResolver2 that gets just the original name passed to its getName method. This method suppresses trivial or AWT/Swing specific component names that QF-Test handles specially.
Parameters
elementThe element to get the name for.
Returns The name of the element or null if a trivial or special name is suppressed.
 
static boolean isInstance(Object object, String className)
This static method should be used instead of instanceof (or isinstance() in Jython). It checks whether an object is an instance of a given class. The check is performed by name instead of through reflection, so conflicts with differing class loaders are prevented and there is no need to import the class to check against.
Parameters
objectThe object to check.
classNameThe name of the class to test for.
Returns True if the object is an instance of the given class.
 
void registerNameResolver2(Object element, NameResolver2 resolver)
Register a name resolver for an individual GUI element. The resolver does not prevent garbage collection and will be removed automatically when the element becomes unreachable.
Parameters
element The GUI element to register for.
resolver The resolver to register.
 
void unregisterNameResolver2(Object element, NameResolver2 resolver)
Unregister a name resolver for an individual GUI element.
Parameters
element The GUI element to unregister for.
resolver The resolver to unregister.
 
void registerNameResolver2(String clazz, NameResolver2 resolver)
Register a name resolver for a GUI element class.
Parameters
clazz The name of the class to register for.
resolver The resolver to register.
 
void unregisterNameResolver2(String clazz, NameResolver2 resolver)
Unregister a name resolver for a GUI element class.
Parameters
clazz The name of the class to unregister for.
resolver The resolver to unregister.
 
void registerNameResolver2(NameResolver2 resolver)
Register a generic or global name resolver.
Parameters
resolver The resolver to register.
 
void unregisterNameResolver2(NameResolver2 resolver)
Unregister a generic or global name resolver.
Parameters
resolver The resolver to unregister.
 
void registerIdResolver(Object element, IdResolver resolver)
Register an id resolver for an individual GUI element. The resolver does not prevent garbage collection and will be removed automatically when the element becomes unreachable.
Parameters
element The GUI element to register for.
resolver The resolver to register.
 
void unregisterIdResolver(Object element, IdResolver resolver)
Unregister an id resolver for an individual GUI element.
Parameters
element The GUI element to unregister for.
resolver The resolver to unregister.
 
void registerIdResolver(String clazz, IdResolver resolver)
Register an id resolver for a GUI element class.
Parameters
clazz The name of the class to register for.
resolver The resolver to register.
 
void unregisterIdResolver(String clazz, IdResolver resolver)
Unregister an id resolver for a GUI element class.
Parameters
clazz The name of the class to unregister for.
resolver The resolver to unregister.
 
void registerIdResolver(IdResolver resolver)
Register a generic or global id resolver.
Parameters
resolver The resolver to register.
 
void unregisterIdResolver(IdResolver resolver)
Unregister a generic or global id resolver.
Parameters
resolver The resolver to unregister.
 
void registerFeatureResolver2(Object element, FeatureResolver2 resolver)
Register a feature resolver for an individual GUI element. The resolver does not prevent garbage collection and will be removed automatically when the element becomes unreachable.
Parameters
element The GUI element to register for.
resolver The resolver to register.
 
void unregisterFeatureResolver2(Object element, FeatureResolver2 resolver)
Unregister a feature resolver for an individual GUI element.
Parameters
element The GUI element to unregister for.
resolver The resolver to unregister.
 
void registerFeatureResolver2(String clazz, FeatureResolver2 resolver)
Register a feature resolver for a GUI element class.
Parameters
clazz The name of the class to register for.
resolver The resolver to register.
 
void unregisterFeatureResolver2(String clazz, FeatureResolver2 resolver)
Unregister a feature resolver for a GUI element class.
Parameters
clazz The name of the class to unregister for.
resolver The resolver to unregister.
 
void registerFeatureResolver2(FeatureResolver2 resolver)
Register a generic or global feature resolver.
Parameters
resolver The resolver to register.
 
void unregisterFeatureResolver2(FeatureResolver2 resolver)
Unregister a generic or global feature resolver.
Parameters
resolver The resolver to unregister.
 
void registerExtraFeatureResolver(Object element, ExtraFeatureResolver resolver)
Register an extra feature resolver for an individual GUI element. The resolver does not prevent garbage collection and will be removed automatically when the element becomes unreachable.
Parameters
element The GUI element to register for.
resolver The resolver to register.
 
void unregisterExtraFeatureResolver(Object element, ExtraFeatureResolver resolver)
Unregister an extra feature resolver for an individual GUI element.
Parameters
element The GUI element to unregister for.
resolver The resolver to unregister.
 
void registerExtraFeatureResolver(String clazz, ExtraFeatureResolver resolver)
Register an extra feature resolver for a GUI element class.
Parameters
clazz The name of the class to register for.
resolver The resolver to register.
 
void unregisterExtraFeatureResolver(String clazz, ExtraFeatureResolver resolver)
Unregister an extra feature resolver for a GUI element class.
Parameters
clazz The name of the class to unregister for.
resolver The resolver to unregister.
 
void registerExtraFeatureResolver(ExtraFeatureResolver resolver)
Register a generic or global extra feature resolver.
Parameters
resolver The resolver to register.
 
void unregisterExtraFeatureResolver(ExtraFeatureResolver resolver)
Unregister a generic or global extra feature resolver.
Parameters
resolver The resolver to unregister.
 
void registerTreeTableResolver(Component com, TreeTableResolver resolver)
Register a TreeTable resolver for a specific component. The resolver will be removed automatically if the component becomes invisible.
Parameters
com The component to register for.
resolver The resolver to register.
 
void unregisterTreeTableResolver(Component com, TreeTableResolver resolver)
Unregister a TreeTable resolver for a specific component.
Parameters
com The component to unregister for.
resolver The resolver to unregister.
 
void registerTreeTableResolver(String clazz, TreeTableResolver resolver)
Register a TreeTable resolver for a component class.
Parameters
clazz The name of the class to register for.
resolver The resolver to register.
 
void unregisterTreeTableResolver(String clazz, TreeTableResolver resolver)
Unregister a TreeTable resolver for a component class.
Parameters
clazz The name of the class to unregister for.
resolver The resolver to unregister.
 
void registerTreeTableResolver(TreeTableResolver resolver)
Register a generic or global TreeTable resolver.
Parameters
resolver The resolver to register.
 
void unregisterTreeTableResolver(TreeTableResolver resolver)
Unregister a generic or global TreeTable resolver.
Parameters
resolver The resolver to unregister.
 
void unregisterResolvers(Object element)
Unregister all resolvers for a specific GUI element.
Parameters
element The element to unregister for.
 
void unregisterResolvers(String clazz)
Unregister all resolvers for the class of a GUI element, value or renderer.
Parameters
clazz The name of the class to unregister for.
 
 
39.1.12
Error handling

All exceptions thrown inside a name resolver will be caught and handled by the ResolverRegistry. However, instead of dumping a stack trace, the registry will only print a short message like "Exception inside NameResolver2" because some resolvers may be called very often, so for a buggy resolver printing a stack trace for every error could flood the net and the client terminal. Therefore name resolvers should include their own error handling. This can still generate a lot of output in some cases, but especially for scripts the output will be more useful than a Java stack trace.