GenDeveloper

Technology Tips and Insights for CA Gen Developers

QAT Publisher 2010 is almost here !

September30

As we approach the start of the beta testing for CA Gen r8 and several CA Gen conferences in October and November, we also get closer to the newest release of our QAT Publisher software.  In case you aren’t familiar, QAT Publisher is a plug-in for CA Gen that allows you to publish information to several different media types (such as PDF, HTML, RTF, Excel etc…) without the use of external action blocks.  QAT Publisher isolates the data from the presentation, so the same data (xml) can be used to produce multiple different outputs. In the current release, layouts are produced by applying stylesheets on top of xml data created by action blocks generated with QAT Publisher. Of course, this requires a stylesheet to be designed that will reproduce the desired layout.  While this is ideal for traditional reports, it can be tedious when it comes to forms that generally have more sophisticated positioning, graphical elements and/or large amounts of static text.  For example, consider IRS forms or even a simple “Authorization for Direct Deposit” form. Well, QAT Publisher 2010 has a new feature that greatly simplifies the publication of PDF Forms.  The data for PDF Forms is retrieved using the same approach as other publication types.  However, the form is designed (or even scanned) as a template and the fields are named on that form.  A new custom function was added to QAT Publisher that will generate a copy of the form with the data applied to each named field. 

This new feature will greatly simplify the development of PDF Forms with CA Gen.  Without using externals, you retrieve data using your CA Gen application and with a few calls to action blocks generated by QAT Publisher have that data transferred to a PDF form. As with the other publication types, PDF Forms will be available for C, Java and .Net.

I’ll be at the EDGEucate 2009 conference in Plano so I hope you’ll stop by and ask me for a demo !

Alex

OLE Automation versus C Api – Part 4

March8

This is the last installment of my posts about the .Net wrapper around CA Gen’s C Api. On this post I will show details on how to use the wrapper, taking as an example a real world application that I created to help us here at QAT on a client assignment.

What we wanted to identify was empty Action Blocks, i.e. Action Blocks with no statements. This was because the client had created models from subsets, and ended up with those stubs. First thing I did was to create a basic GUI to show the results. This GUI looked like that:

Plugin Window

Note that there are other tabs with different functions, but for this post I will focus on the Statements per AB tab. Also, this project was created using Visual Studio 2005 and the C# language.

At the top of the window, there are two entry fields: one for the path where the dat files for the model are, and the other for a path where potential error messages would be saved (in a file called error.log). I added a file browser control (triggered by the “…” button) to allow for easier navigation. When the path is informed and the user clicks the “Connect” button, the following code is executed:

private void btnConnect_Click(object sender, EventArgs e)

{

if (api == null)

{

api = new QATGenCAPI(EncyType.Local);

}

try

{

api.OpenModel(fldModel1Path.Text, fldErrorPath.Text);

MessageBox.Show(“Connected to Model”);

ModelInfoDTO info = api.FetchModelInfo(0);

fldModelName.Text = info.modelName;

fldModelType.Text = info.modelType.ToString();

fldModelStatus.Text = info.modelStatus.ToString();

fldModelRelease.Text = info.modelRelease.ToString();

fldUserName.Text = info.modelUserName;

fldCodePage.Text = info.modelCodePage.ToString();

fldLangCode.Text = info.modelLangCode.ToString();

}

catch (Exception exc)

{

MessageBox.Show(exc.Message);

}

}

First, I check if any api object is already defined. If not, I create a new one, passing a type of EncyType.Local. This tells the wrapper I am connecting to a local model, not a CSE or HE. After I have the api object, I need to open the target model. This is done by calling the OpenModel method of the wrapper, passing the two paths I mentioned before (model and error). Then I call the FetchModelInfo method just to retrieve some basic info about the model to display to the user. All the code is surrounded by a try/catch, in the case something goes wrong. Remember, the wrapper always throws an exception if the Gen Api fails.

After the connection to the model is established, it is time to do the real work. When the user clicks the “Execute” button inside the tab, this event runs:

private void btnListStmt_Click(object sender, EventArgs e)

{

// Here I have some code to set up the listbox. I removed that for clarity

QATGenMetaModelObjects actonCollection = null;

QATGenMetaModelObjects abCollection = api.FetchAllModelTypeObjs(0,GenObject.ACBLKBAA);

foreach (QATGenMetaModelObject ab in abCollection)

{

// retrieve the ACTON collection for that AB

actonCollection = ab.FetchCardManyAsc(GenRelationship.DEFNDBY);

if ((chkOnlyNoStatements.Checked && actonCollection.count == 0) || !chkOnlyNoStatements.Checked)

{

// create the items to add to the list

item = listViewStmt.Items.Add(ab.Name.Trim());

item.SubItems.Add(“BAA”);

item.SubItems.Add(actonCollection.count.ToString());

}

}

abCollection = api.FetchAllModelTypeObjs(0,GenObject.ACBLKBSD);

foreach (QATGenMetaModelObject ab in abCollection)

{

// retrieve the ACTON collection for that AB

actonCollection = ab.FetchCardManyAsc(GenRelationship.DEFNDBY);

if ((chkOnlyNoStatements.Checked && actonCollection.count == 0) || !chkOnlyNoStatements.Checked)

{

item = listViewStmt.Items.Add(ab.Name.Trim());

item.SubItems.Add(“BSD”);

item.SubItems.Add(actonCollection.count.ToString());

}

}

listViewStmt.Sorting = SortOrder.Ascending;

listViewStmt.Sort();

}

The first thing I do is to define and initialize a QATGenMetaModelObjects object to hold my collection of statements in an Action Block. Then I fetch all Action Blocks BAA for that model. Note that I am using the enumeration that I defined for Gen Objects (GenObject.ACBLKBAA). This is much better than using a number (ACBLKBAA is in fact number 23. You can check that on your odrpta.chm file in the Gen directory). Another detail is the first parameter on the FetchAllModelTypeObjs method. This is the model id, and it will always be zero for local models. If we were dealing with CSE or HE, I would have to pass the corresponding id for the model.

Next, for each Action Block in the collection, I retrieve its collection of statements. Statements in Gen are represented by the metamodel object ACTON, and the relationship between an action block and statements is defined by the DEFNDBY relationship. I am using the FetchCardManyAsc method because we usually have many statements per Action Block. In my GUI I have a checkbox to indicate if only Action Blocks with no statements should be listed, and I am checking for that before I include the Action Block name and the number of statements in the list box. Notice the use of the count property of the actonCollection object to indicate the number of statements. This is another thing that was added to the wrapper when I introduced the collection concept.

Since Action Blocks BAA and BSD are two different objects in Gen, the next section in the code just repeats the same processing, but for BSD Action Blocks. The last two statements are used to sort the names in the listbox. I added other things to the GUI itself, like the ability to save the contents of the list as HTML, but this is unrelated to the Api.

I hope I could demonstrate with this example how easy it is to use QAT’s .Net wrapper around the C Api. In few lines of code, I was able to access information inside a Gen model, all this without having to rely on memory allocation and release, pointers and metamodel numbers. Uses for that wrapper are only limited by a developer’s imagination. We’ve used it here at QAT to do a whole range of things, from comparing identifiers between entities in different models to generating full code for Action Blocks. Reporting and cleaning of models are two other areas where the Api can sure help Gen customers. Again, all that functionality has been available for years. My contribution I believe was to make those features available in a more object-oriented way and at the same time shield the developer from having to deal with the oddities of the C language.

My next posts will focus on something that has been around for some time now: user-defined functions in Gen. Those functions can extend Gen’s native functionality and are indeed a suitable and more robust replacement for external action blocks.

« Older Entries