skip to main content
Programmer's documentation > Developing with the JViews Charts SDK > Using the Data Model > Predefined Data Classes
 
Predefined Data Classes
Describes the various classes available in the ilog.views.chart.data package and its subpackages, and how to use them to display your application data.
*Data set classes
*Describes the various data set classes and how to use them.
*Data Source Classes
*Describes the various data source classes and how to use them.
Data set classes
This section describes the various data set classes and explains how to use them.
Data set classes hierarchy
Illustrates the data set class hierarchy.
Data Set Classes Hierarchy
Abstract implementation
The IlvAbstractDataSet class provides default implementations for most of the methods in the IlvDataSet interface. For example, it provides support for listeners, properties handling, access to data limits, and spatial requests.
To create a concrete data set as a subclass of IlvAbstractDataSet, you need to provide an implementation for the following methods:
public abstract int getDataCount();
public abstract double getXData(int idx);
public abstract double getYData(int idx);
In other words, you have to provide the indexed access to data points. As IlvAbstractDataSet defines no-op methods for writing operations, the setData and addData methods need to be overridden as if you want your data set to be editable.
The IlvAbstractDataSet class is usually the preferred choice to write a custom data set, as it greatly simplifies the work that needs to be done. However, there may be cases with more suitable alternatives, for example:
*You need to control the implementation of all methods defined in the IlvDataSet interface so that the result matches more closely the structure of your original data.
*The data set that you want to implement can be expressed as a combination of values stored in existing data sets. In that case the IlvCombinedDataSet class can be the best choice. More information on the IlvCombinedDataSet class can be found in section Data set combination.
*Your data set is just an extension of one of the provided concrete implementations (for example IlvDefaultDataSet ).
In-memory implementation
The IlvDefaultDataSet class provides a concrete data set implementation, where data points are stored in memory with arrays of double primitives. This class supports writing operations such as appending a new data point or changing values of an existing data point.
By using the IlvDefaultDataSet class, you can specify whether x-values should be stored in memory or computed according to the indices of data points (such data sets are also called category data sets, because x-values correspond to a category number). You can also specify whether the array provided to initialize the data set contents should be copied.
Here are several examples of in-memory data sets creation.
 
// Create an empty data set that stores x-values.
IlvDataSet ds1 = new IlvDefaultDataset("DS1");
 
// Create a category data set and initialize it with a copy of
// the specified y-values.
double[] yValues = new double[] {3., 1., 4.5, 2., 7., 6.3};
IlvDataSet ds2 = new IlvDefaultDataset("DS2", yValues);
 
// Create a set and initialize the specified x-values and y-values
// arrays.
double[] xValues = new double[] {1., 2., 4., 6., 7., 8.};
double[] yValues = new double[] {3., 1., 4.5, 2., 7., 6.3};
IlvDataSet ds3 = new IlvDefaultDataset("DS3", xValues, yValues, false);
Alternatively, you can create data sets from an N-dimensional array of doubles with the create method:
 
double[][] data = new double[][]
{
{1.8, 2., 2.7, 4.5, 4.8, 2.8, 2., 2.2, 3.3, 3.5, 2.2, 1.8},
{2.1, 1., 6.6, 6.8, 8.0, 2.4, 3., 1.5, 1.5, 0.7, 0.7, 2.2},
{0.9, 0.9, 2.3, 3., 2.1, 3.4, 3.8, 5.1, 1.5, 6., 5.5, 0.4},
{1.4, 0.4, 3.8, 2.7, 6.9, 1., 0.7, 1., 2.3, 2.2, 2.4, 2.5}
};
 
String[] names = { "Norm", "1998", "1999", "2000"};String[] dataLabels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
// Create data sets from the specified data values, data labels,
// and data set names.
IlvDataSet[] dataSets = IlvDefaultDataSet.create(data, -1, names, dataLabels);
Fixed-size storage
The IlvCyclicDataSet class is a subclass of IlvDefaultDataSet that allows only a limited number of data points to be stored in memory. When new data is appended beyond this limit, the oldest values are removed so that the cardinality remains the same.
This class is particularly useful for real-time charting where new data comes in a constant stream, and only a restricted history of past values should be kept.
The following restrictions apply when using the IlvCyclicDataSet class:
*The visible range of the x-axis of any chart displaying a cyclic data set must be contained within the x-limits of this data set.
*Data indices are mutable in a cyclic data set. This means that objects like rendering hints or annotations cannot refer to a data point by its index (more information on rendering hints and annotations can be found in Handling chart renderers).
Example: Using Cyclic Data Sets
The complete source code of this example can be found in <installdir>/jviews-charts/codefragments/chart/fixed-size-storage/src/FixedSizeStorage.java.
The following code extract initializes an IlvCyclicDataSet with a buffer size equals to the value of the VISI_COUNT constant:
 
// Create the data sets. The data sets containing the random values are
// instances of IlvCyclicDataSet with a buffer size equal to VISI_COUNT and
// no x values storage.
inputData = new IlvCyclicDataSet("Input", VISI_COUNT, false);
chart = createChart();
IlvSingleChartRenderer r = createRenderer(chart);
chart.addRenderer(r, inputData);
The code below shows how new data points are added to the CyclicDataSet. In order to minimize the number of notifications, the addData() calls are wrapped between a startBatch()/endBatch() sequence:
 
void addData()
{
    inputData.startBatch();
    for (int j=0; j<UPDATE_COUNT; ++j) {
        inputData.addData(0, RandomGenerator.rand(counter));
        ++counter;
    }
    inputData.endBatch();
}
Data set combination
The IlvCombinedDataSet abstract class allows you to define a data set that can be expressed as a combination of one or several values from one or several data sets. Here are two examples.
Example: Creating a Data Set as the Moving Average of Another Data Set
The moving average of a data set is implemented by the IlvMovingAvgDataSet class. The following code shows how to create a data set as the moving average of another data set using this predefined class:
 
IlvDataSet ds = ...; // original data set
IlvDataSet movingAvg = new IlvMovingAvgDataSet(ds, 10);
Example: Displaying the Average of Two Data Sets
For this example, two solutions are proposed:
*First solution
The complete source code of this solution can be found in <installdir>/jviews-charts/samples/listener/index.html.
Compute the corresponding average data points and store them in an in-memory data set (for example IlvDefaultDataSet). Then, we need to explicitly register listeners to the original data sets so that we can update our in-memory data set (modify data points or append new ones).
Combine Data Set (1) illustrates this first solution:
Combine Data Set (1)
*Second solution
The complete source code of this solution can be found in <installdir>/jviews-charts/samples/minmax/index.html.
Create a subclass of IlvCombinedDataSet that references the original data sets and dynamically computes the average whenever the values of data points are queried. Combine Data Set (2) illustrates the second solution:
Combine Data Set (2)
The following code extract shows an implementation of such a solution. The IlvCombinedDataSet subclass overrides the getYData(int idx) method to compute the value taking into account the points of the specified index of all datasets handled by this combined data set.
 
    /**
     * Returns the data resulting from an operation on the specified series.
     */
    abstract protected double getData(double[] values);
 
    /**
     * Returns the y value of the data point at the specified index.
     */
    public double getYData(int idx)
    {
        int count = getDataSetCount();
        double[] values = new double[count];
        for (int i=0; i<count; ++i)
            values[i] = getDataSet(i).getYData(idx);
        return getData(values);
    }
This implementation actually delegates the value calculation to the abstract getData(double[] values) method that subclass should implement.
For example, to compute the average of the values, the implementation would be;
 
        protected double getData(double[] values)
        {
            double total = 0.;
            for (int i=0; i<values.length; ++i) {
                total += values[i];
            }
            return total/values.length;
        }
Compared to the first solution, the advantage of using a combined data set is twofold:
*The data set combinations implicitly listen to the changes on the original data sets, so that they can send appropriate change events.
*The generated data is dynamically evaluated, which saves memory.
The use of IlvCombinedDataSet is only suitable when the data can be calculated from the original data sets. For example, this is not the case if we want to represent the maximum value taken by data points across time.
In this situation, we have to keep track of former values and cannot rely only on the values available at a given time.
When the choice does exist between the two solutions, the following issues must be considered:
*The tradeoff between saving memory and the overhead of computing the values dynamically. Sometimes, the expense of computing the values for complex operations outweighs the savings in memory.
*Is the context dynamic or static? If the contents of the original data sets changes, you benefit from the implicit subscription made by IlvCombinedDataSet. In this case, the use of dynamic evaluation is also justified, rather than storing pre-computed values. Likewise, using IlvCombinedDataSet has an advantage if the behavior of the created data set should be dynamic (for example, it is implemented as a mutable function of the values in the original data sets).
Function Implementation
The IlvFunctionDataSet abstract class is designed to represent a data set whose y-values are computed by a function call.
To create a concrete data set as a subclass of IlvFunctionDataSet, the callFunction method must be implemented to perform the desired calculation. Function data sets are then instantiated by providing a definition domain and a number of examples.
Example: Data Set Representing the Cosine Function With a Point Every Degree
The complete source code of this example can be found in <installdir>/jviews-charts/samples/logarithm/index.html.
Data Set Representing the Cosine Function With a Point Every Degree
 
IlvDataSet ds =
   new IlvFunctionDataSet(0, 2*Math.PI, 361){
     public double callFunction(double val){
       return Math.cos(val);
      }
};
The IlvFunctionDataSet class is primarily intended to represent mathematical functions, and has the advantage of not storing values into memory.
Load-On-Demand Data Set
The IlvLODDataSet class implements a data set whose contents is loaded on demand. For more information on this feature, please refer to Using Load-On-Demand.
Data Source Classes
This section describes the various data source classes and explains how to use them.
Data source classes hierarchy
Illustrates the data source class hierarchy.
Data Source Classes Hierarchy
Abstract implementation
The IlvAbstractDataSource class stores the list of accessible data sets, and provides the reading methods to access this collection. It also manages a list of listeners that are notified of changes in the data source contents.
NOTE No method of this class is abstract. Concrete subclasses will usually implement the data set creation, and use the initDataSets protected method to initialize the data source contents. Another alternative is to modify directly the list returned by the getDataSetList protected method. All the writing methods have an empty implementation that needs to be overridden if the contents is editable from the outside.
Editable data source
The IlvDefaultDataSource class is a direct subclass of IlvAbstractDataSource that provides implementations for editing operations. It behaves as an editable data source where data sets can be added or removed explicitly, and can be used to access data that comes from different sources. This class is used by default by the chart renderers.
For more information, refer to Creating the data model.
Reading data from an input source
The JViews Charts library defines IlvInputDataSource as a general-purpose class for reading data from an input source. An input source can be of two forms:
*generic java.io.InputStream object
*URL
A data reader (defined by the IlvDataReader interface) is used to decode the data stored in the input source. This data reader is provided as parameter to the two load methods of the IlvInputDataSource class:
 
public void load(InputStream in, IlvDataReader reader) throws Exception
public void load(String url, IlvDataReader reader) throws Exception
By calling one of these load methods, you reinitialize the contents of the data source with the data sets extracted by the reader. The IlvDataReader interface defines the following methods to load data from the input source:
public IlvDataSet[] read(InputStream in) throws Exception
public IlvDataSet[] read(String url) throws Exception
You use IlvDataInputSource by writing a reader for each specific data format.
The JViews Charts library provides the following examples of custom data readers:
Example: stock
This example shows how to define a reader that reads quote values in CSV (Comma Separated Value) format.
The complete source code of this example can be found in <installdir>/jviews-charts/samples/stock/src/shared/CSVDataReader.java.
Example: load-on-demand
This example shows how to read data stored as 32-bit integers from a binary stream.
The complete source code of this example can be found in <installdir>/jviews-charts/samples/lod/src/lod/BinaryInt32Reader.java.
I n this example, you create an instance of your reader and use it with either an InputStream or a URL description. Both parameters are provided to the IlvInputDataSource constructor, which loads the data automatically.
The following code is extracted from the Load-On-Demand example and shows how to use a custom reader with an IlvInputDataSource.
Using a Custom Reader with an IlvInputDataSource
 
InputStream in = null;
try {
  // Create the reader.
  IlvDataReader reader = new BinaryInt32Reader();
  // Create an InputStream from a file.
  in = new BufferedInputStream(
         new FileInputStream(
           new File(System.getProperty("user.dir"),
                                       "sampleData.dat")));
  IlvInputDataSource sampleDataSource = new IlvInputDataSource(in, reader);
} catch (Exception x) {
  x.printStackTrace();
  System.err.println(x.getMessage());
} finally {
  if (in != null) try {in.close();} catch (Exception x) {}
}
NOTE The InputStream object must be explicitly closed after the loading is performed, whereas connection and disconnection are automatically handled when using a URL.
Reading and writing data from an XML source
The JViews Charts library lets you export or import data in a predefined XML-based format. The ilog.views.chart.data.xml package contains all the classes that are related to XML serialization:
*IlvXMLDataReader, creates the data sets by interpreting the contents of an XML file.
*IlvXMLDataWriter, serializes the data sets in an XML file.
*IlvXMLDataSource, implements a data source dedicated to XML input.
In order to use the ilog.views.chart.data.xml package with Java™ SE 5, you need Apache™ Xerces 2.4.0 or higher in your CLASSPATH. A copy of Apache Xerces can be found in the <installdir>/jviews-framework/lib/ directory.
Reading data from an XML document
The IlvXMLDataReader class implements the IlvDataReader interface and can be used with the general-purpose IlvInputDataSource class.
The following code shows how to read the contents of an XML file, and make it available for charting through an IlvXMLDataSource:
 
// Create the data source.
IlvXMLDataSource ds = new IlvXMLDataSource();
// Create the XML reader.
IlvXMLDataReader reader = new IlvXMLDataReader();
// Optional: Specify that the parser should validate the contents of the file
reader.setValidating(true);
// Load the data.
ds.load(new org.xml.sax.InputSource("data.xml"), reader);
Writing data to an XML document
The IlvXMLDataWriter class allows you to write data sets into an XML document, as shown in the following code:
 
import javax.xml.parsers.*;
import org.w3c.dom.Document;
...
IlvDataSet[] dataSets = ...;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
IlvXMLDataWriter writer = new IlvXMLDataWriter();
writer.write(document, dataSets);
You can also directly serialize the data sets into an output stream, as shown in the next example:
 
IlvDataSet[] dataSets = ...;
IlvXMLDataWriter writer = new IlvXMLDataWriter();
writer.write(new FileOutputStream("chartmodel.xml"), dataSets);
Example: serializing data
A complete example that shows how to import and export data using XML can be found in <installdir>/jviews-charts/codefragments/chart/xml-serialization/src/XMLSerialization.java.
Description of the format
The expected format is an application of the W3C XML language. You can find the full Document Type Definition of this format in Document Type Definition for XML data file in Using the Designer. For more information see XML file format.
The data is described with the following elements:
The chartData element, which belongs to the ilvchart namespace:
 
<!ELEMENT chartData (data+)>
<!ATTLIST chartData xmlns:ilvchart CDATA #FIXED
                      "http://www.ilog.com/products/jviews/chart"
                    version CDATA #REQUIRED>
This root element contains a set of child data elements:
 
<!ELEMENT data (labels?,series+)>
<!ATTLIST data xSeries IDREF #IMPLIED>
Each data element can be seen as a table where rows are represented by one or more series elements. One of these series can be identified as the one holding the x-values. In this case, the other series are assumed to hold the y-values of the considered data.
Series data points might be associated with labels by means of the labels element. Labels can be either defined common to all the series of a data element, or individually for each series. In this case, the labels are specified at the series element level, and override labels that may have been set on the data element.
The series element has the following description:
 
<!ELEMENT series ((valueOperator | (value | valuesList)*),labels?,property*)>
<!ATTLIST series dateFormat CDATA #IMPLIED
                 type (double | date) #REQUIRED
                 id ID #REQUIRED>
Each series is identified by a unique ID and the type of data it contains (either double values or dates). The dateFormat attribute can be any pattern that conforms to the syntax used by the java.text.SimpleDateFromat class. Values can be expressed with elementary value elements, or as a list with the valuesList element:
 
<!ELEMENT value (#PCDATA)>
<!ATTLIST valuesList delimiter CDATA #IMPLIED>
The delimiter attribute specifies the separating character in the values list. The default character is a comma. Here is an example of a series element:
 
<series id="Series_1" type="double">
  <value>0.5</value>
  <valuesList>2.0,8.0,6.0,13.0,22.0,21.0,19.0,28.0,27.0
  </valuesList>
  <value>32.5</value>
</series>
You can also express the values of a series as an operation on the values of other series. This is performed by means of the valueOperator element:
 
<!ELEMENT valueOperator (seriesRef|property)*>
<!ATTLIST valueOperator class NMTOKEN #REQUIRED>
For example, the following series is defined as the moving average of the "Series_1" series:
 
<series id="Series_1_Mov._Avg." type="double">
  <valueOperator class="ilog.views.chart.data.IlvMovingAvgDataSet">
    <seriesRef ref="Series_1"/>
    <property name="period">5</property>
  </valueOperator>
</series>
The class attribute refers to the class name of the data set that implements the operation. The seriesRef element refers to a valid series identifier within the same data element.
A property element is defined as follows:
 
<!ENTITY % propertyExt "">
<!ELEMENT property (#PCDATA %propertyExt;)*>
<!ATTLIST property name CDATA #REQUIRED
                   javaClass CDATA #IMPLIED>
By default, a property element consists of text data. A property is defined by its name (the name attribute) and optionally by the Java class name of the Java object it refers (the javaClass attribute). The use of the javaClass attribute is explained in the next section.
The entity propertyExt can be defined in the internal DTD subset to add custom subelement, or custom attributes to the property element within a given document.
For example, the following lines extend the property element with additional child elements myelement:
 
<!DOCTYPE chartData SYSTEM 'chartxml.dtd'
[
<!ENTITY % propertyExt "|myproperty">
<!ELEMENT myproperty (myelement)*>
<!ELEMENT myelement .... myelement definition goes there ".>
]>
The properties can be used with valueOperator and series elements. A default mechanism allows you to specify simple properties for valueOperator elements. This mechanism uses reflection to determine which method should be called on the data set instance, as well as the expected parameter type. The method is found according to the JavaBean naming convention. For example, in the definition of your moving average operator, the setPeriod method is called:
 
<valueOperator class="ilog.views.chart.data.IlvMovingAvgDataSet">
  <seriesRef ref="Series_1"/>
  <property name="period">5</property>
</valueOperator>
Extending the XML Reader
In this section you will see how to extend the reader to deal with series properties, as well as with complex or extended properties. The IlvXMLDataReader class allows you to register readers that will be used to interpret custom properties within the XML file.
A property reader must implement the IlvXMLPropertyReader interface, which defines the following methods:
*readProperty, used to read the property from the specified DOM element.
*setProperty, used to associate the property with the corresponding data set.
By default, a predefined reader is used to decode the property value. This predefined reader decodes the property value according to the following rules:
*if the javaClass attribute is set, then the XML property value is converted into the corresponding Java class using a java.beans.PropertyEditor.
*if the javaClass attribute is missing, or if the above conversation has failed, then the Java property value is the string representation of the XML property value.
You can override this default mechanism by registering your own property reader. A reader is registered by means of the IlvXMLDataReader.registerPropertyReader (for readers to be shared between all instances) and IlvXMLDataReader.setPropertyReader (for readers specific to an instance) methods.
For example:
*to register a specific property, use the following code:
registerPropertyReader
and
aReader.setPropertyReader(aPropertyName, aReader);
*to register a default reader that is used to interpret properties with no associated reader, use the following code:
registerPropertyReader
aReader.registerPropertyReader(null, aReader);
When a property is read, the IlvXMLDataReader searches for the corresponding property reader in the following order:
*in the reader repository of the reader instance, then
*in the reader repository of the IlvXMLDataReader class.
If no reader has been registered for a property, then the IlvXMLDataReader searches for a default property reader in the following order:
*the default property reader of the reader instance, then
*the default property reader of the IlvXMLDataReader class.
If no property reader has been found, then the predefined reader is used as a fallback.
The following are examples of properties element read by the predefined readers:
 
<property name="product">JViews Charts</property>
property name="color" javaClass="java.awt.Color">red</property>
<property name="dataLabels">
Main classes,renderer,data,interactor,swing,servlet,java2d,util,graphic,other
</property>
They are respectively interpreted as the “JViews Charts” string, the java.awt.Color.red, and the last one is as the data labels of the data set.
The following example shows how to use this mechanism. The complete source code can be found in <installdir>/jviews-charts/codefragments/chart/xml-extension/src/XMLExtension.java.
You want to associate a URL for each point of a data set. These URLs will be specified in the XML file as a property of the series. To support this new custom property, you first have to extend the JViews Charts DTD:
 
<!DOCTYPE chartData PUBLIC '-//ILOG//JVIEWS/Chart 1.0' 'chartxml.dtd'
[
<!ENTITY % propertyExt "| hrefs">
<!ELEMENT hrefs (#PCDATA)>
]>
This extension means that the property element now contains a hrefs element that consists of PCDATA.
Then, you add the property to the series:
 
<chartData version="1.0">
  <data>
    <series id="Series1" type="double">
      <valuesList>353.2,191.6,160.7,54.5,36.6,34.3,31.3,28.1,25.5,45.2
      </valuesList>
      ...
      <property name="hrefs">
<hrefs>
../../../../doc/refman/ilog/views/chart/package-summary.html;
../../../../doc/refman/ilog/views/chart/renderer/package-summary.html;
../../../../doc/refman/ilog/views/chart/data/package-summary.html;
../../../../doc/refman/ilog/views/chart/interactor/package-summary.html;
../../../../doc/refman/ilog/views/chart/swing/package-summary.html;
../../../../doc/refman/ilog/views/chart/servlet/package-summary.html;
../../../../doc/refman/ilog/views/chart/java2d/package-summary.html;
../../../../doc/refman/ilog/views/chart/util/package-summary.html;
../../../../doc/refman/ilog/views/chart/graphic/package-summary.html;
../../../../doc/refman/ilog/views/chart/package-summary.html
</hrefs>
</property>
    </series>
  </data>
</chartData>
The next step is to implement an IlvXMLPropertyReader to read your custom property: class HREFPropertyReader implements IlvXMLPropertyReader.
 
{
    /** The <code>hrefs</code> property element tag. */
    public static final String HREFS_TAG = "hrefs";
 
    /**
     * Reads the specified property element.
     * This method reads an <code>hrefs</code>
      * element associated with a series and stores its contents in a
     * <code>List</code>.
     */
    public Object readProperty(org.w3c.dom.Element propertyElt)
    {
        Node child = propertyElt.getFirstChild();
        while (child != null) {
            if (child.getNodeType() == Node.ELEMENT_NODE &&
                child.getNodeName().equals(HREFS_TAG)) {
                Element hrefElt = (Element)child;
                StringTokenizer tokenizer =
                    new StringTokenizer(hrefElt.getFirstChild().getNodeValue(),
                                ";\n\t ");
                List hrefs = new LinkedList();
                while (tokenizer.hasMoreTokens())
                    hrefs.add(tokenizer.nextToken());
                return hrefs;
            }
            child = child.getNextSibling();
        }
        return null;
    }
 
    /**
     * Sets the property on the specified data set. This method sets the
    * <code>href</code>s <code>List</code> as a property
    * of the specified data set.
    */
    public void setProperty(IlvDataSet dataSet,
                            String propertyName,
                            Object value)
    {
        dataSet.putProperty(HREFPropertyReader.HREFS_TAG, value, false);
    }
 
}
Finally, you register this property reader on your IlvXMLDataReader:
 
// Register our own XMLPropertyReader
reader.setPropertyReader(HREFPropertyReader.HREFS_TAG,
                              new HREFPropertyReader());
The XML reader can also be extended to create instances of custom data sets. This is performed by overriding the createDataSet method. By default, this method returns an instance of the IlvDefaultDataSet class.
Database access through JDBC
JDBC technology offers a platform and server independent way to retrieve data stored in a database. The requests are expressed through the JDBC API, and are usually performed in three steps:
*Establish the connection to the server.
*Execute a database statement (SQL query).
*Process the result of the request. This result is available through a java.sql.ResultSet object, which presents a tabular structure.
Database processing is actually performed by a driver, which depends on the type of the database server. You can find more information about JDBC on the JavaSoft site at: http://java.sun.com/products/jdbc. This site also contains information about driver availability for the most popular database vendors.
The JViews Charts library supports the use of the JDBC interface to retrieve data values from database servers. This support is provided by the IlvJDBCDataSource class, which extracts data sets from the result of a database query.
You can specify the information related to the database request as follows:
*Provide directly the result of the query in the form of a JDBC ResultSet, either in the constructor of the data source, or with the setResultSet method.
*Provide the connection parameters as well as the SQL query statement. This can be done either in the constructor of the data source, or with the corresponding getter and setter methods. If you use this methodology, you must call the executeQuery method to produce the resulting ResultSet.
You can control how data sets are extracted from the ResultSet by means of two parameters:
*The index of the column that holds the x-series.
If this index is set to -1, the category data sets will be created.
*The index of the column that holds the data labels.
If this index is set to -1, no data label is defined.
By default, the IlvJDBCDataSource class creates data sets that store the result of the query into memory without any binding to the database. In other words, this means that the data accessible from these data sets is not bound to the data stored in the database. For example, modifying the value of a data point with the IlvDataSet.setData method does not send an update statement to the database.
Since JViews 6.5, in addition to this read-only mode, the IlvJDBCDataSource also support a read-write mode in which any changes on the data model are committed to the data base. This read-write mode must be enabled at construction time by means of the following constructors:
IlvJDBCDataSource(boolean readOnly)
and
IlvJDBCDataSource(String databaseURL,
String user,
String passwd,
String driverName,
String query,
int xColumnIndex,
int dataLabelsColumnIndex,
boolean readOnly)
Example: Importing the content of a CSV (Comma Separated Value) file through the CSV JDBC Driver
The complete source code of the example can be found in <installdir>/jviews-charts/samples/jdbc/src/jdbc/JDBCDemo.java.
/**
* This method initializes and configures the connection and calls <code>executeQuery()</code>.
*/
protected void connect() {
if (jdbcDs == null) {
// The data source is initialized. The connection string
// is set to "jdbc:relique:csv:data", where 'data' is the directory
// which contains csv files. The user and password are left blank,
// the driver to use is the CSV-JDBC driver ("org.relique.jdbc.csv.CsvDriver"),
// the query is to be initialized later, and there are no x series
// or data labels to read (-1 = no x series column).
jdbcDs = new IlvJDBCDataSource("jdbc:relique:csv:data", "", "", "org.relique.jdbc.csv.CsvDriver", null, -1, 3);
// We specified the separator used in the csv files (the default separator for the driver is ','
Properties props = new Properties();
props.put("separator", ";");
jdbcDs.addProperties(props);
}
executeQuery();
}
/**
* Executes the queries.
*/
protected void executeQuery() {
if (jdbcDs != null) {
// First load the csvdemo1 data file.
String query = "select * from csvdemo1";
// Set the query.
jdbcDs.setQuery(query);
// Execute the query and initialize the
// data source data sets.
try {
jdbcDs.endConnection();
jdbcDs.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
System.err.println("A database access error occurs");
return;
}
// Initialize the data sets of the area renderer (for the radar chart).
renderer.getDataSource().setDataSets(jdbcDs.getDataSets());
renderer.setStyles(palettes);
renderer.getChart().getXScale().setCategory(jdbcDs.getDataSet(0), false);
// Load the csvdemo2 data file.
query = "select * from csvdemo2";
// Set the query.
jdbcDs.setQuery(query);
// Execute the query and initialize the
// data source data sets.
try {
jdbcDs.endConnection();
jdbcDs.executeQuery();
} catch (SQLException e) {
System.err.println("A database access error occurs");
return;
}
// The first column (that is, the first data set) is rendered through
// stockRenderer.
stockRenderer.getDataSource().setDataSets(new IlvDataSet[] { jdbcDs.getDataSet(0) });
// The second and third columns (data sets of index 1 and 2) are
// rendered through ioRenderer.
ioRenderer.getDataSource().setDataSets(new IlvDataSet[] { jdbcDs.getDataSet(1), jdbcDs.getDataSet(2) });
stockRenderer.getChart().getXScale().setCategory(jdbcDs.getDataSet(0), true);
}
}
Connecting to a Swing TableModel
The Swing TableModel interface defines a tabular data model that can be represented with a javax.swing.JTable in the GUI of your application. The IlvSwingTableDataSource class allows you to create a data source from an existing TableModel.
1. The IlvSwingTableDataSource acts as an adapter between both data models, which means that the original data accessible from the table model is not copied.
2. Both data models are bound, which means that modifications done through a data set are forwarded to the table model. Likewise, modifying the table model fires a change event for the corresponding data set.
There are several ways to indicate how data sets should be extracted from the table model:
*By specifying the series type ( ROW_SERIES, COLUMN_SERIES ), which indicates whether data sets are extracted in rows or columns.
*By specifying optional rows or columns that hold the x-series and the data point labels.
*By providing data converters to map objects stored in the table into double values. This feature is only used when series are extracted by column as it is based on the information provided by the TableModel.getColumnClass method. To register a data converter for a given Object class, use the setDefaultConverter static method. By default, converters exist for Date and Double.
Example: Connecting to a TableModel
The complete source code of the example can be found in <installdir>/jviews-charts/codefragments/chart/swingtable/src/TableModelConnection.java.
 
// Create the chart.
IlvChart chart = createChart();
 
// Create the swing TableModel containing the data.
AbstractTableModel swingModel = null;
try {
    swingModel = createSwingTableModel();
} catch (ParseException e) {
    swingModel = new DefaultTableModel();
}
// Bind an IlvSwingTableDataSource to this swing table model. The series
// being arranged by column, the data source is of type COLUMN_SERIES.
// Since a specific column is used for the abscissa (the Year column) for
// all the series, the index in the table model of the year column
// is also specified (0).
IlvSwingTableDataSource tableDs =
    new IlvSwingTableDataSource(swingModel,
                                        IlvSwingTableDataSource.COLUMN_SERIES,
                                0,
// the column index for the x-values
                                -1);
// no datalabels
// At this time, the data sets corresponding to the table model series
// have been created.
 
// Connect the data source to a polyline chart renderer.
// The IlvPolylineChartRenderer will create a renderer for each data set
// of its data source and hold them in an internal list. These sub-
// renderers are called child renderers and can be parsed using an
// Iterator (see below).
IlvPolylineChartRenderer r = new IlvPolylineChartRenderer();
        r.setDataSource(tableDs);
        chart.addRenderer(r);
Converting Data
To be properly merged into a chart data model, data imported from a database or a table model needs to be mapped into double values. This conversion is handled by means of data converters, instances of the IlvDataConverter interface.
A data converter handles the conversion between a particular Object class and its double representation, by means of the following methods:
 
public Object toObject(double value)
public double toValue(Object object)
For example, a data converter implementation that handles conversions between a String object and a double representation would be:
 
public Object toObject(double value)
{
    return Double.toString(value);
}
public double toValue(Object object)
{
    if (!(object instanceof String))
        throw new IllegalArgumentException("IlvStringConverter: object not a java.lang.String instance.");
    try {
        return Double.parseDouble((String)object);
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("IlvStringConverter: Cannot parse object.");
    }
}
The IlvJDBCDataSource and IlvSwingTableDataSource classes handle a set of data converters common to all instances of these classes. These common converters are called default converters, and are registered using the setDefaultConverter and setDefaultConverter static methods.
By default, the IlvJDBCDataSource and IlvSwingTableDataSource classes register converters for Date, String, Short, Integer, Long, Float and Double objects.
NOTE The IlvJDBCDataSource also registers default converters for Time and Timestamp SQL data types.
The data converters are retrieved using the getDataConverter and getDataConverter methods. The default implementation of these methods returns the default converter for the object type of the specified column. If none exists, it returns the first default converter able to convert it:
*For the IlvSwingTableDataSource, it returns the default converter associated with the column class (see TableModel.getColumnClass ).
*For the IlvJDBCDataSource, it returns the default converter associated with the Java-equivalent type of the database column type as defined by the JDBC specification.
You can override this method to change the default implementation, for example if you need to define a per-instance registering mechanism.
The JViews Charts package provides three default implementations of the IlvDataConverter interface:
*string converter ( IlvStringConverter),
*date converter ( IlvDateConverter),
*number converter ( IlvNumberConverter).

Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.