Why Query Language
Data sources with help of parsers get your data from the source but the data often comes in large chunks where you are only interested in some subset. Even if you need all data you often want to process it piece by piece. Finally, binding UI controls to data sources becomes much more easier if you can bind to a simple expression rather than binding to a complex parser function.
Design Overview: Filtering
You should know by now that data in Data Sources Framework is organized in a tree-like structure which consists of RecordSets, Records and raw data (String, Integers, etc.). The framework uses a generic notion of filtering (
org.netbeans.javafx.datasrc.Filter). In the most general case, a filter processes a RecordSet and creates a new RecordSet that contains only filtered data. This functionality is available directly on a RecordSet and also on a DataSource.
|available on RecordSet and uses a Filter implementation to filter this RecordSet and produce another one. Results of this call are NOT cached and every call does new filtering and produces a new RecordSet.|
|available on RecordSet and uses an expression written in QL to filter one RecordSet and produce another one. In fact, this is a helper function that uses a special |
|available on RecordSet and uses an expression written in QL to filter one RecordSet and produce s String value. This is a helper functions that first calls the previous |
|available on DataSource and uses an expression written in QL to filter data in the DS and produce a new DS containing only filtered data. In fact, this is a helper function that in fact calls |
There is a special implementation of the
Filter class called
Filter.Expr. It takes an expression string written in QL, evaluates it and eventually produces a filtered RecordSet.
QL is itself insipred by XPath and uses its syntax in the simplest form possible to cover most use cases JavaFx users could encounter.
The expression is a series of element names separated by forward slashes:
name0 "/" name1 "/" ... "/" nameN
Each segment can be optionally indexed:
name0 "[" index0 "]" / name1 "[" index1 "]" / ... / nameN "[" indexN "]"
Indexes are 0-based and specify indexes into the actual RecordSet. Example:
In this case the field "books" in in the "bookstore" Record must be a RecordSet.
The last segment can be optionally prefixed with an "at sign" in which case it specifies an XML attribute:
name0 "/" name1 "/" ... "/" "@" nameN