How to Write a Data Source Provider Class

Our goal in this tutorial is to show how to write a custom DSP (Data Source Provider) class.

The role of DSP class is to provide data for both design-time and run-time of reports and documents.
A DSP class inherits one of three possible base DSP classes:

  • DocDataSourceProviderSrsReporting
  • DocDataSourceProviderBasicReporting
  • DocDataSourceProviderMailMerge

depending on which sub-framework of Docentric AX is used: SSRS reports, Basic reports or Mail Merge (Docentric Template Libraries, i.e. Word documents).

When the base DSP class is used and when a custom DSP class is needed

1. SSRS reports

If you improve only a SSRS report design then the default base DSP (Data Source Provider) for Docentric SSRS reports (DocDataSourceProviderSrsReporting) is used.

A custom DSP class should be used with SSRS reports when you want to:

  • Add some additional data to an existing SSRS report without modifying the report artifacts.
  • Define and fetch all needed data for a new custom SSRS report developed from scratch for which you don't want to spend time on creating temporary tables and also you want to have an ability to arbitrary shape your data.
  • Define and manage custom placeholders used in print destinations.

2. Basic reports

The base DSP class for Docentric Basic Reports (DocDataSourceProviderBasicReporting) is an abstract class with the abstract generateXmlDataSource() method which means that this method has to be implemented for each Basic report. This also means that for Basic reports we have no other choice but to create and use custom DSP classes.

3. Word documents

If you use queries to describe Word document data sources (this is the only possibility in the standard Document Management framework) then the default base DSP (Data Source Provider) for query based Docentric Word documents (DocDataSourceProviderMailMergeQuery) is used. This class executes the data source query of a document and generates document data source.

On the other hand, if you want to gain more control in fetching and shaping your data, a custom DSP class is needed that inherits from the DocDataSourceProviderMailMerge class, a base class for Docentric Word documents. This is a recommended approach to take.

How do we use a custom DSP class

But we don’t have to worry about extending the proper base DSP class and implementing the particular methods. There is a wizard that generates a new Data Source Provider class for our Word document, Basic report or even SSRS report, in case we want to extend its data source.

1. The generateXmlDataSource() method

The only thing we really have to do is to implement one single method – generateXmlDataSource(). This method actually provides the data needed for a report or a document by collecting, calculating and (re)shaping the data as required.

2. The addDataFieldsForRdpTableRecord() method

Additionally for SSRS reports you will most likely be using the addDataFieldsForRdpTableRecord() method in order to add additional data or exclude particular data from the currently adding record of an RDP (report data provider) temporary table, or to change names and labels of particular fields or adding record itself. Learn here on how to use the addDataFieldsForRdpTableRecord() method for Docentric SSRS reports.

When is a DSP class invoked

Docentric AX Framework invokes the implementation of the generateXmlDataSource() and addDataFieldsForRdpTableRecord() methods of a DSP class (base or custom) and produces the main section of the Data Source Package (DDSP file) for a document or a report when:

  • DDSP file is generated and saved to a physical file and afterwards used in the template design,
  • a Word document is generated from the template or a SSRS or Basic report is executed.

Each DDSP file contains also two standard Data Sections automatically added by Docentric AX Framework:

  • General Data Section containing data related to the current company, worker, etc.
  • Parameter Data Section containing report parameters (applicable to reports only).

You can read more about Data Source Package structure here >> .

What we get if we use custom DSP classes

If we use custom DSP classes for customizing and developing SSRS reports and Word documents we get:

1. Greater flexibility

You do not have to deal only with tabular data (tables and fields) in a report or a document data source as we used to in AX world. With the use of Docentric AX APIs for building data sources, you can arbitrary shape and nest your data. And the good news is that Docentric AX Designer fantastically manages n-level nested lists/tables/collections.

2. Much faster development

Simply traverse through the needed data in X++ and shape/nest/calculate them as you like by using Docentric AX APIs described in this tutorial.

3. No need for modifying the built-in SSRS report artifacts

If you need to add some additional data fields or records to an existing SSRS report or to exclude unnecessary data, you don't have to customize the report built-in artifacts (temporary table, data provider, etc.). You can use custom Docentric DSP classes for SSRS reports instead.

Using Record Builder APIs

1. Adding Data Records and Fields to the Record Builder’s Internal Record Tree

When implementing the generateXmlDataSource() method, we use the DocXmlRecordBuilder class to build an XML report or document data source (Data Source Package) simply by traversing through the needed data and adding them to the DocXmlRecordBuilder instance (called Record Builder) as Data Records and Data Fields using various methods shown on the picture below. For example, we can add a table buffer as a Data Record, fields from a table field group or a table display method as Data Fields, etc. All added Data Records and Fields are stored in the Record Builder’s Internal Record Tree that is afterwards serialized into an XML fragment, with the following rule: Data Records are serialized as XML elements and Data Fields as XML attributes.

Data Records and Fields added to Record Builder’s Internal Record Tree can be either Table Buffer Based (we use addRecordXXX(), addField(), addFieldGroupXXX(), addDisplayMethod(), etc. methods) or Calculated (we use addCalculatedFieldXXX() and addCalculatedRecord() methods). Calculated Data Records and Fields enable us to reshape the data structure and to add calculated values.

1.1 Examples in code

Take a look at the following code fragment from the generateXmlDataSource() method:

The resulting XML is:

2. The main rule regarding Internal Record Tree structure

If the name of an adding Data Record is the same as the name of recordBuilder.currentRecord(), the Data Record is added on the same level as recordBuilder.currentRecord(), i.e. as its next sibling; otherwise, the Data Record is automatically added as a child of the recordBuilder.currentRecord().

For example:

The resulting XML is:

In the first pass of the while loop in the code above, when we were adding the first PurchRFQTable record to the Record Builder’s Internal Record Tree, the current record name was ‘PurchRFQCaseTable’ and hence the record has been added as a child record. In the second pass of the loop, when we were adding the second PurchRFQTable record, the current record name was ‘PurchRFQTable’. Therefore, the second PurchRFQTable record has been added as a sibling record to the first PurchRFQTable record. In the end, Internal Record Tree serialization resulted in the above XML fragment.

3. Navigating through internal record builder’s record tree

When we add a Data Record to Internal Record Tree, the current record pointer of the Record Builder recordBuilder.currentRecord() is moved to the newly added record. We can use goToXXX() navigation methods to change the current record pointer position.

Take a look at the previous example. If we invoke the recordBuilder.goToParentRecord() navigation method directly after adding of the PurchRFQCaseTable record:

The resulting XML will be:

4. DocXmlRecord and DocXmlField classes

Result of the addRecordXXX() and addFieldXXX() methods is an instance of the DocXmlRecord or DocXmlField class, representing a Data Record or a Data Field added to Internal Record Tree of the Record Builder. After a addXXX() method is executed and a DocXmlRecord or DocXmlField instance is created, we can invoke some of the following methods: setRecordName(), setRecordLabelId() or setFieldName(), setFieldLabelId(), etc. These methods allow us to modify the names and labels of the corresponding XML elements and attributes in the resulting XML, after the serialization of Internal Record Tree takes place.

5. Execution context

5.1 Report parameters

A report parameter value can be retrieved through the method:
This applies only to SSRS or Basic DSP classes.

5.2 Report execution context

Use methods this.getReportExecutionContextXXX() to access the report execution context table in a case of SSRS or Basic DSP classes.

5.3 Primary Table execution context

Use the methods this.getPrimaryTableXXX() to access a Primary table in case of Mail Merge (Word Documents) DSP classes.

6. Labels

All addRecordXXX() and addFieldXXX() methods automatically add the corresponding system labels, but at the same time allowing us to override them. These labels can be used later during template design. Also if we need to introduce some custom labels for a report or a document, this can be done through the report or document setup. On how to use labels and make multilingual documents and reports you can learn here >>.

7. Dumping Data Source XML

Use the following methods to dump the resulting XML of document or report data source:

Using Data Records and Data Fields APIs

Alternatively, you can use the DocXmlRecord and DocXmlField classes alongside/instead of Record Builder to gain more control over building data source record tree.

For example, you can retrieve the current record from Record Builder and change the record name and label:

In the method addDataFieldsForRdpTableRecord(DocXmlRecord _addingRecord, Common _rdpTableRecord, TableName _rdpTableName) you will deal with DocXmlRecord and DocXmlField objects directly instead of using Record Builder, but APIs are practically the same. Learn more here >>


Data source provider class Data source (DDSP file) TemplatingFeaturesOverview Template Subdocument

NOTE: This example can be used only with Docentric Template Library, for the Primary table PurchTable. Please see Document Template Libraries Examples for more details.

See also

Download examples >>
Docentric Data Source Packages (DDSP files) Overview >>
How to Extend Standard Data Sections of Data Source Package >>
How to Add Additional Data to a Docentric SSRS Report >>
How to Develop a New SSRS Report >>
How to Create a Word Document with DSP Class >>