Yes, parent/child (nested mail merge regions) is one of those highly demanded features that is available in Aspose.Words for .NET and not yet available in Aspose.Words for Java. And yes, this feature is going to be available for Java very soon, when our autoporting project is complete.
BTW, there are only 16 files remain to be made autoportable.
Today a small technical article that describes challenges and solutions we came across when making the Aspose.Words MailMerge autoportable to Java.
To run a mail merge in Aspose.Words requires a “mail merge data source”. Mail merge data sources in Aspose.Words are completely abstracted via the IMailMergeDataSource and IMailMergeDataSourceRoot interfaces. The abstraction of mail merge data sources via interfaces allows the user to feed any data on any platform into a document template during mail merge. For example, the user can implement a mail merge data source to retrieve data from an XML document or from a business object or a collection of objects.
Although implementing mail merge data sources for Aspose.Words is easy, most of the users don’t need this flexibility. Most of the users have their data in a “standard” database access library on their platform. Therefore Aspose.Words implements the “standard” mail merge data sources and allows the user to use them seamlessly. On .NET the database access technoligy is ADO.NET and Aspose.Words allows to mail merge from DataTable, DataSet and other objects (more info below). On Java the database access technology is JDBC and Aspose.Words allows to mail merge from ResultSet objects.
Obviously, ADO.NET and JDBC both are platform-specific technologies and we cannot expect to automatically port code that accesses ADO.NET objects to Java. But nevertherless, I wanted to make sure that as much code is autoportable and only the thin layer of platform-specific details is manually coded. At the same time the public API should be smooth on both platforms.
Problems and Solutions
|.NET||Java||Problem and Solution|
|DataTable has TableName||ResultSet does not have a table name||ADO.NET DataTable roughly corresponds to ResultSet in Java. The problem is that during mail merge Aspose.Words needs to know the table name. It uses the table name to match with the mail merge region in the template document. E.g. the “Orders” table will be used to populate the “Orders” mail merge region. In .NET, the table name is avaialble in DataTable.TableName, but in Java, the table name is not easily available. |
In some cases the table name in Java can be obtained from ResultSetMetadata, but not always.
In earlier version of Aspose.Words for Java I think we provided a method that accepted two parameters ResultSet and String (instead of one parameter DataTable on .NET). Such difference in signature is not good for autoporting and I decided to make it better this time.
I introduced the new public com.aspose.words.DataTable class that is basically a tuple, it just stores a ResultSet and a table name inside itself. So the user will need to pass com.aspose.words.DataTable instead of plain ResultSet on Java and thus the user will be forced to make sure he specifies the table name and this solved many autoporting issues at the same time.
|DataSet||Not available||ADO.NET DataSet can contain many tables and relationships between them. Aspose.Words accepts a DataSet object for mail merge operations that populate multiple mail merge regions in one pass. This includes the highly popular nested mail merges. |
In earlier version of Aspose.Words for Java we provided a public class ResultSetHashMap, which was actually a map of string table name into a ResultSet object. This was enough for mail merge operations with multiple mail merge regions, but was not enough for nested mail merges because nested mail merges need data relations described.
I introduced the new public com.aspose.words.DataSet class that mimics the bare minimum of the System.Data.DataSet class needed for nested mail merge to work on Java and also helps to make code autoportable. The user will need to create a com.aspose.words.DataSet object, add com.aspose.words.DataTable objects to it and also add com.aspose.words.DataRelation objects.
|DataRelation||Not available||This is related to the above. ADO.NET DataSet has a collection of DataRelation objects the describe the parent-child relationships between the tables in the dataset. The Aspose.Words “standard mail merge data source” implementation uses DataRelations to navigate from parent to child tables and to select the child rows. In other words the parent-child structure of the document template and the parent-child links in the DataSet need to match for a nested mail merge to be successful. |
There was no DataSet and no DataRelation on Java, so I created these classes as public classes in the Aspose.Words API for Java. They mimic the ADO.NET classes, but implement the bare minimum needed for Aspose.Words mail merge to work.
|DataRow.GetChildRows||Not available||During nested mail merge Aspose.Words needs to select child records for the current parent record. For example select all order items for the current order. This is easy to do in ADO.NET using the DataRow.GetChildRows(DataRelation childRelation). There is nothing like that on Java. |
At first I tried to use FilteredRowSet to apply a filter over a table that will select the child rows, but then figured that FilteredRowSet is only available on Java 1.5 or higher. This is not good since we target 1.4 too. I simply ended up implementing our own filtering inside the Java implementation of the mail merge data source.
As a result, two files are manually implemented in Java:
MailMergeDataSourceDataTable – This iterates over all records in a ResultSet (used for a root table or for non nested mail merges)
MailMergeDataSourceDataRelation – This iterates over filtered records in a ResultSet (used for child tables in a nested mail merge).
|Unit tests, |
ADO.NET Connection etc
|JDBC Connection etc||Hidden in the platform specific TestMailMergePal class, see below.|
|Unit tests, programmatic creation of disconnected DataSet, DataTable||Store tests data in CSV files. Implemented loading of CSV into System.Data.DataTable and com.aspose.words.DataTable (e.g. ResultSet) in the platform specific TestMailMergePal class, see below.|
Aspose.Words MailMerge .NET to Java public API mappings
|Execute(string fieldNames, object values)||execute(String, Object)||Ok|
|Execute(System.Data.DataTable)||execute(com.aspose.words.DataTable)||Ok. On Java, instead of System.Data.DataTable, the user needs to use com.aspose.words.DataTable that contains java.sql.ResultSet.|
|ExecuteADO(object recordset)||N/A||COM and ADO is not applicable on Java.|
|Execute(IDataReader)||N/A||ADO.NET data reader, not applicable on Java.|
|Execute(DataView)||N/A||ADO.NET data view, not applicable on Java.|
|Execute(DataRow)||N/A||ADO.NET data row, not applicable on Java.|
|ExecuteWithRegions(System.Data.DataSet)||executeWithRegions(com.aspose.words.DataSet)||Ok. On Java, the user needs to create com.aspose.words.DataSet and add com.aspose.words.DataTable and add com.aspose.words.DataRelation objects to describe the data and relationships between the tables.|
|ExecuteWithRegionsADO(object recordset)||N/A||COM ADO not applicable on Java.|
|ExecuteWithRegions(DataView)||N/A||ADO.NET data view not applicable on Java.|
|ExecuteWithRegions(IDataReader, string tableName)||N/A||ADO.NET data reader not applicable on Java.|