The RTView Custom Data Adapter API lets you create a custom adapter to an external source of data, making the data available for use in RTView applications. The API provides support for event-driven and polled data updates, connection management, and automatic creation of the Options Tab, Connections Tab, and Attach To Data dialog in the Display Builder.
The Custom Data Adapter API is defined by the classes in the com.sl.gmsjrtviewds package, most importantly the GmsRtViewDs and GmsRtViewDsAdapter classes. Because the data is stored in tabular form, the GmsTabularData class in the com.sl.gmsjrt package is also considered an important part of the API.
All custom data adapters contain a class that extends the com.sl.gmsjrtviewds.GmsRtViewDs class. This class, referred to as the custom ds or simply the ds, defines the data source in a declarative manner, including the properties of the data source and the formats of the objects used to create data attachments, define connections, and specify options. In addition, the GmsRtViewDs class contains methods to store and retrieve data tables.
All custom data adapters also contain a class that extends the com.sl.gmsjrtviewds.GmsRtViewDsAdapter class. This class, referred to as the custom ds adapter or simply the adapter, defines methods that are invoked during the execution of an RTView application, including methods to initialize the data source, start data collection, establish connections, process options, update data attachments, validate information entered into dialogs and shut down the data source.
This section contains the following:
§ “Custom Data Adapter - Data Adapter Characteristics” on page 1254
§ “Custom Data Adapter - Data Adapter Properties” on page 1257
§ “Custom Data Adapter - Data Management” on page 1263
§ “Custom Data Adapter - Connections” on page 1273
§ “Custom Data Adapter - Data Source Options” on page 1279
§ “Custom Data Adapter - Dialogs” on page 1282
Custom Data Adapter - Data Adapter Characteristics
The Custom Data Adapter API includes features for handling a wide variety of data sources. This section presents some common characteristics of data adapters and discusses the features in the API to support them.
The Data Adapter API provides support for both polled and event-driven data updates through a collection of lifecycle callbacks, invoked as an application runs. A custom adapter may override any of these methods to provide support for polled or event-driven data updates, or a combination of both. The default implementations of these methods do nothing, so a custom adapter is free to implement only the methods it requires.
§ The initialize data method, GmsRtViewDsAdapter.initializeData(), is called at application startup to allow the custom adapter to perform set-up operations on the external data source.
§ The start data method, GmsRtViewDsAdapter.startData(), is called after all RTView Data Adapters have been initialized, but before any displays have been loaded. A custom data adapter can override this method to begin data generation.
§ The register data method, GmsRtViewDsAdapter.registerData(GmsRtViewDataObject), is called whenever a new data attachment is activated, normally by loading a display. This method is typically used by an event-driven data adapter to register interest in data with the external data source.
§ The update data object method, GmsRtViewDsAdapter.updateDataObject(GmsRtViewDataObject), is called once every update period for each active data attachment. This is the primary method that a polled data adapter would override to update data.
§ The unregister data method, GmsRtViewDsAdapter.unregisterData(GmsRtViewDataObject), is called whenever the last attachment to a data item is removed, normally by unloading a display. This method is typically used by an event-driven data adapter to remove interest in data with the external data source.
§ The terminate data method, GmsRtViewDsAdapter.terminateData(), is called when the application shuts down to allow the custom adapter to perform cleanup operations.
In addition to the lifecycle callbacks listed above, an event-driven data adapter would also include an event handler, which would receive notifications of data changes from the external data source and would store the new data.
In the Display Builder, graphical objects are attached to data retrieved from the data source using the Attach To Data dialog. Each data attachment contains enough information to identify which item of data should be accessed and how the data should be stored for later retrieval. The data object class, com.sl.gmsjrtviewds.GmsRtViewDataObject, defines a data attachment.
During initialization the Custom Data Adapter defines an exemplar, or template, for its data attachments. On this exemplar, the Custom Data Adapter adds the fields that make up a data attachment and identifies which fields make up the data key. The data key determines how the data is stored. In the Display Builder, the Attach To Data dialog is automatically constructed from the information provided in the exemplar.
The Custom Data Adapter API provides support for automatic connection management. The conninfo class, com.sl.gmsjrtviewds.GmsRtViewDsConnInfo, defines a connection. Each connection has a name and an arbitrary number of fields that define the connection parameters (e.g. host, port, username, password).
During initialization, the Custom Data Adapter defines the information needed for the connection objects by adding fields to an exemplar. In the Display Builder, the Connections tab of the Options dialog is automatically constructed from the information provided in the exemplar. At runtime, the GmsRtViewDsAdapter.attemptConnection(GmsRtViewDsConnInfo) method is invoked to signal that a connection should be made to the external data source. The return status from the method indicates whether the connection attempt was successful. Unsuccessful connection attempts are retried on the next update cycle. Connection definitions are stored in the options file for the Custom Data Adapter, which is specified in the method GmsRtViewDsProperties.setOptionFileName(String).
The Custom Data Adapter API provides support for custom options which can be used in any way at runtime. The dsoptions class, com.sl.gmsjrtviewds.GmsRtViewDsOptions, defines the options available to the Custom Data Adapter.
During initialization, the Custom Data Adapter defines these options by adding fields to an exemplar. In the Display Builder, the Options tab of the Options dialog is automatically constructed from the information provided in the exemplar. At runtime, the GmsRtViewDsAdapter.applyDsOption(GmsRtViewDsOptions) method is invoked once for each option. Options are stored in the options file for the Custom Data Adapter, which is specified in the method GmsRtViewDsBaseProperties.setOptionFileName(String).
In the Display Builder, the Attach To Data dialog is automatically created by classes included in the Custom Data Adapter API. Normally this dialog contains fields to enable a row filter on an individual data attachment. A row filter specifies the subset of rows from the data table which are used in a data attachment. The dialog includes a check box, a combo-box to identify the column for row filtering, and a text field to specify the filter value to match.
In some data sources, row filtering is not relevant. An example might be a streamed data source, where each data table has only one record containing the most recent streamed event. To simplify the Attach To Data dialog, the Custom Data Adapter may choose to disable row filtering.
The Custom Data Adapter API includes the method GmsRtViewDsControlProperties.setRowFilteringEnabled(boolean) to enable or disable the creation of the row filtering fields in the Attach To Data dialog. This characteristic must be set at initialization time in the method GmsRtViewDs.initDsControlProperties(GmsRtViewDsControlProperties). This property cannot be changed after initialization.
In the Display Builder, the Attach To Data dialog is automatically created by classes included in the Custom Data Adapter API. Normally this dialog contains fields to enable a column filter on an individual data attachment. A column filter specifies the subset of columns from the data table which are used in a data attachment. The dialog includes a combo-box to select the columns from the data table.
In some data sources, column filtering is not relevant. An example might be a data source which provides time-series data, where all tables include only a timestamp and value. To simplify the Attach To Data dialog, the Custom Data Adapter may choose to disable column filtering.
The Custom Data Adapter API includes the method GmsRtViewDsControlProperties.setColumnFilteringEnabled(boolean) to enable or disable the creation of the column filtering fields in the Attach To Data dialog. This characteristic must be set at initialization time in the method GmsRtViewDs.initDsControlProperties(GmsRtViewDsControlProperties). This property cannot be changed after initialization.
In the Display Builder, the Attach To Data dialog is automatically created by classes included in the Custom Data Adapter API. Normally this dialog contains a combo-box to allow the polled update mode to be set on an individual data attachment. The polled update mode controls how frequently the method GmsRtViewDataAdapter.updateDataObject(GmsRtViewDataObject) is called while the display is loaded. Available options include polling at the RTView update interval, an interval specific to the Custom Data Adapter, an interval which can be specified for an individual data attachment, only once whenever a display is loaded or reloaded, or only once the first time a display is loaded.
In some data sources, the polled update behavior is not relevant. An example might be a data source that is completely event-driven. In this case, the Custom Data Adapter may choose to disable support for this feature, to simplify the Attach To Data dialog.
The Custom Data Adapter API includes the method GmsRtViewDsControlProperties.enableUpdateModes(Set<UpdateMode>) to control which update modes are shown in the Attach To Data dialog. This characteristic must be set at initialization time in the method GmsRtViewDs.initDsControlProperties(GmsRtViewDsControlProperties). This property cannot be changed after initialization.
Custom Data Adapter - Data Adapter Properties
The methods GmsRtViewDs.initDsBaseProperties(GmsRtViewDsBaseProperties) and GmsRtViewDs.initDsControlProperties(GmsRtViewDsControlProperties) are invoked during application initialization to define properties and behaviors for the Custom Data Adapter. The GmsRtViewDsBaseProperties and GmsRtViewDsControlProperties objects contain methods for setting properties and behaviors. Note that all properties and behaviors must be set in the GmsRtViewDsAdapter.initDsBaseProperties(GmsRtViewDsBaseProperties) and GmsRtViewDs.initDsControlProperties(GmsRtViewDsControlProperties) methods. Properties cannot be changed after initialization.
The base properties are initialized from the GmsRtViewDs constructor, before any command-line arguments or options are processed. The control properties are initialized after command-line arguments and options have been processed.
This section describes the properties that can be configured for a Custom Data Adapter. Of the properties, only the DS Key and the Adapter Class Name are required, although we recommend that you set each of the properties to clearly document the intended behavior of your Custom Data Adapter.
Base Property: DS Key (required)
The DS Key, or dskey, is a short string that uniquely identifies the data source. The dskey should not contain any spaces or colon characters, and should not conflict with other dskeys already in use by RTView data adapters (e.g. sql, xml, jms, jmx). SL recommends using a prefix like custom- at the beginning of your dskey to avoid conflicts with other RTView dskeys. For example, a custom XML data adapter might use the custom-xml dskey.
In an RTView display, each data attachment is saved as a string, known as the dsstring. The dskey is the first word in the dsstring, and is used to identify the data adapter which will provide the data. The dskey is followed by a series of fields which contain additional information to specify the data that will be accessed.
To set the dskey for a Custom Data Adapter, use the method GmsRtViewDsBaseProperties.setDsKey(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsBaseProperties ( GmsRtViewDsBaseProperties properties )
{
properties.setDsKey( “custom-xml” );
...
}
}
Base Property: Adapter Class Name (required)
This property specifies the fully qualified class name of the adapter class for this Custom Data Adapter. The adapter class is a subclass of com.sl.gmsjrtviewds.GmsRtViewDsAdapter. This property is set using the method GmsRtViewDsBaseProperties.setAdapterClassName(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsBaseProperties ( GmsRtViewDsBaseProperties properties )
{
// identify the class MyCustomEventDsAdapter in the package
// com.mydomain.mypackage
properties.setAdapterClassName(
“com.mydomain.mypackage.MyCustomEventDsAdapter” );
}
}
Base Property: Custom Data Adapter Description
This property is used to identify the Custom Data Adapter in the RTView About Dialog. If this property is not set, the description will default to RTView DS (Generic). The description is set using the method GmsRtViewDsBaseProperties.setDsDescription(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsBaseProperties ( GmsRtViewDsBaseProperties properties )
{
properties.setDsDescription( “My Custom Event DS” );
...
}
}
Base Property: Option File Name
This property identifies the name of the file used to store the Options and Connection definitions for the Custom Data Adapter. If this property is not set, the option file REVIEWDSOPTIONS.ini will be used. The option file name is set using the method GmsRtViewDsBaseProperties.setOptionFileName(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsBaseProperties ( GmsRtViewDsBaseProperties properties )
{
properties.setOptionFileName( “MYCUSTOMDSOPTIONS.ini” );
...
}
}
Control Property: Row Filtering
This property indicates whether the Custom Data Adapter will permit row filtering in data attachments. Row filtering allows a data attachment to return a subset of rows from a data table by specifying a column and value to match against.
By default, row filtering is enabled. When row filtering is disabled, the Attach To Data dialog will not contain the Filter Rows check box or the two associated text fields Filter Column and Filter Value. To enable or disable row filtering, use the method GmsRtViewDsControlProperties.setRowFilteringEnabled(boolean). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
properties.setRowFilteringEnabled( false );
...
}
}
Control Property: Column Filtering
This property indicates whether the Custom Data Adapter will permit column filtering in data attachments. Column filtering allows a data attachment to specify which columns will be returned from a data table.
By default, column filtering is enabled. When column filtering is disabled, the Attach To Data dialog will not contain the Column(s) combo-box and column chooser. To enable or disable column filtering, use the method GmsRtViewDsControlProperties.setColumnFilteringEnabled(boolean). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
properties.setColumnFilteringEnabled( false );
...
}
}
Control Property: Update Modes
This property indicates the available polled update modes the Custom Data Adapter will allow for data attachments. The following modes are supported:
§ UpdateMode.DS_OPTION_PERIOD: Poll for data at the interval specified in the Ds Options tab for the custom data adapter. If this interval is zero, poll for data at the RTView data update rate.
§ UpdateMode.DATA_ATTACHMENT_PERIOD: Poll for data at the interval specified for this data attachment. When this update mode is selected, the Poll Interval field in the Attach To Data dialog is enabled to allow the interval to be specified.
§ UpdateMode.ON_DEMAND_UPDATE: Poll for data once when the display is loaded, and again whenever the display is reloaded.
§ UpdateMode.STATIC_UPDATE_ONCE: Poll for data once, when the display is first loaded.
By default, all of the update modes are enabled. A custom data adapter may disable some or all of the update modes using the method GmsRtViewDsControlProperties.enableUpdateModes(Set<UpdateMode>). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
Set<UpdateMode> modes =
Collections.unmodifiableSet(
EnumSet.of( UpdateMode.DS_OPTION_PERIOD,
UpdateMode.ON_DEMAND_UPDATE ));
properties.enableUpdateModes( modes );
...
}
}
For convenience, the GmsRtViewDs base class defines the following sets of update modes:
§ GmsRtViewDs.DEFAULT_UPDATE_MODES: The set of update modes which are enabled by default.
§ GmsRtViewDs.NO_UPDATE_MODES: A set containing none of the update modes. A custom data adapter which is completely event-driven and does no polling could use this to disable all polled updates. When no update modes are enabled, the attach to data dialog will not contain the Polling Mode combo-box or the Poll Interval text field.
This property indicates whether the Custom Data Adapter supports commands in data attachments.
By default, commands are disabled. When commands are enabled, the dskey will appear in the list of Data Adapters for the Define Command menu option. Selecting the Data Adapter will bring up the Define Command dialog. To enable or disable commands, use the method GmsRtViewDsControlProperties.setCommandsEnabled(boolean). For example,
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
properties.setCommandsEnabled( true );
...
}
}
Control Property: Option Tab Class Name
This property specifies the fully-qualified class name of the Option Tab for the data adapter. If this property is not set or the class name provided is null, the default option tab class will be used. The default option tab class, com.sl.gmsjrtviewds.GmsJRtViewOptionTab, automatically builds the Option tab from the fields defined in the com.sl.gmsjrtviewds.GmsRtViewDsOptions exemplar.
Note: This version of the Custom Data Adapter API does not support custom dialog classes. SL recommends using the default class by specifying null for this property, as shown in the following example.
To specify the name of the Option tab class, use the method GmsRtViewDsControlProperties.setOptionTabClassName(String). For example,
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
// use default class
properties.setOptionTabClassName( null );
...
}
}
Control Property: Attach To Data Dialog Class Name
This property specifies the fully-qualified class name of the Attach To Data dialog for the data adapter. If this property is not set or the class name provided is null, the default dialog class will be used. The default dialog class, com.sl.gmsjrtviewds.GmsJRtViewDataDialog, automatically builds the Attach To Data dialog from the fields defined in the com.sl.gmsjrtviewds.GmsRtViewDataObject exemplar.
Note: This version of the Custom Data Adapter API does not support custom dialog classes. SL recommends using the default class by specifying null for this property, as shown in the following example.
To specify the name of the Attach To Data dialog class, use the method GmsRtViewDsControlProperties.setAttachDataDialogClassName(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
// use default dialog class
properties.setAttachDataDialogClassName( null );
...
}
}
Control Property: Command Dialog Class Name
This property specifies the fully-qualified class name of the Command dialog for the data adapter. If this property is not set or the class name provided is null, the default dialog class, com.sl.gmsjrtvbuild.GmsJRtViewCommandDialog, will be used.
Note: This version of the Custom Data Adapter API does not support custom dialog classes. SL recommends using the default class by specifying null for this property, as shown in the following example.
To specify the name of the Command dialog class, use the method GmsRtViewDsControlProperties.setCommandDialogClassName(String). For example:
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
// use default dialog class
properties.setCommandDialogClassName( null );
...
}
}
Control Property: Resource Bundle Name
This property identifies the name of the file that contains localization resources for the data adapter. These resources are used to customize the text displayed in the Attach To Data dialog, the Options tab, and the Connections tab in the Display Builder. If this property is not set or the bundle name is null, the default resource bundle, com.sl.gmsjrtviewds.rtviewds, will be used.
To specify the resource bundle name use the method GmsRtViewDsControlProperties.setResourceBundleName(String). For example,
public class MyDs extends GmsRtViewDs
{
protected void initDsControlProperties ( GmsRtViewDsControlProperties properties )
{
// look for localization resources in the
// file “mycustomds.properties”
properties.setResourceBundleName( “mycustomds” );
...
}
}
Custom Data Adapter - Data Management
The primary responsibility of a Custom Data Adapter is to retrieve data from an external data source and to make the data available for use in RTView applications. This section describes the classes and methods in the Custom Data Adapter API which are used for data management.
In RTView, data is stored in tabular form as a collection of named com.sl.gmsjrt.GmsTabularData objects. The table name, or data key, is used by the Custom Data Adapter to store the data. The data key is also used by RTView data attachments to access and display the data.
The Custom Data Adapter defines the data key when it initializes the com.sl.gmsjrtviewds.GmsRtViewDataObject class exemplar. The data key then determines the organization of the data tables within RTView.
In the Custom Data Adapter, all data is stored in named tables. The com.sl.gmsjrt.GmsTabularData class defines the tabular data format used by the Custom Data Adapter API. This class includes methods to define a table, to add rows and columns, and to set and query values in individual cells.
The com.sl.gmsjrtview.GmsRtViewDs class contains several overloaded methods to store tabular data, as well as the method GmsRtViewDs.getStoredDataTable(String) to retrieve a data table.
It is also important to note that the Custom Data Adapter stores only current data values. When new data is stored, the previous data is replaced. If necessary, historical data can be saved through the use of the RTView Cache.
In the Custom Data Adapter, each data table is identified by a unique name, the data key. When data is stored or retrieved, the data key can either be specified directly or determined automatically from the fields of a data object. Data objects are described in the section Data Attachments and Data Objects.
The information that determines the data key is specified during initialization, in the method GmsRtViewDs.initDataObjectExemplar(GmsRtViewDataObject). This method defines the fields that make up a data object. After defining the fields, one or more fields are chosen to uniquely identify the data when it is stored, using the method GmsRtViewDataObject.setDataKeyColumnFields(String[]). The data key is built from the values of these fields.
The following example shows a data object containing three fields, SalesRegion, Product, and Model. In this example, the SalesRegion and Product are defined as the data key fields. This means that each unique combination of SalesRegion and Product will be stored in a new data table. Within each data table, records for any number of Models might be stored.
Consider the following data set:
SalesRegion |
Product |
Model |
East |
Radio |
A100 |
East |
Radio |
A101 |
East |
Heater |
A100 |
South |
Radio |
A220 |
South |
Radio |
A104 |
South |
Radio |
A130 |
The definition of SalesRegion and Product as the data key would result in three tables:
SalesRegion=East Product=Radio
SalesRegion=East Product=Heater
SalesRegion=South Product=Radio
If instead, we had only defined SalesRegion as the data key, the data would have been stored in two tables:
SalesRegion=East
SalesRegion=South
And if we wanted all of the data to be stored in a single table, we could have added a field named TableName, designated it as the only data key field, and set its value to SalesData in all of our data attachments. We then would have only a single table, with the data key:
TableName=SalesData
In our custom ds class, we define the data key fields:
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string
exemplar.addField( “SalesRegion” );
exemplar.addField( “Product” );
exemplar.addField( “Model” );
// define the data key fields — these are
// the fields that uniquely identify a
// data table
String[] dataKeyFields = new String[]{ “SalesRegion”, “Product” };
exemplar.setDataKeyColumnFields( dataKeyFields );
}
}
When we build displays and make data attachments, we specify which SalesRegion, Product, and Model to query. Then, when a display is loaded into RTView, the data attachment (data object) triggers a call to GmsRtViewDsAdapter.updateDataObject(GmsRtViewDataObject). In the Custom Data Adapter, this method would examine the fields in the data object to determine which data is needed, get the data from the data source, put the data into a GmsTabularData object, and store the data.
The Custom Data Adapter API also provides support for data indexing. Index columns are defined during the initialization of the data object exemplar in the method GmsRtViewDs.initDataObjectExemplar(GmsRtViewDataObject). In this method, one or more of the data object fields can be identified as index columns using the method GmsRtViewDataObject.setIndexColumnFields(String[]).
When data is stored in an indexed data table, the Custom Data Adapter provides the index values for the new data. The methods GmsRtViewDs.storeData(GmsRtViewDataObject, GmsTabularData, String[]) and GmsRtViewDs.storeData(String, GmsTabularData, String[]) are used to specify the index values. The third argument in these methods is a String array containing the values for each index column, in the order they were defined in the data object exemplar.
The following example adds a Connection field to the example from the previous section. In this example, the data key remains the same, so that each unique combination of SalesRegion and Product is stored in a separate table. However, we also define the Connection as an index column. This means that a given table will contain data for several different connections, and a new column called Connection will be added to each table:
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string
exemplar.addField( “Connection” );
exemplar.addField( “SalesRegion” );
exemplar.addField( “Product” );
exemplar.addField( “Model” );
// define the data key fields—these are
// the fields in the dsstring that uniquely
// identify a data table
String[] dataKeyFields = new String[]{ “SalesRegion”, “Product” };
exemplar.setDataKeyColumnFields( dataKeyFields );
// define the index fields—these fields
// will automatically be added into new columns
// in the data table whenever new data is
// received; this additional data can be used
// to uniquely identify the source of the data
String[] indexFields = new String[]{ “Connection” };
exemplar.setIndexColumnFields( indexFields );
}
}
In our custom ds adapter class, we specify the index values when we store the data. This example is from a polled data source, where the GmsRtViewDsAdapter.updateDataObject(GmsRtViewDsObject) method is called periodically for each active data object. The SalesRegion and Product specified in the data object will determine which table contains the data (because these two fields were defined to be the data key), and the value of the Connection will be added to the table.
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void updateDataObject (GmsRtViewDataObject dataObject)
{
// determine the connection, sales region,
// product, and model required for this
// data object
String conn = dataObject.getFieldValue( “Connection” );
String region = dataObject.getFieldValue( “SalesRegion” );
String product = dataObject.getFieldValue( “Product” );
String model = dataObject.getFieldValue( “Model” );
// get the data from the external
// data source
GmsTabularData table = getSalesData(conn, region, product, model);
// store the data, indexed by Connection
String[] indexValues = new String[] { conn };
ds.storeData( dataObject, table, indexValues );
}
}
In an event-driven data source, an event handler would typically be invoked when data is changed. The following example shows how a custom adapter might store indexed data when an event is received. Note that in this example we do not have a GmsRtViewDataObject, so we must build the data key to identify the data table from the values sent to the event handler:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
private void onDataChanged (String conn, String region,
String product, GmsTabularData table)
{
// Using the SalesRegion and Product,
// build the data key to identify the
// table to be stored
String[] dataKeyValues = new String[] { region, product };
String dataKey = ds.buildDataKey( dataKeyValues );
// store the data, indexed by Connection
String[] indexValues = new String[] { conn };
ds.storeData( dataKey, table, indexValues );
}
}
Data Attachments and Data Objects
In the Display Builder, the Attach To Data dialog allows you to bind a property of an RTView object to a table or to an element within a table. In the Custom Data Adapter API, each data attachment is represented by a data object, an instance of the com.sl.gmsjrtviewds.GmsRtViewDataObject class.
The data object is a general purpose object that contains an arbitrary number of named fields. A Custom Data Adapter configures the data object at initialization time by adding fields to a class exemplar. These fields are used to automatically build the Attach To Data dialog.
A Custom Data Adapter contains a single data object exemplar, which serves as a template for all of its data attachments. The data object exemplar is initialized in the method GmsRtViewDs.initDataObjectExemplar(GmsRtViewDataObject). In this method, the Custom Data Adapter calls GmsRtViewDataObject.addField(), GmsRtViewDataObject.setDataKeyColumnFields(), and optionally GmsRtViewDataObject.setIndexColumnFields() to define the exemplar.
Note: Data object field names must not begin with two underscore characters (i.e. __) because this prefix is reserved for internal use by RTView.
In the following example we define a data object containing the fields Plant Name, Tag Name, and Retrieval Method. The Attach To Data dialog will display a combo-box for each of these fields. We designate the Plant Name as the data key, so we will have a separate table for each Plant. Finally, we designate the Tag Name as an index column. RTView will add a Tag Name column to the data table when it is stored, if a column named Tag Name does not already exist.
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string
exemplar.addField( “Plant Name” );
exemplar.addField( “Tag Name” );
exemplar.addField( “Retrieval Method” );
// define the data key fields—these are
// the fields in the dsstring that uniquely
// identify a data table
String[] dataKeyFields = new String[]{ “Plant Name” };
exemplar.setDataKeyColumnFields( dataKeyFields );
// define the index fields—these fields
// will automatically be added into new columns
// in the data table whenever new data is
// received; this additional data can be used
// to uniquely identify the source of the data
String[] indexFields = new String[]{ “Tag Name” };
exemplar.setIndexColumnFields( indexFields );
}
}
The Custom Data Adapter API provides support for scrambled fields within the data object. Scrambled fields are not stored in plain-text, so they are useful for passwords or other sensitive information. To add a scrambled field, use the method GmsRtViewDataObject.addScrambledField(String) when initializing the data object exemplar. For example,
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string
exemplar.addField( “user” );
exemplar.addScrambledField( “password” );
...
}
}
The labels that are displayed for each field in the Attach To Data dialog can be configured by adding properties to the Resource File. For information about specifying the resource file, please refer to the section Resource Bundle Name.
The property name is formed by appending the field name to the string dataKeyField_. For example, the property name for the user field would be dataKeyField_user. Here is an example of the entries in the resource file for the data object defined above:
dataKeyField_user=User Name:
dataKeyField_password=Password:
In addition to the properties for custom data fields, the resource file also contains entries for the other buttons and labels in the Attach To Data dialog:
# Attach To Data Dialog
# The Property Name label and the OK, Apply, Reset, Clear and Cancel
# buttons are shared by all Attach to Data dialogs. The localized
# values for these components are defined in rtview.properties.
# The Select Columns dialog which comes up when the user selects
# Select Columns is also shared by all of the Attach To Data dialogs.
# The localized values for this dialog’s components are defined in
# rtview.properties.
d_AttachToCustomData_Title=Attach To Custom Event DS Data
d_AttachToCustomData_Label_Column=Column(s):
d_AttachToCustomData_Label_FilterRows=Filter Rows:
d_AttachToCustomData_Label_FilterColumn=Filter Column:
d_AttachToCustomData_Label_FilterValue=Filter Value:
d_AttachToCustomData_Label_UpdateOnce=Update Once:
d_AttachToCustomData_Popup_SelectColumns=Select Columns
When a data object is stored in an RTView display, it is serialized into a string called the dsstring. The Custom Data Adapter API generates dsstrings with the following format:
dskey {token1 token2 token3}
where dskey is the unique identifier defined in the GmsRtViewDs.initDsBaseProperties(GmsRtViewDsBaseProperties) method and each token represents a field in the data object. The tokens have the following format:
fieldname=fieldvalue
where fieldname is a URL-encoded representation of the field name, and fieldvalue is a URL-encoded and optionally scrambled representation of the field value.
Note that RTView uses field names beginning with two underscore characters to store internal properties of a data object, including row and column filtering information, update once behavior, and the encoding format.
By default, each field defined in the data object is represented by a combo-box in the Attach To Data dialog. You can choose a different UI element when adding a field by using the overloaded forms of the GmsRtViewDataObject.addField() and GmsRtViewDataObject.addScrambledField() methods.
In the following example, the server will appear as a text field, the query will appear as a multi-line text area, the user will appear as a combo-box (the default), and the password will appear as a password text field.
Note: Currently the combo-box, text field, text area, and password text field are the only dialog field types supported.
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the dsstring
exemplar.addField( “server”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addField( “query”, DialogFieldType.FIELD_TEXTAREA );
exemplar.addField( “user” );
exemplar.addScrambledField( “password”,
DialogFieldType.FIELD_PASSWORD );
...
}
}
The com.sl.gmsjrtviewds.GmsRtViewDs class maintains a collection of active data objects. Data objects are added to the collection when a display is loaded, and freed when there are no more references to them. Data objects are passed to the lifecycle methods GmsRtViewDsAdapter.registerData(GmsRtViewDataObject), GmsRtViewDsAdapter.unregisterData(GmsRtViewDataObject), GmsRtViewDataAdapter.updateDataObject(GmsRtViewDataObject), and GmsRtViewDataAdapter.validate(GmsRtViewDataObject).
You can query the value of a field in a data object using the method GmsRtViewDataObject.getFieldValue(String), and you can set the value of a field using the method GmsRtViewDataObject.setFieldValue(String, String). Field values are normally only set during validation of the information entered into the Attach To Data dialog. For more information, please refer to the Dialogs section.
The following example shows how an adapter for a polled data source would query the fields of the data object to determine the data to retrieve from the external data source:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void updateDataObject (GmsRtViewDataObject dataObject)
{
// determine the data required for this
// data object
String server = dataObject.getFieldValue( “server” );
String query = dataObject.getFieldValue( “query” );
String user = dataObject.getFieldValue( “user” );
String password = dataObject.getFieldValue( “password” );
// NOTE: You would get the data from the external data source
// here...
GmsTabularData table = getData(server, query, user, password);
// store the data
ds.storeData( dataObject, table );
}
}
Custom Data Adapter - Connections
The Custom Data Adapter API provides support for named connections through the com.sl.gmsjrtviewds.GmsRtViewDsConnInfo, or conninfo object. Like the data object, the conninfo object is a general purpose object that you configure at initialization time by adding fields. The conninfo object contains one predefined field, the name of the connection. This section describes conninfo objects and the features in the Custom Data Adapter API to support them.
A Custom Data Adapter contains a single conninfo object exemplar, which serves as a template for all named connections. The conninfo exemplar is configured in the method GmsRtViewDs.initConnInfoExemplar(GmsRtViewDsConnInfo), which calls GmsRtViewDsConnInfo.addField(String) and GmsRtViewDsConnInfo.addScrambledField(String) to add fields to the exemplar. For a discussion of plain-text and scrambled fields, please refer to the “Data Object Exemplar” section.
If your Custom Data Adapter does not require the use of named connections, just add an empty GmsRtViewDs.initConnInfoExemplar(GmsRtViewDsConnInfo) method and return without adding any fields. The Connections tab in the Options dialog will not be created. For example,
public class MyDs extends GmsRtViewDs
{
public void initConnInfoExemplar (GmsRtViewDsConnInfo exemplar)
{
// this Custom Data Adapter does not use
// named connections
return;
}
}
If your Custom Data Adapter uses connections, then configure the exemplar by adding fields.
Note: Field names must not begin with two underscore characters (i.e. __) because this prefix is reserved for internal use by RTView.
In the following example, we define a conninfo object containing the fields host, port, user, and password. The password field is defined to be a scrambled field. We also specify the UI element to be used for each field in the Connections tab of the Options dialog. The host field will appear as a combo-box (the default UI element), the port and user fields will appear as text fields, and the password field will appear as a password text field.
public class MyDs extends GmsRtViewDs
{
public void initConnInfoExemplar (GmsRtViewDsConnInfo exemplar)
{
// define the fields that will appear in
// the conninfo object
exemplar.addField( “host” );
exemplar.addField( “port”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addField( “user”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addScrambledField( “password”,
DialogFieldType.FIELD_PASSWORD );
}
}
The labels that are displayed for each field in the Connections tab can be configured by adding properties to the Resource File. For information about specifying the resource file, please refer to the “Control Property: Resource Bundle Name” section.
The property name is formed by appending the field name to the string connInfoField_. For example, the property name for the host field would be connInfoField_host. Here is an example of the entries in the resource file for the conninfo object defined above:
connInfoField_host=Host Name:
connInfoField_port=Port Number:
connInfoField_user=User Name:
connInfoField_password=Password:
In addition to the properties for custom conninfo fields, the resource file also contains entries for the other buttons and labels on the Connection tab and the Connection Setup dialog:
# Connection Tab
d_Options_CustomDs_Connection_TabName=Connections
d_Options_CustomDs_Label_DefaultConnection=Default Connection:
d_Options_CustomDs_Button_Add=Add Connection
d_Options_CustomDs_Button_Remove=Remove Connection
d_Options_CustomDs_Label_Connections=Connections:
# Connection Setup Dialog
d_Options_CustomDs_AddConn_Title= Add Connection
d_Options_CustomDs_AddConn_Label_ConnName=Connection Name:
d_Options_CustomDs_AddConn_Button_OK=OK
d_Options_CustomDs_AddConn_Button_Clear=Clear
d_Options_CustomDs_AddConn_Button_Reset=Reset
d_Options_CustomDs_AddConn_Button_Cancel=Cancel
d_Options_CustomDs_AddConn_Button_Help=Help
The conninfo objects defined in the Connections tab of the Options dialog are stored as strings in the Options File. For details about specifying the options file, please refer to the “Base Property: Option File Name” section.
Each conninfo object is written to the options file with the following format:
<dskey>conn token1 token2 token3 ...
where <dskey> is the unique identifier defined in the GmsRtViewDs.initDsProperties(GmsRtViewDsProperties) method and each token represents a field in the conninfo object. The tokens have the following format:
fieldname=fieldvalue
where fieldname is a URL-encoded representation of the field name, and fieldvalue is a URL-encoded and optionally scrambled representation of the field value.
Note: RTView uses field names beginning with two underscore characters to store internal properties of a conninfo object.
The following example shows a conninfo object named conn2 in a Custom Data Adapter with the custom-eventds dskey. The connection refers to the host server1 and port 3333:
custom-eventdsconn __name=conn2 host=server1 port=3333
Establishing Connections
At program startup, the method GmsRtViewDsAdapter.attemptConnection(GmsRtViewDsConnInfo) is invoked for each defined connection. Each connection attempt is made on a different thread.
The attemptConnection method returns a ConnectStatus indicating whether or not the attempt was successful. There are three possible values:
ConnectStatus.SUCCEEDED |
The connection attempt was successful. |
ConnectStatus.FAILED |
The connection attempt failed (this time). |
ConnectStatus.INVALID |
The connection is invalid as configured. It will never connect. |
If the adapter returns ConnectStatus.FAILED, the attemptConnection method will be invoked again to try to establish the connection. If the adapter returns ConnectStatus.INVALID, the conninfo is assumed to be configured improperly, and the attemptConnection method will not be invoked again.
Here is an example of the attemptConnection method for the conninfo object defined above:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected ConnectStatus attemptConnection (GmsRtViewDsConnInfo connInfo)
{
String host = connInfo.getFieldValue( “host” );
String port = connInfo.getFieldValue( “port” );
String user = connInfo.getFieldValue( “user” );
String password = connInfo.getFieldValue( “password” );
if (host == null || host.length() == 0 ||
port == null || port.length() == 0) {
return ConnectStatus.INVALID;
}
// NOTE: your “openConnection” method would establish a
// connection to your external data source
boolean success = openConnection(host, port, user, password);
if (success) {
return ConnectStatus.SUCCEEDED;
} else {
return ConnectStatus.FAILED;
}
}
}
Closing Connections
At program termination, the GmsRtViewDsAdapter.closeConnection(GmsRtViewDsConnInfo) method is invoked for each open connection. A Custom Data Adapter should override this method to close the connection to the external data source. For example,
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void closeConnection (GmsRtViewDsConnInfo connInfo)
{
String host = connInfo.getFieldValue( “host” );
String port = connInfo.getFieldValue( “port” );
String user = connInfo.getFieldValue( “user” );
String password = connInfo.getFieldValue( “password” );
// NOTE: your “closeConnection” method would close the
// connection to your external data source
closeConnection(host, port, user, password);
return;
}
}
A Custom Data Adapter can also inform RTView that a connection has been closed by calling the method GmsRtViewDsConnInfo.setDisconnected(). RTView will then try to re-establish the connection as described above in the section Establishing Connections. The following example shows how a custom adapter for a polled data source might detect a broken connection when trying to update data:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void updateDataObject (GmsRtViewDataObject dataObject)
{
// get connection name from the
// data object
String connName = dataObject.getFieldValue( “conn” );
if (connName = null || connName.length() == 0) {
return;
}
// get conninfo object and extract
// fields
GmsRtViewDsConnInfo connInfo = ds.getConnInfoFromName( connName );
if (connInfo == null) {
return;
}
String host = connInfo.getFieldValue( “host” );
String port = connInfo.getFieldValue( “port” );
String user = connInfo.getFieldValue( “user” );
String password = connInfo.getFieldValue( “password” );
// NOTE: your “isConnected” method would check the
// connection to your external data source
boolean connected = isConnected(host, port, user, password);
// if not connected, alert DS
// to attempt to reconnect
if (!connected) {
connInfo.setDisconnected();
return;
}
// get data...
...
}
}
Custom Data Adapter - Data Source Options
The Custom Data Adapter API provides support for user-supplied options through the com.sl.gmsjrtviewds.GmsRtViewDsOptions, or ds options object. Like the data object and conninfo object, the ds options object is a general purpose object that you configure at initialization time by adding fields. However, unlike those objects, there is only one ds options object for the entire Custom Data Adapter. All options are stored as fields on this object.
This section describes the ds options object and the features in the Custom Data Adapter API to support it.
A Custom Data Adapter contains a single ds options object exemplar, which is configured in the method GmsRtViewDs.initDsOptionsExemplar(GmsRtViewDsOptions). In this method, the Custom Data Adapter uses the methods GmsRtViewDsOptions.addField(String) and GmsRtViewDsOptions.addScrambledField(String) to add fields to the exemplar. For a discussion of plain-text and scrambled fields, please refer to the “Data Object Exemplar” section.
If your Custom Data Adapter does not require any user-supplied options, just add an empty GmsRtViewDs.initDsOptionsExemplar(GmsRtViewDsOptions) method and return without adding any fields. The Options tab in the Options dialog will not be created. For example:
public class MyDs extends GmsRtViewDs
{
public void initDsOptionsExemplar (GmsRtViewDsOptions exemplar)
{
// this Custom Data Adapter does not define any
// user-supplied options
return;
}
}
If your Custom Data Adapter requires user-supplied options, then configure the exemplar by adding fields.
Note: Field names must not begin with two underscore characters (i.e. __) because this prefix is reserved for internal use by RTView.
In the following example, we define a ds options object containing three fields. The defaultUser and defaultPassword fields will be used for connection management, in case the user leaves these fields blank when defining conninfo objects. The field maxPoints will be used for data management, to limit the size of data returned from the external data source:
public class MyDs extends GmsRtViewDs
{
public void initDsOptionsExemplar (GmsRtViewDsOptions exemplar)
{
// define the fields that will appear in
// the ds options object
exemplar.addField( “defaultUser”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addScrambledField( “defaultPassword”,
DialogFieldType.FIELD_PASSWORD );
exemplar.addField( “maxPoints”, DialogFieldType.FIELD_TEXTFIELD );
}
}
The labels that are displayed for each field in the Options tab can be configured by adding properties to the Resource File. For information about specifying the resource file, please refer to the “Control Property: Resource Bundle Name” section.
The property name is formed by appending the field name to the string dsOptionsField_. For example, the property name for the defaultUser field would be dsOptionsField_defaultUser. Here is an example of the entries in the resource file for the ds options object defined above:
dsOptionsField_defaultUser=Default User Name:
dsOptionsField_defaultPassword=Default Password:
dsOptionsField_maxPoints=Maximum Number of Data Points:
In addition to the properties for custom ds options fields, the resource file also contains entries for the label on the Options tab, and for a Dummy Tab Message. The dummy tab message is displayed only if you do not define any fields in both the ds options and conninfo object exemplars:
# Options Tab
d_Options_CustomDs_Options_TabName=Options
# Dummy Tab message
d_Options_CustomDs_Label_NoOptions=This data source does not \
have any customizable options.
All DS Options are stored in the Options File. For details about specifying the options file, please refer to the “Base Property: Option File Name” section.
Each field in the ds options object is written to the options file on a separate line, using the following format:
<dskey>option token1
where <dskey> is the unique identifier defined in the GmsRtViewDs.initDsBaseProperties(GmsRtViewDsBaseProperties) method and the token represents a field in the ds options object. The token has the following format:
fieldname=fieldvalue
where fieldname is a URL-encoded representation of the field name, and fieldvalue is a URL-encoded and optionally scrambled representation of the field value.
The following example shows the ds options defined above, in a Custom Data Adapter with the dskey custom-eventds. The defaultPassword field is scrambled:
custom-eventdsoption defaultUser=sales
custom-eventdsoption defaultPassword=8i539k5fa47e864l75032
custom-eventdsoption maxPoints=1000
During initialization, each DS Option is passed to the custom ds adapter in a separate call to the method GmsRtViewDsAdapter.applyDsOption(String, String). A Custom Data Adapter would override this method to process the options for later use. The return value from this method indicates whether the option was successfully processed.
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected boolean applyDsOption (String name, String value)
{
if (name.equals( “defaultUser” )) {
if (value.length() == 0) return false;
defaultUserName = value;
return true;
} else if (name.equals( “defaultPassword” )) {
if (value.length() == 0) return false;
defaultPassword = value;
return true;
} else if (name.equals( “maxPoints” )) {
if (value.length() == 0) return false;
try {
maxPoints = Integer.valueOf( value );
} catch( NumberFormatException nfe ) {
return false;
}
return true;
}
return false;
}
}
The Custom Data Adapter API includes classes to automatically create dialogs for the objects defined by the Custom Data Adapter. The Attach To Data dialog is created for the com.sl.gmsjrtviewds.GmsRtViewDataObject, the Connections tab is created for the com.sl.gmsjrtviewds.GmsRtViewDsConnInfo object, and the Options tab is created for the com.sl.gmsjrtviewds.GmsRtViewDsOptions object.
This section describes the features available in the Custom Data Adapter API to control the appearance and contents of these dialogs. The procedures for configuring the dialogs and validating user input are almost identical for each of the objects, so the concepts and techniques described in each subsection may be applied to any of the dialogs, except where noted.
In the dialog, each field in an object is represented by a Swing control and a corresponding label. The default control for a field is a combo-box, but this may be changed by specifying the dialog field type (com.sl.gmsjrtview.DialogFieldType) when adding the field to the exemplar during initialization.
The Custom Data Adapter API currently supports the following dialog field types:
DialogFieldType.FIELD_COMBOBOX |
Combo-box |
DialogFieldType.FIELD_TEXTFIELD |
Single-line text field |
DialogFieldType.FIELD_TEXTAREA |
Multi-line text field |
DialogFieldType.FIELD_PASSWORD |
Text field for entering passwords |
In the following example, a conninfo object is defined and dialog field types are specified as fields are added. In the Connections tab, the host field will be represented by a combo-box, user will be a text field, and password will be a password text field:
public class MyDs extends GmsRtViewDs
{
public void initConnInfoExemplar (GmsRtViewDsConnInfo exemplar)
{
// define the fields that will appear in
// the conninfo object
exemplar.addField( “host” );
exemplar.addField( “user”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addScrambledField( “password”,
DialogFieldType.FIELD_PASSWORD );
}
}
When the exemplar is defined, default values can be specified for each field. The following example sets default values for each of the fields in the conninfo object exemplar:
public class MyDs extends GmsRtViewDs
{
public void initConnInfoExemplar (GmsRtViewDsConnInfo exemplar)
{
// define the fields that will appear in
// the conninfo object
exemplar.addField( “host” );
exemplar.addField( “user”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addScrambledField( “password”,
DialogFieldType.FIELD_PASSWORD );
// set default values for each field
exemplar.setFieldValue( “host”, “SERVER1” );
exemplar.setFieldValue( “user”, “guest” );
exemplar.setFieldValue( “password”, “guest” );
}
}
A default list of choices for a combo-box can be specified when the exemplar is defined, if the choices are known at initialization time. If the choices are not known, for example if they depend on a value entered into another field, the list of choices can also be set during dialog validation, as described in the “Validation” section.
The following example initializes a field named retrievalMode to contain three choices: Current Data, Historical Data, and Current and Historical Data. Because these choices are set on the data object exemplar, they will appear in the retrievalMode combo-box for each data attachment:
import java.util.Set;
import java.util.LinkedHashSet;
public class MyDs extends GmsRtViewDs
{
static final Set<String> retrievalModeChoices;
static {
retrievalModeChoices = new LinkedHashSet<String>();
retrievalModeChoices.add( “Current Data” );
retrievalModeChoices.add( “Historical Data” );
retrievalModeChoices.add( “Current and Historical Data” );
}
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string, in order
exemplar.addField( “conn” );
exemplar.addField( “pointName”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addField( “retrievalMode” );
// set the list of choices for the
// retrievalMode combo-box
exemplar.setFieldChoices( “retrievalMode”, retrievalModeChoices );
}
}
The UI state controls whether a control is visible, invisible, disabled, or editable. By default, each field in a dialog is visible and editable. The UI state is typically set during data validation, but the UI state for a field can also be changed in the exemplar during initialization to provide a different default state.
The UI State can be set to the following values:
DialogFieldState.HIDDEN |
Field is not visible. |
DialogFieldState.DISABLED |
Field is grayed-out |
DialogFieldState.ENABLED |
Field is visible but not editable |
DialogFieldState.EDITABLE |
Field is editable |
DialogFieldState.UNKNOWN |
The UI state has not been set |
In the following example, the default UI state for the pointName and retrievalMode fields is set to disabled. When the Attach To Data dialog is displayed, these fields will be grayed-out. Presumably, the validate method in this Custom Data Adapter would make these fields editable when a valid connection was chosen:
public class MyDs extends GmsRtViewDs
{
public void initDataObjectExemplar (GmsRtViewDataObject exemplar)
{
// define the fields that will appear in
// the ds string, in order
exemplar.addField( “conn” );
exemplar.addField( “pointName”, DialogFieldType.FIELD_TEXTFIELD );
exemplar.addField( “retrievalMode” );
// disable (gray-out) the pointName and
// retrievalMode fields
exemplar.setFieldUIState( “pointName”, DialogFieldState.DISABLED );
exemplar.setFieldUIState( “retrievalMode”,
DialogFieldState.DISABLED );
}
}
The field validity controls the background color of the field in the dialog. Valid fields are white, invalid fields are red, and unknown fields are gray. The field validity can be set to the following values:
DataFieldValidity.GOOD |
Field is valid |
DataFieldValidity.BAD |
Field is invalid |
DataFieldValidity.UNKNOWN |
Field validity is unknown |
In the following example, a data object is validated in the GmsRtViewDsAdapter.validate(GmsRtViewDataObject) method. If the retrievalMode field has not been set to one of the allowable values, the field is marked as invalid:
import java.util.Set;
import java.util.LinkedHashSet;
public class MyDsAdapter extends GmsRtViewDsAdapter
{
static final Set<String> retrievalModes;
static {
retrievalModes = new LinkedHashSet<String>();
retrievalModes.add( “Current Data” );
retrievalModes.add( “Historical Data” );
retrievalModes.add( “Current and Historical Data” );
}
@Override
protected void validate (GmsRtViewDataObject dataObject)
{
String mode = dataObject.getFieldValue( “retrievalMode” );
if (mode.length() > 0) {
if (retrievalModes.contains(mode))
dataObject.setFieldValidity( “retrievalMode”,
DataFieldValidity.GOOD );
else
dataObject.setFieldValidity( “retrievalMode”,
DataFieldValidity.BAD );
}
...
}
}
Handling Substitutions in Fields
When validating objects, you may need to apply substitutions in order to determine whether a field is valid. For example, you might find the value $conn entered into a connection field. If a substitution is available for $conn, you can get the substituted value by using the getFieldSubstitutionValue() method. For example:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void validate (GmsRtViewDataObject dataObject)
{
// get the value entered into the conn
// field after applying substitutions
String conn = dataObject.getFieldSubstitutionValue( “conn” );
GmsRtViewDsConnInfo conninfo = ds.getConnInfoFromName( conn );
...
}
}
The GmsRtViewDsAdapter class provides a validate() method for each of the automatically generated dialogs. A custom subclass can override these methods to add validation logic. Using methods in the Custom Data Adapter API, the validation methods can query and set field values, modify the UI state to hide or gray-out a field, update the available field choices, or set the field validity to change the background color of the field.
When a data object is edited in the Attach To Data dialog, the GmsRtViewDsAdapter.validate(GmsRtViewDataObject) method is called when the dialog is first displayed, whenever the focus changes, and when the dialog is dismissed. A subclass can override this method to perform custom validation.
In the following example, we query the value of the server field. If the user has entered a server name, we check to see whether the server name is valid, and set the field validity. If the server name is valid, we also set the available choices for the pointName combo-box.
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void validate (GmsRtViewDataObject dataObject)
{
String server = dataObject.getFieldValue( “server” );
if (server == null || server.length() == 0)
return;
// you would check whether the server name was valid here ...
boolean isValid = MYCLASS.isServerValid(server);
if (isValid) {
dataObject.setFieldValidity( “server”,
DataFieldValidity.GOOD );
// ... you would get the available point names
// for the server here ...
Set<String> pointNames = MYCLASS.getPointNames(server);
dataObject.setFieldChoices( “pointName”, pointNames );
} else {
dataObject.setFieldValidity( “server”,
DataFieldValidity.BAD );
}
}
}
When a conninfo object is edited in the Connections tab, the GmsRtViewDsAdapter.validate(GmsRtViewDsConnInfo) method is called when the dialog is first displayed, whenever the focus changes, and when the dialog is dismissed. A subclass can override this method to perform custom validation. In the following example, we check that the value in the port field is numeric:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void validate (GmsRtViewDsConnInfo connInfo)
{
String port = connInfo.getFieldValue( “port” );
DataFieldValidity validity = DataFieldValidity.GOOD;
if (port.length() > 0) {
try {
int i = Integer.valueOf(port);
} catch(NumberFormatException nfe) {
validity = DataFieldValidity.BAD;
}
}
connInfo.setFieldValidity( “port”, validity );
}
}
When the ds options object is edited in the Options tab, the GmsRtViewDsAdapter.validate(GmsRtViewDsOptions) method is called when the dialog is first displayed, whenever the focus changes, and when the dialog is dismissed. A custom ds adapter can override this method to perform custom validation. In the following example, we check that the value in the maxPoints field is a positive number:
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void validate (GmsRtViewDsOptions dsOptions)
{
String maxPoints = dsOptions.getFieldValue( “maxPoints” );
DataFieldValidity validity = DataFieldValidity.GOOD;
if (maxPoints.length() > 0) {
try {
int i = Integer.valueOf(maxPoints);
if (i <= 0)
validity = DataFieldValidity.BAD;
} catch(NumberFormatException nfe) {
validity = DataFieldValidity.BAD;
}
}
dsOptions.setFieldValidity( “maxPoints”, validity );
}
}
Localization and Customization
In each of the dialogs, the field label defaults to the field name. These labels can be customized by adding properties to the Resource File. For information about specifying the resource file, please refer to the “Control Property: Resource Bundle Name” section. The property name consists of a prefix followed by the field name, as shown below (where xxxxx is the field name):
dataKeyField_xxxxx
connInfoField_xxxxx
dsOptionsField_xxxxx
The following example shows custom labels for the machine and pointName fields in the data object, for the server and port fields in the conninfo object, and for the maxPoints and defaultServer fields in the ds options object:
dataKeyField_machine=Machine Name:
dataKeyField_pointName=Point Name:
connInfoField_server=Server Name:
connInfoField_port=Port Number:
dsOptionsField_maxPoints=Maximum Number of Points:
dsOptionsField_defaultServer=Default Server Name:
The resource file also contains entries for the labels shown on standard buttons and controls in the dialogs, allowing these objects to be customized or localized as well. For specific information please refer to the Localization section for the appropriate object.
Row and Column Filtering Choices
Note: This section only applies to the Attach To Data dialog, and only when row or column filtering has been enabled for the Custom Data Adapter. For more information about enabling row and column filtering, please refer to the “Column Filtering” section.
If row filtering has been enabled for the data adapter, the Attach To Data dialog will contain a Filter Column combo-box. If column filtering has been enabled for the data adapter, the Attach To Data dialog will contain a Column(s) combo-box and column chooser. You can set the available columns for these controls using the method GmsRtViewDataObject.setAvailableColumns(Set<String>).
The available columns are typically set in the method GmsRtViewDsAdapter.validate(GmsRtViewDataObject), as shown in the following example.
In this example, we use the data object to locate the corresponding data table. If data has previously been stored, we query the column names from the data table to set the available columns. If data has not previously been stored for this table, we assume we know nothing about the table structure and we make the set of available columns empty.
public class MyDsAdapter extends GmsRtViewDsAdapter
{
@Override
protected void validate (GmsRtViewDataObject dataObject)
{
// Make empty Set
Set<String> dataColumns = new HashSet<String>();
// Try to locate a data table for this
// data object
String dataKey = ds.buildDataKey(dataObject);
if (dataKey != null) {
GmsTabularData tabularData = ds.getStoredDataTable(dataKey);
// If the table is found, add the column names
// to the set of available columns
if (tabularData != null) {
int numColumns = tabularData.getNumColumns();
String[] columnNames = tabularData.getColumnNames();
for (int i = 0 ; i < numColumns; i++) {
dataColumns.add(columnNames[i]);
}
}
// Set the available columns for the combo-box
// and column chooser
dataObject.setAvailableColumns(dataColumns);
}
}