### Hierarchical data source API

As a database application, JReport Designer cannot only access data stored in a database through the JDBC connection and user data source (UDS), but also supports the importing of data from hierarchical data sources (HDS).

The HDS API is a part of the JReport Data Access Model as shown in the following diagram:

The hierarchical data source API:

- Is a Java interface that provides a dataset to JReport.
- Has a PARAMETER string, which can be changed when the HDS object is added into JReport Designer. The result set may differ according to the PARAMETER string. It is very flexible and convenient.

Notes:

- The PARAMETER here is the parameter string given to the HDS interface. That is, the HDS API provides a method getResultSet (String strParam), and PARAMETER is string strParam in the above method. After reading the subsequent information on HDS API, this information will become clearer to you. As a note, we would like to remind you that PARAMETER here is different from that in a JReport catalog. To distinguish between them, we have used an upper case PARAMETER to refer to the parameter string in the HDS, and a lower case parameter for a parameter object in a catalog.
- To design a report, JReport requires meta data (See java.sql.ResultSetMetaData) which corresponds with the ResultSet that the data source has returned. To view or run a report, JReport requires a ResultSet object. The hierarchical data source must provide both of these two parts to JReport.

#### HDS API interfaces

The HDS API contains three interfaces as listed below that you must implement.

- jet.datasource.JRHierarchicalDataSource
- jet.datasource.JRHierarchicalDataset
- jet.datasource.JRHierarchicalDatasetMetaData

Reference: JReport Javadoc jet.datasource.JRHierarchicalDataSource, jet.datasource.JRHierarchicalDataset and jet.datasource.JRHierarchicalDatasetMetaData classes in `<install_root>\help\api`.

##### jet.datasource.JRHierarchicalDataSource

Provides data to JReport for generating reports. The JRHierarchicalDataSource class is developed by users of JReport, and can provide data from a flat file, non-relational database, or application data. The data returned by this class is in JRHierarchicalDataset object, so that users are required to create a JRHierarchicalDataset instance for JReport to use this instance to fetch data. Users can also create their own JRHierarchicalDataset class.

The following are methods provided by the interface.

public JRHierarchicalDataset getHierarchicalDataset (String param) throws JRUserDataSourceException

This method gets the data in JRHierarchicalDataset according to the parameters set.

- PARAMETER: param - A String value used to request and get different result sets. The format of the PARAMETER string is defined and also parsed by yourself.
- Returns: JRHierarchicalDataset object, which implements the interface JRHierarchicalDataset.
- Throws: JRUserDataSourceException - If a data access error occurs.

public void releaseHierarchicalDataset() throws JRUserDataSourceException

This method releases the data and related resources.

- Throws: JRUserDataSourceException - If a data access error occurs.

The class definition may be as follows:

    public class HierarchicalDataSource implements JRHierarchicalDataSource {
    	// Define data.
    	public JRHierarchicalDataset getHierarchicalDataset(String param)
    			throws JRUserDataSourceException {
    		// Method body.
    	}

    	public void releaseHierarchicalDataset() throws JRUserDataSourceException {
    		// Method body.
    	}
    }

##### jet.datasource.JRHierarchicalDataset

Provides data to JReport for generating reports. The JRHierarchicalDataset class is developed by users of JReport, and can provide data from a flat file, non-relational database, or application data.

The following are methods provided by the interface.

    public interface JRHierarchicalDataset
    {
        /**
        * Retrieves the number, types and properties of this object's leaves
        */
      public JRHierarchicalDatasetMetaData getMetaData();
        /**
        * Moves the cursor down one row from its current position in the current node.
        * return true if the new current row is valid; false if there are no more rows
        * in the current node.
        */
      public boolean next(String branchName);
        /**
        * Gets the value of the designated leaf node in the current branch node row as a boolean
        * in the Java programming language.
        */
      public boolean getBoolean(int leafIndex);
        /**
        * Gets the value of the designated leaf in the current branch node row as a byte
        * in the Java programming language.
        */
      public byte getByte(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a short
        * in the Java programming language.
        */
      public short getShort(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as an int
        * in the Java programming language.
        */
      public int getInt(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a long
        * in the Java programming language.
        */
      public long getLong(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a float
        * in the Java programming language.
        */
      public float getFloat(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a double
        * in the Java programming language.
        */
      public double getDouble(int leafIndex);
        /**
        * Gets the value of the designated leaf in the current branch node row as a
        * java.math.BigDecimal with full precision.
        */
      public java.math.BigDecimal getBigDecimal(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a
        * java.sql.Date object
        * in the Java programming language.
        */
      public java.sql.Date getDate(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a
        * java.sql.Time object
        * in the Java programming language.
        */
      public java.sql.Time getTime(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as
        * a java.sql.Timestamp object
        * in the Java programming language.
        */
      public java.sql.Timestamp getTimestamp(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as a String
        * in the Java programming language.
        */
      public String getString(int leafIndex);
        /**
        * Returns the value of the designated leaf in the current branch node row as an Array object
        * in the Java programming language.
        */
      public java.sql.Array getArray(int leafIndex);
        /**
        * Reports whether the last leaf read had a value of SQL NULL
        */
      public boolean wasNull(int leafIndex);
        /**
        * Releases this object's resource.
        */
      public void close();
    }

##### jet.datasource.JRHierarchicalDatasetMetaData

Provides meta data for JRHierarchicalDataset. The JRHierarchicalDatasetMetaData class is developed by users of JReport, and it works together with a JRHierarchicalDataset.

The following are methods provided by the interface.

    public interface JRHierarchicalDatasetMetaData
    {
        /**
        * Return root node names
        */
      public String[] getRoot() ;
        /**
        * Return the name of the parent.
        */
      public String getParentName(String name)
        /**
        * Return all leaf node names.
        */
      public String[] getLeafNames(String parentName);
        /**
        * Return the number of leaves of the specified branch node.
        */
      public int getLeafCount(String parentName);
        /**
        * Return all branch names for the specified parent node.
        */
      public String[] getBranchNames(String parentName);
        /**
        * Return the data type of the leaf.
        */
      public int getLeafType(String parentName, String leafName);// throws SQLException;
        /**
        * Return the name of data type.
        */
      public String getLeafTypeName(String parentName, String leafName);
        /**
        * Return the precision of the leaf.
        */
      public int getPrecision(String parentName, String leafName);
        /**
        * Return the scale of the leaf.
        */
      public int getScale(String parentName, String leafName);
        /**
        * Return the nullable state of the leaf.
        */
      public int isNullable(String parentName, String leafName);
        /**
        * Return the currency state of the leaf.
        */
      public boolean isCurrency(String parentName, String leafName);
    }

#### Examples of using the HDS API

The HDS API is flexible and convenient to use. Before you implement it, you should make an overall consideration of the architecture. JReport provides you with several scenarios which use the JReport HDS API. You can refer to them for assistance.

- You can import an XML format hierarchical data source directly from an external data source to JReport Designer using the JReport built-in classes. See Example 2: Importing an HDS from an XML file to a catalog.
- You can also develop your own classes to implement the HDS APIs, and then import your customized hierarchical data source. See Example 1: Adding a general HDS to a catalog.