Column View Search

Author: Nathan Fiedler

The XML Schema editor supports three views, one showing the raw text, another displays interactive graphs of the component relationships, and a third shows the components in a tree/table hybrid (referred to as the column view). The text editor has a suitable search facility which is supplied by the NetBeans IDE. This specification describes the search feature as it exists in the columns view.

Below is a screen shot of the columns view. Note that the search toolbar is not visible until the Find action is invoked, either from the Edit menu, the IDE toolbar, or by pressing the Ctrl-F keyboard shortcut. Note that the Schema view has both a columns mode and a tree mode (the two small icons in the view toolbar). The search feature works identically in both views.

column view

Search Field

To start with, we will take a brief look at the search interface of a popular desktop application used by many Sun employees, Mozilla Thunderbird. The search field in Mozilla Thunderbird is always visible in the area just below the toolbar. The field is not labelled, but an icon just inside the field depicts a magnifying glass, which is easily interpreted to represent searching.

thunderbird search

Normally, it is quite common for a magnifying glass to represent a zoom feature, in which a graphical view is magnified to increase the size of the elements within the view. In some software products, the search feature is represented by binoculars (e.g. Adobe Reader). Given that the two most popular web browsers (IE and Firefox) both represent their search feature with a magnifying glass, it seems reasonable to use a similar icon for our search feature.

Thunderbird offers the ability to search over one or more fields of a mail message, although the search phrase is always treated as a simple text string. The interface for choosing which field or fields to search through is offered by a menu accessed from a button in the search field, as shown below.

thunderbird search types

The column view search should offer a similar feature, in which a query phrase could be matched against one of several types of components in an XML Schema document. For instance:

Component Name
Finds components whose name attribute matches the search phrase.
Component Kind
Finds components whose kind matches the search query.
Attribute Declaration
Finds components with attributes of a particular name.
Attribute Value
Finds components with attributes of a particular value.
Namespace Usage
Finds named component references that reference components of a particular namespace.
Finds components that match the given XPath. (This option is not provided at present due to it being very slow.)

Search Query

There are several types of query strings, depending on what the user provides. By default the query phrase is treated as a simple sub-string, unless it contains wildcards (*, ?), in which case it is a wildcard search. If the search type is XPath, then the query must be a valid XPath expression. Likewise, if the "Use regular expression" menu item is checked, then the query phrase must be a valid Perl-like regular expression. Each type of query phrase is described below.

Simple sub-string
The query phrase is treated as a case-insensitive sub-string. That is, the phrase is considered a match if it is equal to the target text, whether in whole or in part. For example, leng with match "minLength", "maxlength", and even "LENG".
Basic wildcard expression
The query phrase is treated as a case-insensitive, simple wildcard expression. The expression must match the target text in its entirety to constitute a match. The allowed wildcards are asterisk (*) for zero or more characters, and question mark (?) for exactly one character. For example, floss* will match any text that begins with "floss", including just "floss", while loss? will match "lossy" but not "loss". Using * will match anything, while ??? only matches text comprised of three characters. Wildcards can be combined, and appear more than once in the expression, so floss*pas?? would match "floss and paste".
Perl-like regular expression
See the java.util.regex.Pattern class API documentation for the details on the regular expression format.
XPath expression
An XPath expression, with case-sensitivity. The expression must match the component path in its entirety in order to constitute a match (i.e. no sub-string matching). See the XML Path Language specification for more information.

Note that search queries that are not sub-string expressions will require that the expression contains any necessary namespace prefix in order to match components. That is, if your schema contains components with a prefix such as xs:, then your query should either include a wildcard prefix (e.g. *), or the namespace prefix. For instance, searching for min* may find nothing at all, while either xs:min* or *min* will likely find what you are expecting. This applies to the "Basic wildcard expression", "Perl-like regular expression", and "XPath expression" query types.

Search Options

The search menu provides options for controlling how the search is performed, and they are as follows.

Search from selected
Starts the search from the component most recently selected in the columns view interface. That is, rather than searching from the root of the schema document, the search is performed with the selected sub-tree. Note that this option is not supported by the XPath query search.
Use regular expression
When selected, the phrase entered into the text field is treated as a Perl-like regular expression, with case-sensitivity, as described above. Note that this option is not supported by the XPath query search.

Displaying Search Results

The column view displays the XML schema in a table form in which there is only one row, with multiple columns. Displaying the results of a search in this view would likely take one of two forms.

The first would be to hide those components that do not match the query phrase, or do not lead to a matching component. For example, Mozilla Thunderbird hides those messages which do not match the given search phrase, as shown in the image below.

thunderbird search results

In our column view image shown above, if the search query was for \d{5} then the only components visible might be Address, zip, and \d{5} itself. That is, only the components which match, and the components leading up to those matches, would be shown in the columns view. The image below provides an example of this. Note that the query example here is not a regular expression.

filtered search results

The second form of indicating the matching components would be to highlight those components that match the query, or that lead to a matching component. This is similar to the search facility in Mozilla Firefox, in which the text matching a query phrase is highlighted with a bright color. Since changing the background color would conflict with the painting of the selection highlight, the search will change the foreground color and render the text in bold.

highlighted search results

Components which match the query are highlighted with a dark orange color, while the components that lead to a matching component are colored with a light orange. This is to help the user distinguish between the actual results and those components that simply lead to a result. The first matching result will be selected in the view, possibly opening columns (or expanding the tree if the tree view is selected).

If the search phrase appears in multiple locations, then entries within each visible column will be highlighted appropriately. In this way, the user can quickly navigate from the root components down to the matching component. In addition to the highlight, the search toolbar provides a buttons for moving to the next and previous search results. These buttons will wrap around, such that if the user keeps pressing one button or the other, they will first see all of the results, and then start from the beginning again.

The preferred form for indicating the search results is to highlight the matching components. The reason for this is that the context of the matching components may be lost if all other components are hidden. In particular, Chris Webster pointed out that components of a sequence may no longer make sense when viewed alone.

Indicating No Match

Mozilla Firefox indicates that the query phrase could not be found by highlighting the search field in red, emitting a beep sound, and adding a Phrase not found message in the search toolbar. It seems very unlikely that our search facility should ever beep, as it would probably be the first time the IDE ever made a noise. Secondly, while the Phrase not found label is certainly clear and concise, it would not fit in our current toolbar area. This approach would seem to work best when the search results are highlighted rather than filtered.

An alternative to the red highlight in the search field would be to hide all of the components in the column view. This is what Thunderbird does when the query phrase does not match any messages. Naturally this makes the most sense when paired with the filtering of search results. That is, if the search results are highlighted, then no components will be filtered, and instead the search field will be highlighted in red. Since our search results will be highlighted, the search field will be highlighted when there is no match, as shown in the screen shot below.

phrase not found

Dismissing the Search

To cancel the active search and restore the column view to its normal display of all of the components in the schema, the IDE offers a red 'x' icon in the search toolbar. This is what Firefox does and it is sufficiently intuitable such that an explanation is not really necessary. In the case of highlighting the search results, the close button removes the highlight effect from the view.

Implementation Details

The search implementation(s) generally subclass DeepSchemaVisitor and add each matching component to a Set. The path from the matching component to the schema root is determined by using getParent() to walk up the tree. In this way, it is possible to visit every component in the schema model and store the complete path of each matching component. With the complete path of each matching component, it is trivial to highlight the search results in the columns view.

The search interface is implemented in the SchemaSearchPanel and SearchFieldPanel classes, both in the XML Schema UI - Basic module. The logic of dealing with initiating the search and handling user input is in SearchFieldPanel, while SchemaSearchPanel manages the search toolbar and the close, next, and previous buttons.

Highlighting the search results is accomplished by creating Highlight objects and registering them with the default HighlightManager. Each Highlight instance is associated with a single SchemaComponentReference, and the SchemaComponentNode and CategoryNode classes implement the Highlighted interface in order to render the search results appropriately.

The search field displays the type of the search that would be performed if a phrase were provided (e.g. Component Name) using the inactive text color in the text field. When the field gains the input focus, the text will disappear and a text cursor will indicate that it is ready to receive the search phrase. When focus is lost and the field is blank, the search type string will re-appear. The search type string also disappears when the search type menu is opened, and re-appear when the menu closes.

Each of the view Category implementations provide zero or more SearchProvider implementations in their Lookup. If no search providers are available in the currently active category, then the search field in the toolbar is disabled to indicate the search feature is unavailable. The SearchProvider interface includes the following methods:

String getDisplayName()
Returns the display string for describing this search provider.
String getInputDescription()
Returns a description of the expected input for this provider. This is used to instruct the user on what should be entered into the search field.
String getShortDescription()
Returns a brief description of this search provider, useful for tooltips.
List<SchemaComponent> search(Query query)
Performs the search using the given query string, and returns the list of matches that were found.

Note that Query is a simple class that encapsulates the search phrase and the search parameters.

The search interface code listens to the category selection (via property changes in the CategoryPane) and change the enabled state of the search field accordingly (as described above). If the current category provides one or more search providers, then the "search types" described earlier will correspond to the available search providers.

Project Features

About this Project

XML was started in November 2009, is owned by dstrupl, and has 62 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
Please Confirm