Project

General

Profile

Gap Analysis

Introduction

Gap Analysis is the process by which a project's compatibility with FWD is assessed. Not all Progress 4GL features are supported in FWD or those features may only be partially supported. Likewise, there may be portability issues that occur when the application is being moved to a new hardware and/or operating system. Engaging in gap analysis is a crucial part of the project planning process. Knowing the gaps that need to be resolved allows the effort of the project to be more accurately estimated and the optimal approach to be chosen in advance.

Most importantly, a developer engaged in gap analysis must have a comprehensive understanding of the issues on which to check. The following are good resources to gain that understanding:

It is best to make a checklist of the potential issues that need to be investigated.

Before spending any significant time analyzing the reports, it is critical to ensure that all of the code and schemas that are necessary to represent the complete application are present. If there is anything missing, add it to the project and rerun the reports.

From there the developer deeply inspects the application using the reports and cross referencing items in the checklist with the level of support in FWD. A list of the gaps is developed with the results.

Sometimes a given canned report is only the first step. Specific questions may be raised which can best be answered by searches, ad-hoc reports, custom reports or by other forms of analysis. The process can be tedious but if one carefully and comprehensively, a proper gap analysis will eliminate many problems and wasted time in the future.

Most of the collecting is now automated. The gap analysis generator reads the report database and writes a single document naming every 4GL feature the project uses which FWD does not yet support completely, together with what is missing from each. See "The Gap Analysis Generator" below. It does not replace the review; it replaces the gathering, so that the review can start from a complete list rather than build one. The tool was created in task #11861.

The generated gap analysis is just a starting point for your analysis. Use the Analytics (standard reports, search and custom reports) to explore the gaps further and determine exactly how each gap or flagged issue is used.

Golden Code Development, the creators and maintainers of the FWD technology, provide a wide range of services in support of Progress ABL conversions. Gap analysis is one of the services that their conversion experts can provide. Please see www.goldencode.com for more details.

Understanding Support Levels

Many of the Code Analytics built-in reports provide two Support Level columns (one for Conversion and another one for Runtime). Reports with these columns have a value displayed there to indicate the lowest support level available for the 4FL feature being reported. Use the descriptions below to help evaluate the meaning of the support levels.

During execution of the conversion front-end, there is a phase called Gap Analysis Marking. This is a set of rules that match specific 4GL language features to AST nodes and leave behind an annotation called support_level of data type Long (although only the least significant 32-bits are used). This is really just a bit field with two sections. The conversion section can be seen by the CVT_LVL_MASK which is 0x001F or 0000 0000 0001 1111 in binary. This means that bits 0 through 4 are associated with the conversion section. The runtime section can be seen by the RT_LVL_MASK which is 0x7F00 or 0111 1111 0000 0000 in binary. This means that bits 8 through 14 are associated with the runtime section.

The reason there are two sections is because it is possible for there to be conversion support for something that has a different level of runtime support and vice versa. Since these factors are independent of each other, they must be tracked separately.

If the annotation does not exist or its value is 0x0000, then the support level is unknown (LVL_UNKNOWN). Otherwise, there should be two bits turned on. One bit is in the conversion support level section and the other bit is in the runtime support level section.

The TRPL rules use constants that are bitwise OR'd together to create the support level. The following maps out the constants that are used and their meanings (the name and color can be seen in the reports).

Constant Value Name Meaning
LVL_UNKNOWN 0x0000 Unknown The support level is not known.
CVT_LVL_MASK 0x001F n/a This is used to isolate the conversion section using bitwise operations, it does not correspond with a real support level.
CVT_LVL_NONE 0x0001 None There is no support for this feature.
CVT_LVL_PARTIAL 0x0002 Partial Partial conversion support is implemented but there is at least some implementation missing.
CVT_LVL_BASIC 0x0004 Basic A basic conversion implementation is available but there are limitations which require more work before having a complete implementation. This is typically a statement of more compatibility testing being needed.
CVT_LVL_FULL_RESTR 0x0008 Full (R) Full conversion support is implemented, but there are permanent restrictions. This is typlically due to some feature that does not make sense or is not needed in Java.
CVT_LVL_FULL 0x0010 Full Full conversion support is implemented. It is expected to be fully compatible.
RT_LVL_MASK 0x7F00 n/a This is used to isolate the runtime section using bitwise operations, it does not correspond with a real support level.
RT_LVL_NONE 0x0100 None There is no support for this feature.
RT_LVL_STUB 0x0200 Stubs Runtime functionality stubbed out, but not implemented. This means that there are placeholder classes and methods in the Java code, sufficient for any converted code to compile. BUT these classes and methods have no real implementation inside, they are just there to satisfy the javac compiler.
RT_LVL_UNTESTED 0x0400 Untested A runtime implementation exists, but it needs testing. It is likely there are issues to resolve to achieve compatibility.
RT_LVL_PARTIAL 0x0800 Partial Partial runtime support is implemented but there is at least some implementation missing.
RT_LVL_BASIC 0x1000 Basic A basic runtime implementation is available but there are limitations which require more work before having a complete implementation. This is typically a statement of more compatibility testing being needed.
RT_LVL_FULL_RESTR 0x2000 Full (R) Full runtime support is implemented, but there are permanent restrictions. This is typlically due to some feature that does not make sense or is not needed in Java.
RT_LVL_FULL 0x4000 Full Full runtime support is implemented. It is expected to be fully compatible.

At this time, not all language features have gap marking rules implemented. This means that some reports cannot yet show the support levels. Many of the most important aspects of the language have been marked and their reports upgraded to show the support level columns.

By reviewing those reports, gap analysis is made much simpler because one can quickly identify which features need work.

Gap Details

A support level says how much of a feature works. It does not say what is missing, and for any level between None and Full that is the question a reader asks next.

A gap marking may therefore carry gap details alongside the level: one sentence for the conversion side, another for the runtime side, either of which may be absent. In the TRPL rules an entry which has something to say is written through rw.gap() instead of as a bare level:

funcs.put(prog.kw_example, rw.gap(rw.cvt_lvl_full | rw.rt_lvl_partial,
                                  null,
                                  "only the INPUT form is implemented"))

Both forms may appear in the same marking map. For a built-in OO class or method, where the marking comes from a Java annotation rather than from a rules map, the same text is carried by the cvtGapsDetail and rtGapsDetail elements of LegacyResourceSupport.

A detail attached to a fully supported level is dropped with a warning, since a feature with full support has nothing missing to describe.

The generator puts these details in the What is missing column of every table it writes. A row at less than full support with an empty column means nobody has yet recorded why, which is itself worth chasing.

The Gap Analysis Generator

The generator reads a project's report database and writes the whole gap analysis as one document. Its purpose is to remove the collecting step: rather than opening forty reports and transcribing the rows which are not fully supported, the reviewer starts from a document which already names every one of them, in reading order, with its usage counts and whatever is known about what is missing.

Prerequisites

  1. The analytics reports must have been generated, so that a report database exists. See Code Analytics. The database is the rptdb directory of the converted project.
  2. The reports must have been generated by a front end run which actually re-parsed the code. Gap Analysis Marking is a phase of the conversion front end, not of the report generation, and the front end may skip a file whose 4GL source has not changed since the last run. Because the marking rules belong to FWD rather than to the project, upgrading FWD or correcting a marking changes the levels without changing a single line of 4GL — so an incremental run will quietly reuse the levels it stored last time. After any such change the front end has to be made to parse from scratch, which generally means discarding the conversion's intermediate output first. How that is done is specific to the project's own build. If in doubt, check that the front end log shows the Gap Analysis Marking phase running over the full file list rather than reporting an incremental conversion.
  3. Nothing else may hold the report database open. The Code Analytics web server keeps it open, which will block the generator. Stop it first, and remove any stale rptdb/rptdb.lock.db left behind.

Running It

From the converted project's directory:

java -DP2J_HOME=. -Xmx16g -cp "p2j/build/lib/*" \
     com.goldencode.p2j.report.server.GapDocumentDriver [project] [output file]

Both arguments are optional. The project name defaults to the name of the directory the conversion was run in, and the output file to <project>_gap_analysis.textile in that directory.

The generous heap matters on a large project; the report database can be far larger than memory and several phases aggregate across the whole of it.

The run reports each phase as it goes and finishes with a one line summary naming the output file, the item count and the elapsed time. On a twelve million line project with a 133 GB report database it takes on the order of fifteen seconds to a minute and a half, so it is cheap to regenerate after every marking change — which is the point of having a generator rather than a hand written document.

How It Selects the Files

A report database holds every file the conversion parsed, which is not the same as the set of files the project actually converts. The generator therefore opens the database the same way the Code Analytics web server does and establishes a report server session of its own, so that the default file filter profile applies. The profile it used is named in the document's opening paragraph, so a reader can always tell what the figures cover.

The session uses a private negative session id which the web server can never hand out, and its rows are removed when the document has been written.

What It Generates

The output is Redmine Textile, ready to paste into a wiki page. Its structure is fixed:

Section Content
Heading and preamble The project name, the date, the filter profile in effect, and a note that an item appears when either its conversion or its runtime support is less than full
Statistics Four tables — Code Summary, Database, User Interface and Gaps. The first three size the project; the fourth counts the gaps by group and by band, and is the one the rest of the document elaborates
Base Language, Database, User Interface The gaps themselves, one h2 per group, subdivided by the kind of 4GL feature. Each row gives the feature, its two support levels colored as the reports color them, its usage and file counts, and what is missing
How It Is Used Where one 4GL keyword is used on more than one kind of receiver, a subsection breaking the usage down by receiver type with an example line of 4GL for each. The table row links to it
Inventories Tables appended to a group which describe something in full rather than reporting a gap in it — currently the parameters passed to CONNECT statements, at the end of the Database group
Platform Specific Features Everything which ties the application to the platform it was written on

Within a group the items are ordered by the kind of feature and then by weakest support, so the worst gaps are read first. Items are banded as Unknown, No support, Partial support and Full, with restrictions, the weaker of the two sections deciding the band — full conversion support is worth nothing if the runtime is stubbed.

An Unknown item is not a statement about the feature. It is a place the gap marking did not reach, and it is a defect in the marking to be fixed rather than a gap to be estimated. The Gaps table counts them separately so they cannot be missed.

Platform Specific Features

This section holds what the support level cannot express. Some of its entries have no support level at all, because there is nothing partial to say about them — COM automation, ActiveX controls, window handles, .NET. Others convert and run perfectly well and are still listed, because what they cost is portability rather than support: a native library has to exist on the new host, and a Windows registry key does not exist off Windows.

It currently covers .NET classes, COM automation objects, the COM and ActiveX API surface, OCX controls, window handle use, shell commands, shared object and DLL API calls, Windows DDE usage and Windows registry usage. A section which the project does not exercise is left out entirely rather than printed empty, and a table of more than twenty five rows is wrapped in a collapse macro so that one long list does not bury the sections after it.

What It Will Not Tell You

  • Whether a gap matters. The document says a feature is partially supported and, where it is recorded, what is missing. Whether the missing part is on the path this application takes is a judgement the reviewer makes.
  • Anything about a feature with no gap marking. A language feature nobody has marked cannot appear, and its absence from the document is not evidence of support. See the note at the end of "Understanding Support Levels".
  • Why a level is what it is, beyond the recorded gap details. Where the detail is missing, the answer is in the marking rules or in the FWD source, not in the document.
  • Anything about code which is not in the project. If source or schema is missing when the reports are generated, the gaps in it are missing too. Confirm the file set before reading anything.

Review Process

The generator gathers all of the content described in this section. What follows is an inventory of everything gap analysis examines and what each item tells you — not a list of reports to open one by one. Running the generator first, and reading its output, is the efficient way to cover it. The list is here so that a reviewer knows what has been covered, can tell when something is missing, and can go to the underlying report when a row raises a question the document cannot answer.

What the Generator Examines

The generator draws on four kinds of input in the report database.

1. Feature reports which carry a support level

These produce the gap tables, which are the body of the document. A report qualifies when its categories name a 4GL feature and it computes a support level for them; the generator takes every category whose conversion or runtime level is less than full. Around seventy reports qualify, covering the following kinds of feature.

Language constructs

Feature type What it covers
statement Language statements — the top level constructs of a program
statement form A statement whose variants differ enough to be judged separately, such as the forms of RUN
statement option An option of a statement, judged separately from the statement itself
block type The kinds of block: DO, FOR, REPEAT, triggers, procedures, methods
block option Options on an inner block, such as TRANSACTION, BREAK, BY, WHILE, ON ERROR
error-handling construct Structured error handling: the ON phrases, UNDO with a throw action, CATCH and FINALLY
operator Language operators, including the database-evaluated ones such as CONTAINS and MATCHES
literal Literal syntax, judged separately from the data type the literal yields
data type The 4GL data types, including the large object types
function Built-in functions
function definition, function declaration User defined function definitions and forward declarations
global variable Built-in global variables
compiler constant Preprocessor and compiler constants

Handle, widget and I/O features

Feature type What it covers
attribute Handle and widget attributes. This is the largest single family
method Handle based methods
event 4GL UI events, both named events and keyboard events
widget option, frame option, browse option Options on a widget, a frame or a browse
query option Static query options — OPEN QUERY, DEFINE QUERY and the QUERY-TUNING sub-options
record phrase option Options of a record phrase
table parameter option Options on a table or dataset parameter, such as BY-REFERENCE and BIND
temp-table option, temp-table field option Options of a temp-table definition and of its fields
I/O option Options on the stream statements
shared menu Shared menu definitions and references

Database features

Feature type What it covers
metadata table, metadata field The schema metaschema — the _file, _field, _index, _sequence family and their fields. These describe what a FWD deployment can and cannot report about itself
database trigger Database trigger types, judged per type, since the four do not behave identically

Object oriented features

Feature type What it covers
class Built-in 4GL classes, marked from the LegacyResourceSupport annotation on the implementing FWD class
OO method Built-in 4GL method calls, resolved to the class which declares the method rather than the class the call evaluates to
OO class features Class definition options such as SERIALIZABLE
enum Enumeration references
generic type parameter Generic type usage

2. Feature reports which carry no support level

These produce the Platform Specific Features section. Their presence alone is the gap, so there is no level to compute:

Feature type What it covers
NET class NET class references
automation object COM, ActiveX and OLE automation objects created by the application
COM/OCX member The COM and ActiveX API surface. Summarized rather than listed — a project driving Excel reaches hundreds of members and no decision follows from reading the names
OCX control The ActiveX controls the application loads, by the descriptor each is loaded under
window handle use Places where a window handle crosses into a native API
external API, external library Shared object and DLL entry points, and the libraries they come from

3. Reports consumed by name

Some reports describe something the reviewer needs in full even though their categories are application data rather than 4GL features, so they carry no feature type and are named to the generator explicitly:

Report Why it is gathered
Shell Commands The external programs the application launches. Each has to exist on the new host
Shared Object/DLL API Calls Listed by name, which orders them by library, so the section reads as the set of native libraries the application is built on
Windows DDE Usage A Windows-only conversation between running applications, with no counterpart in a converted application
Windows Registry Usage Reported under the BASE-KEY each LOAD names, because that is what decides whether the use is portable: an INI file environment is read the same way anywhere, a registry one exists only on Windows
CONNECT Parameter Details The parameters the application passes to CONNECT, which decide whether its connections can be expressed against a FWD database

4. Reports used to measure the project

These produce the statistics, which are what the gaps are read against — a hundred partially supported features mean one thing in a twenty thousand line application and something else in a twelve million line one:

Measure Source
Source files by kind and in total The parsed file set, counted by path
Lines of code, and the split between lines written in the program and lines arriving from include files Lines of Code Analysis By File
Average program length Derived from the two figures above
Include files referenced, and how widely Include File Usage (By Included Filename)
Windows, frames, dialogs, static and dynamic widgets Windows, Frames, Dialogs, Static Widget Usage, Dynamic Widget Usage
Databases Tables by Database
Permanent tables, temp-tables and work-tables, fields, indexes, sequences Non-Temp Tables by Name, Temp-Tables/Work-Tables by Name, Fields by Table, Indexes by Name, Sequences

Two Things the Generator Does That Are Easy to Miss

It merges duplicates. The same feature is named differently by different reports — KW_CAN_FIND in one and can-find() in another are one gap. Names cannot be compared reliably, so the generator compares the set of occurrences: two reports which matched the same file, line and column every time saw the same thing. Where two candidates have the same set, the more specific report wins, because it is the one which knows the context. A narrower set is a different, narrower gap and stays its own item.

It breaks down attributes and methods by receiver. One 4GL keyword can be used on several kinds of thing, and a single support level describes all of them at once. Where that happens the generator reads the parser dump of each occurrence, groups them by the kind of receiver, and quotes a line of the original 4GL for each — so the reader can see whether the project's use is the one the gap applies to.

What the Reviewer Still Has To Do

The generator collects; it does not judge. The following remain the reviewer's work.

  1. Confirm the file set is complete before reading anything. Missing source or schema means missing gaps, and the document cannot know what it was not given.
  2. Review every Unknown item. Each is a hole in the gap marking rather than a gap in FWD, and each should be resolved and the marking corrected before the document is relied on.
  3. Chase every row with an empty "What is missing" column. A level between None and Full with nothing recorded means the reason has not been written down.
  4. Decide whether each gap matters to this application. This is the substance of the review. The usage counts, the file counts and the receiver breakdown are there to support that judgement.
  5. Cross-reference against the FWD Conversion Reference, which remains the definitive statement of what can and cannot be converted.
  6. Follow up specific questions with searches, ad-hoc reports or custom reports. A generated document answers "what and how much"; it does not answer "why here". The report database holds the original 4GL source line behind every match, which makes most such questions a short query rather than a search of the source tree.

What the Generator Does Not Cover

Everything the generator reads is listed above, and that includes the reports a reviewer would previously have opened one at a time — Language Statement Usage, Attribute Usage, Handle-Based Method Usage, Builtin Function Usage, Builtin Global Variable Usage, Database Field Usage (By Data Type), Schema Metadata Field Usage (By Name), Inner Block Options, RUN Statement Options, Widget Options, Dynamic Widget Options, Browse Options, Frame Options and Dynamic Frame Options. There is no need to walk those by hand any more.

Two things are still missing, and they are different in kind.

Features with no gap marking at all

These cannot appear in the generated document, and their absence from it is not evidence of support.

Report Why it is a blind spot
Format Strings No report which names a format string carries a support level, so format string compatibility is invisible to gap analysis. Formats differ between the 4GL and FWD in ways that matter to a character mode application
Color Phrases and Explicit Color Keyword Options Likewise. Colour handling differs between drivers, and nothing in the gap tables will say so

Read both directly, for any application with a user interface. The same caution applies to any other 4GL feature for which no marking rules have yet been written — see the note at the end of "Understanding Support Levels".

Reports which answer "where" rather than "what"

The generator names a feature, counts its uses and says what is missing. It does not say which files to look in. When a row raises that question, the report behind it usually has a "by File" or per-occurrence companion. The most useful are:

Subject Reports
Platform and operating system coupling File System and Environment Access; Hard Coded Filenames; Non-Program Hard Coded Filenames; Operating System Name References; Terminal Type References
Native libraries Shared Object/DLL List; Shared Object/DLL API List; Shared Object/DLL Calling Conventions; Shared Object/DLL PERSISTENT Definitions; Shared Object/DLL API Calls by File; High Level Call (HLC) Usage
COM and ActiveX COM/OCX API Usage by Control; COM/OCX API Usage by File; COM/OCX Accesses With Unresolved Control Origin; OCX Control Frame Creation; OCX Usage by File; .wrx File References
Streams and I/O Stream Handle Usage; Named Stream Definitions; New Shared Stream Definitions; Imported Shared Stream Definitions; Special Stream Usage; PUT CONTROL; PUT UNFORMATTED
Large objects COPY-LOB Statement Usage

These are context, not coverage. The feature in each case is already judged in the gap tables — COPY-LOB appears there as a statement, the shared library entry points as external APIs, the COM surface as a summary. What these reports add is the location and the form of each use, which is what an estimate needs once the gap itself is understood.

A note on the user interface reports. The user interface can be ignored only if the application has no UI usage at all, and it cannot be ignored if redirected terminal is used. Check regardless — the result is either a set of gaps to plan for, or the discovery of dead code which can be removed before conversion.


© 2004-2026 Golden Code Development Corporation. ALL RIGHTS RESERVED.