8.5. Class File Data Source

For maximum flexibility, you can retrieve and prepare the dataset in any way you want and pass it to the report engine. To pass in your class file as the data source, your class file must implement the IDataSource interface.

8.5.1. Non Parameterized

Below is a simple example that implements IDataSource and contains no parameters:

public class CustomClassData implements IDataSource {

      // Setting DbData for passing data as arguments
      String dataType[] = {"string", "String", "double"};
      String fieldName[] = {"Destination", "Time", "Price"};
      String records[][] = {{"Mayfair", "13:43", "3.50"},
            {"Bond Street", "13:37", "3.75"},
            {"RickmansWorth", "13:12", "5.25"},
            {"Picadilly", "13:24", "3.00"}};
      DbData data = new DbData(dataType, fieldName, records);

      public IResultSet getResultSet()
      {
            return data; } 

}
        

Full Source Code

The example above creates data (DbData instance) and stores it in memory. When getResultSet() method is called, it returns DbData object which implements IResultSet. Keep in mind that it is not necessary to create your data in this manner. As long as you are able to return an object that implements IResultSet, you can obtain the data from any data source.

Please note that if you are passing in your own class file as the data source, the class file must be accessible from the CLASSPATH of the EDAB Server.

8.5.2. Parameterized

You can also pass in a parameterized class file as the data source for the report. The parameter is obtained at run-time from the user and the data is then fetched and used to generate the report. Here is an example of a parameterized class file.

public class ParamClassFile implements IParameterizedDataSource
{
	String url = "jdbc:hsqldb:help/examples/DataSources/database/woodview";
	String driver = "org.hsqldb.jdbcDriver";
	String username = "sa";
	String password = "";

//	Specify what the parameter properties are.
	public IQueryInParam[] getParameters()
	{
		SimpleQueryInParam[] params = new SimpleQueryInParam[2];
//		SimpleQueryInParam(name, promptString, mapToColumn, TableName, ColumnName, dataType, defaultValue, actualValue)
		params[0] = new SimpleQueryInParam("price", "Max price:", false, null, null, Types.DOUBLE, new Double(500.00), null);
		params[1] = new MySimpleQueryInParam("popular", "Popular Items Only:", false, null, null, Types.VARCHAR, new String("NO"), null);
		return params;
	}

	private class MySimpleQueryInParam extends SimpleQueryInParam implements IQueryParamValuesProvider
	{
		public MySimpleQueryInParam(String paramName, String promptName, boolean mapToColumn, 
				String tableName, String columnName, int sqlType, Object defaultValue, Object value)  {
			super(paramName, promptName, mapToColumn, tableName, columnName, sqlType, defaultValue, value);
		}
		public Vector getSelectionChoices() {
			Vector choices = new Vector();
			choices.add(new String("Yes"));
			choices.add(new String("No"));
			return choices;
		}
	}

//	Specify what data is to be returned
	public IResultSet getResultSet(IQueryInParam[] params)
	{
		double price = 500.00;
		int units = 999;

		if ((params != null) && (params.length >= 1))
		{
			Object obj = params[0].getValue();
			if ((obj != null) && (obj instanceof Double)) price = ((Double)obj).doubleValue();
			obj = params[1].getValue();
			if((obj != null) && (obj instanceof String) && ((String)obj).equalsIgnoreCase("yes")) units = 15; 
		}

		try{
			Class.forName(driver);
			Connection conn = DriverManager.getConnection(url, username, password);
			String query = "SELECT ProductName, Description, UnitPrice, UnitsInStock FROM Products WHERE UnitPrice < " 
				+ price + " AND UnitsInStock < " + units;
			Statement stmt = conn.createStatement();

			ResultSet rs = stmt.executeQuery(query);
			QueryResultSet qry = new QueryResultSet(rs);

			return qry;

		} catch(Exception e) {
			e.printStackTrace();
		}

		return null; 
	}

}
        

Full Source Code

The parameterized class file must implement IParameterizedDataSource. The above example obtains data from woodview (HSQLDB) database and the query contains two parameters. The first parameter allows the user to set the maximum price for the query results. The parameter is of type double and the default is set to 500.00. The second parameter is a custom parameter and its purpose is to give the user a yes or no option to determine whether or not to show popular items only. To construct a custom parameter, create a class that extends the SimpleQueryInParam class, implements the IQueryParamValuesProvider interface and overwrites the getSelectionChoices() method. If the user selects yes, only items with less than 15 UnitsInStock will be returned in getResultSet().

8.5.3. Custom Selection Choices

When using parameterized class file as the data source, keep in mind that you can not map it to a column directly (i.e. set the table name and column name in the SimpleQueryInParam constructor). In order to map a parameter to a column, you will have to use a custom parameter similar to the one shown above. However, the getSelectionChoices() method will look as follows:

public Vector getSelectionChoices() {

      System.out.println("getSelectionChoices called");
      try {
            Class.forName("jdbc:hsqldb:help/examples/DataSources/database/woodview");

            String url = "org.hsqldb.jdbcDriver";
            Connection conn = DriverManager.getConnection(url, "sa", "");
            Statement stmt = conn.createStatement();
            String query = "SELECT DISTINCT " + getColumnName() + " FROM " + getTableName();
            ResultSet rs = stmt.executeQuery(query);
            Vector v = new Vector();

            while (rs.next()) {
                  switch (getSqlType()) {
                        case Types.INTEGER:
                              v.add(new Integer(rs.getInt(1)));
                              break;
                                case Types.VARCHAR:
                              v.add(rs.getString(1));
                              break; } }
            stmt.close();
            conn.close();

            return v;

            } catch (Exception ex) {
                  ex.printStackTrace(); } return null; 

}
        

Full Source Code

In addition to mapping the parameter to a column, this example also uses a multi-value parameter. Although the process is similar to using a single value parameter, there are some places where the code deviates from the norm. Please see the comments in the above source code for details.