Using Host Integrator Connector APIs

Creating client applications that interact with host applications involves:

You can also use filter expressions to fetch records from a recordset.

Modeling your host application using the Design Tool

With the Design Tool, you create a model of the host application. The model consists of a main model file (.modelx) and several supporting files that are located in the \<VHI install directory>\models\<your model> folder. See the Design Tool Reference for detailed information on how to create models.

Connecting to a Host Integrator Server

To connect to a Host Integrator server, you must decide whether you will connect to a model or session pools. The key difference is that host application models do not connect to and log onto a host until you request the model; sessions are typically already connected to the host and are queued to a particular screen in a host application, thus have superior performance results and is generally recommended. However, your Host Integrator implementation may not use session pools.

There are four methods available to you:

 

Secure connections

You can make sure the connectors communicate with the Host Integrator servers using a secure connection by configuring the server to require a secure connection or having the client request a secure connection by calling the RequireSecureConnection method before establishing a connection.

Interacting with data in the host application

Note:  An application that interacts with VHI models should not mix model-level and table-level methods. This is because the operation definitions in these two model layers make certain assumptions about entity navigation paths and cursor positions. For example, if you issue a model-level method in a table-based model, it can break the table operations because the model subsequently can't locate the table's home entity. Unless you are very familiar with a model, you should avoid mixing procedures with direct model access.

Accessing host data

You can access host data using one of the following approaches:

Procedures

This approach is possible when you're working with host models that contain tables and procedures. This is the most efficient way to access host applications, and is also the technique that requires the least knowledge about the host application and the model created from that host application.

While using model-level methods requires some knowledge of the host application model, using procedure-level methods to access table definitions of data requires no direct knowledge of the host application or the modeling process. The person who created the host application model will have abstracted the host application data into tables that can respond to SQL queries just like an actual relational database. The table interface supports a subset of the SQL 92 standard for SELECT, UPDATE, INSERT, and DELETE statements.

There are two key methods in each of the connectors for interacting with the host application at the procedure level:

You can use either one of these methods depending on your preference and experience. If you have SQL or database experience, you might prefer to use ExecuteSQLStatement. But the two methods are largely interchangeable. The concept is the same in either case: working at the procedure level turns your host application into a virtual database.

Some of the filtering and sorting options available in SQL are not available when you access host data; regardless of the method you choose.

All of the host navigation and interpretation is already contained in the procedure definitions in the model file. To see a list of procedures and columns stored in the model file, you can generate an XML- or HTML-based model file using the Export dialog box of the Design Tool.

Your target API has documentation on the data structures you use to call ExecuteSQLStatement or PerformTableProcedure, or to manipulate the returned data.

Models

You may encounter host applications that you cannot effectively mine using procedures (although event handlers can help you with even the most unorthodox host applications.) For such applications, you can create clients that interact directly with the model's entities, attributes, operations, and recordsets.

If you choose not to interact with the host application using procedures, use model-level methods to access host data or to navigate through a host application. Working at the model layer requires knowledge of the Design Tool's modeling process, and of the specific model you are interacting with. Information on the model's entities, operations, recordsets, and attributes can be accessed directly from the model, or from the XML- or HTML-based model file created in the Design Tool's Export dialog box.

Navigating Host Applications
You can use several different model-level methods to navigate through a host application. Use the SetCurrentEntity method to navigate directly to a host application screen, or the PerformEntityOperation method to navigate through a host application by executing an operation directly.

You can also navigate by means of a recordset that supports selection, using a record in the recordset to navigate to another entity. You can set the recordset index using SetCurrentRecordIndex to set the index to an absolute value, and MoveCurrentRecordIndex to set the index by a relative movement method (for example, ScrollHome, ScrollEnd, ScrollLineUp, ScrollLineDown, ScrollPageUp, and ScrollPageDown).

You can select a record to navigate to another entity using the following methods:

At the terminal level

This approach bypasses the model—and the abstraction and optimization offered by Host Integrator—completely.

Unlike the model-level methods, using terminal methods requires an intimate knowledge of the host application since the entity definitions created in the model file are not used with terminal-level methods. Terminal-level access is the most laborious and inefficient way to access host data, and can usually be avoided with good modelling practices.

You can set host data directly using InsertStringAtOffset and InsertStringAtRowColumn, or access host functionality with PerformAidKey. You can access host data with GetStringAtOffset and GetStringAtRowColumn. You should only use terminal methods if you do not want to use the entity definitions that have been created in the model file.

Terminal methods also contain synchronization methods that wait for an event on the host application before executing. For example, WaitForCursor waits for the cursor to be in placed in a given row or column, WaitForString waits for a string to appear at the given row and column, and WaitForStringRelCursor waits for a string to appear at a screen position relative to the host application cursor.

Retrieving Terminal Attributes
Terminal attributes are host-generated properties that affect how an attribute displays in the terminal window. Terminal attributes are used to denote the importance of a field or its availability. Before you can retrieve terminal attributes from a model, you must enable them in the model. If you are unsure whether terminal attributes are enabled in your model, check with the model designer. For more information, see the Enable terminal attributes setting.

To retrieve terminal attributes from a host application model:

  1. Enable the retrieval of terminal attributes by calling the EnableTerminalAttributes method and setting the enable parameter to True.

    Important: After you enable terminal attributes, they remain enabled for the duration of the session, until you explicitly disable them. Leaving terminal attributes enabled will have an impact on performance, so after you have retrieved attributes, disable the setting until you need to retrieve attributes again.

  2. Use getAttributes or fetchRecords to obtain a ModelRecord or RecordSet object to be used by the getTerminalAttributes method.

  3. Retrieve the terminal attributes using the getTerminalAttributes method.

    For example, here is a section of Java code that demonstrates this process:

        mySession.enableTerminalAttributes(enable);
    
            JOptionPane.showMessageDialog(null, "Current Entity: " + mySession.getCurrentEntity());
            entityName = JOptionPane.showInputDialog("Goto entity: ");
    
            mySession.setCurrentEntity(entityName);
            JOptionPane.showMessageDialog(null, "Current Entity: " + mySession.getCurrentEntity());
    
            myModelRecord = mySession.getAttributes(null); //null specifies all attributes
            JOptionPane.showMessageDialog(null, myModelRecord.toString());
            System.out.println(myModelRecord.toString());
    
            attributeName = JOptionPane.showInputDialog("Attribute name: ");
            myTerminalAttributes = myModelRecord.getTerminalAttributes(attributeName);
    
            if (myTerminalAttributes.isReverse())
            {
                    JOptionPane.showMessageDialog(null, "isReverse = True");
            } else
            {
                    JOptionPane.showMessageDialog(null, "isReverse = False");
            }
    

Using Filter Expressions

Many methods let you specify filter expressions when fetching records from a recordset. The following table illustrates the format for syntax expressions:

Condition Expressions

You can use expressions on both the left and right sides of the condition statement. Be sure to enclose string data in quotation marks.

AND condition_expression AND condition_expression
OR condition_expression OR condition_expression
Not NOT condition_expression
Equal to value_expression = value_expression
Equal to (case insensitive) value_expression =* value_expression
Not equal to value_expression <> value_expression
Less than value_expression < value_expression
Greater than value_expression > value_expression
Less than or equal to value_expression <= value_expression
Greater than or equal to value_expression >= value_expression
( ) (multiple condition_expressions)

Value Expressions

A value expression can take any of the following formats:

Filter Expression Examples

This example returns all recordset fields in the patients recordset that are not "Smith":

patients.lastname <> "Smith"

Here's an example that is exactly equivalent to the first example:

NOT (patients.lastname = "Smith")

This example returns all records in the SearchResults recordset with the field "last name" equal to "Smith" and the field "first name" equal to "Steven":

(SearchResults.LastName = "Smith") and (SearchResults.FirstName = "Steven")

This last example returns all fields in the AccountNumbers recordset greater than or equal to 10000 and less than or equal to 20000:

(AccountNumbers.Accounts >= 10000) and (AccountNumbers.Accounts <= 20000)