Project

General

Profile

DMO Index

The DMO index provides a list of all tables (permanent and temporary) which will be registered with Hibernate at server startup. Also, it is used as a persistent container to save additional info which can not be specified in the associated .hbm.xml file of a certain DMO file or other 4GL features which can not be determined from the table metadata or from the DMO configuration file. The DMO index is stored in an XML file named dmo/dmo_index.xml. It is stored in the root package of the converted Java code.

While the 4GL code is still maintained, this file should not be edited by hand, as the file gets generated on each conversion (assuming that the schema generation step is included). Instead, there are two different ways to add a new table: either edit the main database schema file and add the new table definition directly in 4GL style or the new DMO can be written directly in Java. When writing it directly in Java, DMO registration and other DMO-related information must be added to a special merge file. More details about this special merge file and about how the schema changes can be handled while the 4GL code is still maintained can be found in the Managing Data Model Object (DMO) Changes section of the Integrating Hand-Written Java chapter of the FWD Developer Guide book.

This file contains the DMO list, grouped per each schema. For permanent tables, the schema name is the same as the name of the .df file which holds the 4GL schema. The list of temporary tables is always kept under the _temp schema, which is a reserved name in FWD. The following table explains the structure of the DMO index file. Later, each element will be described in more detail.

Element name Description Attributes
dmo-index The root element. package - this package name followed by the schema name will determine the package where DMO source files are generated.
schema+ An element of this type will be emitted for each permanent schema. An element with the _temp name will emitted if there are any temporary tables. impl - the package name (relative to the package specified at the dmo-index element) where the DMO implementation class and .hbm.xml file are generated.
name - the schema name
class+ This element is used to register in the DMO index file the DMO interface associated with each converted table. On FWD server startup, all the DMOs registered here will be registered with Hibernate. interface - the DMO interface name
case-sensitive* Used to store all the character and case-sensitive DMO properties. name - the DMO property name
encoded* Used to store all the character and base64-encoded DMO properties. name - the DMO property name
foreign* Used to store the foreign interface - the foreign DMO interface name
  property+ The DMO property names which appear in the foreign relation. name - the foreign DMO property name
unique* Store data about each unique constraint. N/A
  component+ The DMO property names which appear in the unique constraint. name - the DMO property name
index* Used for temporary tables only. Store information about the index DDL. name - the index name
unique - when true, it marks an unique index
  column+ Store data about each indexed column. ignore-case – when false, it marks a case-sensitive column
name - the table column name

Table 1. The structure of the DMO index file.

The root element of the DMO index file is named dmo-index and has as a single attribute the root package name of all DMOs, which is built from the root package name of the converted Java code followed by the dmo package name. So, if the root package name is com.foo.bar, this will result in the following header of the dmo_index.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--Data Model Object classes managed with Hibernate--><!DOCTYPE dmo-index SYSTEM "dmo-index-1.0.dtd">

<dmo-index package="com.foo.bar.dmo">

The root element will have as children schema elements with the DMO list belonging to that schema. The first schema elements will always be for the permanent tables, while the schema element for the temporary tables will be emitted last.

As there are differences on what data the DMO index file stores for the permanent and temporary schema, each element will be treated in two sections - for permanent tables and for temporary tables.

DMO Index for Permanent Tables

Each permanent schema is stored in a separate .df file. When converting the schema from i.e simple.df file, this will result in a schema element which will have as attributes the schema name (which is simple) and the package where the DMO implementation classes reside, built from the schema name and the impl suffix (resulting in the simple.impl package name). This package name is relative to the root DMO package name specified at the dmo-index root node. Following is the resulted element in the DMO index file:

<schema impl="simple.impl" name="simple">

This element has as children a list of class elements where each element has as single attribute, the name of the DMO interface associated with a converted table. If the table name is book and it belongs to the simple schema, this will result in the following class element under the simple schema element:

<class interface="Book">

This means an interface named Book exists in the package built from the root package name defined at the dmo-index element and the schema name, resulting in the com.foo.bar.dmo.simple package name. Also, the DMO implementation class (named BookImpl) and the .hbm.xml file (named BookImpl.hbm.xml) will reside under the package built from the root package name defined at the dmo-index element and the package name defined at the schema element, resulting in the com.foo.bar.dmo.simple.impl package name.

For each DMO, the middle conversion process will gather data from the .df schema file, the schema hints or by analyzing the 4GL code. The .df schema file provides data about case sensitive columns and unique indexes; the schema hints file is used to identify base64-encoded character columns and the 4GL code will be used to determine the foreign side of a primary-foreign key relation in a natural join.

Case Sensitive Columns

In 4GL, by default all character columns are case insensitive. If a certain column needs to be marked as case sensitive, this is done by specifying the CASE-SENSITIVE attribute at the column definition within the 4GL schema file. This will result in adding a case-sensitive child element under the class element generated for this table's DMO. For more information about what changes the case (in)sensitive column imply in the converted code, please see the CASE-SENSITIVE entry of the table in the Database Schema Elements chapter of Part 3 - Schema conversion of this book.

Unique Indexes

Some of the index data must be stored in the DMO index file, as some index behavior can only be implemented inside the FWD runtime (for example, how unique constraints cause flushing of newly created records). Thus, the conversion process gathers data about all unique constraints and saves them as unique child elements under the class element.

The following example shows how the unique indexes defined for the book table are saved in the DMO index file:

ADD TABLE "Book" 
  AREA "Schema Area" 
  DESCRIPTION "Test table with variety of indexes" 
  DUMP-NAME "book" 
...
ADD INDEX "book-id" ON "Book" 
  AREA "Schema Area" 
  UNIQUE
  PRIMARY
  INDEX-FIELD "book-id" ASCENDING

ADD INDEX "isbn" ON "Book" 
  AREA "Schema Area" 
  UNIQUE
  INDEX-FIELD "isbn" ASCENDING

If the .df schema file has the above two indexes defined for the book table, this will result in the following elements added to the Book class element.

<class interface="Book">
   <unique>
     <component name="isbn"/>
   </unique>
   <unique>
     <component name="bookId"/>
   </unique>
</class>

The order of the unique elements under the class element it's not important. For each unique index, its columns are specified using component elements; each component element will have as an mandatory attribute the DMO property name which maps the table column name (i.e. the column's converted Java name). Note that in this case, the order of the component elements is important and they will always be emitted in the same order as the table columns appear in the index definition.

Base64 Encoded Columns

Currently, P2j provides only conversion support for character columns which need to be base64-encoded for storage and decrypted upon retrieval. To mark a certain character column as encoded, the schema hints file must be modified; assuming the schema name is simple, there will be a data/namespace/simple.schema.hints file which will contain an entry similar to the following entry, to mark the comments column for table book as being base64-encoded:

<hints>
   <schema>
      ...
      <table name="book">
         <field name="comments" encoded="true"/>
      </table>
      ...
   </schema>
</hints>

For more information about the structure of the schema hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.

When the above hint exist for a certain column, the DMO index file will be added an encoded element as child of the class node; this element will have as single mandatory attribute the converted Java name of the encoded column. For the above example, the encoded element of the class node in DMO index file will look like this:

<class interface="Book">
   ...
   <encoded name="comments"/>
</class>

where comments is the column's converted Java name.

Foreign Relations

In 4GL, there is no concept of formal foreign keys between tables, and only natural joins (i.e., joins between tables identified by the 4GL construct <BUFFER-A> OF <BUFFER-B> within a record phrase) can be used. When a natural join is encountered, the 4GL runtime determines the common fields between the two tables and, from those, it chooses the fields which are part of an unique constraint in one of the tables.

In FWD, this relationship is determined at conversion time rather than at runtime. The DMO index file is used to hold metadata about the columns which are part of the foreign key relation. This data is determined at conversion time by analyzing the queries and the involved tables. Once it has determined that a natural join is involved, the FWD conversion will collect the data about the foreign table and the referenced columns and it will store them using a foreign element under the class element for the child table. If the 4GL queries are not enough to determine the foreign table of the relation (i.e. an one-to-one relation where both tables have an unique index on the common fields), file-level hints can be used to hard code the table and columns which are part of the foreign relation. For more information about how to use the hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.

As an example, lets assume that a book can have one or more authors and a certain author may write one or more books. To simulate this many-to-many relation we will use another table (named book-author) which will have a one-to-many relation to the book table and a one-to-many relation to the author table. If we want to display all the authors of this book, a construct like the following can be used:

...
for each book where book.book-title = 'FWD Conversion Reference',
         book-author of book,
         author of book-author:
   display author.
End.
...

In this example, the book table has an unique index on the book-id field and the author table has an unique index on the author-id field. The book-author table contains only the book-id and author-id fields. During conversion, FWD will identify the natural joins and will translate them into an one-to-many relation between the book-author and the book table (on the book-id field) and another one-to-many relation between the book-author table and the author table (on the author-id field). This will result on the following foreign elements emitted under the class element for the BookAuthor DMO:

<class interface="BookAuthor">
  <foreign interface="Book">
    <property name="bookId"/>
  </foreign>
  <foreign interface="Author">
    <property name="authorId"/>
  </foreign>
</class>

Each foreign element will have as children property elements, with the name of the foreign columns. With this information provided, FWD will be able to identify correctly the foreign side of the relation, when the natural joins are executed.

Indexes

For permanent tables, no indexes will be emitted into the DMO index file. On server startup, FWD will automatically collect the table indexes from the table metadata.

DMO Index for Temporary Tables

For all temporary tables defined using the DEFINE TEMP-TABLE or DEFINE WORK-TABLE statements, during conversion the DMO sources will be generated under the com.foo.bar.dmo._temp package. In the DMO index file, all DMOs will have a class element emitted under the schema element with the _temp name. For a temporary table defined as in:

def temp-table tt-book
    field book-title as char
    field comments as char
    field copies as integer.

if the tt-book will be converted to the DMO with the TempRecord1 name, the schema element in DMO index file will look like this:

<schema impl="_temp.impl" name="_temp">
  <class interface="TempRecord1" />
</schema>

Note that a schema element with the _temp name will be emitted only if there is at least a temporary table defined in the converted programs.

The data collected for the temporary tables is the same as the data collected for the permanent tables. But, as there is no .df schema file where the temporary tables are defined, all the data will be collected from the temporary table definition as it appears in the DEFINE TEMP-TABLE statement.

Case Sensitive Columns

If a certain character field is specified the case-sensitive attribute, then a case-sensitive element with the name of that field will be emitted. If the temporary table is defined as:

def temp-table tt-book
    field book-title as char case-sensitive
    field comments as char
    field copies as integer.

the following element emitted under the class node is shows how the generated DMO index file will save the case-sensitive element:

...
<case-sensitive name=”bookTitle” />
...

Unique Indexes

For the temporary tables, the unique constraint information saved in the DMO index file is determined in the same way as for the permanent tables: all unique indexes are identified and the unique constraint is saved in the unique element, under the class element for the temporary DMO. If the unique index is defined for the temporary table as in:

def temp-table tt-book
    field book-title as char case-sensitive
    field comments as char
    field copies as integer
    index idx-book is unique
       book-title asc.

this is how the generated DMO index file will save the case-sensitive element:

...
<unique>
   <component name=”bookTitle” />
</unique>
...

Base64 Encoded Columns

A temporary table's column is marked as being base64-encoded in the same way as a column belonging to a permanent table is marked: the column must be registered in a hints file, so that on conversion FWD will be aware of the special usage of this column. In this case, as temporary tables are created by the 4GL program where the DEFINE TEMP-TABLE statement exists, the file which must be modified is the schema hints file associated with this program. If the program's name is test.p, then the associated schema hints file is named test.p.schema.hints and resides in the same location as the test.p program. In our case, where we only need to mark a certain column as base64 encoded, the hits file looks similar as the one for the permanent table.

Assuming we want to mark the comments field of the tt-book table as being base64 encoded, the hints file would look like this:

<hints>
   <schema>
      ...
      <table name="tt-book">
         <field name="comments" encoded="true"/>
      </table>
      ...
   </schema>
</hints>

For more information about the structure of the schema hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.

When the above hint exist for a certain column, the DMO index file will be added an encoded element as child of the class node; this element will have as single mandatory attribute the converted Java name of the encoded column. For the above example, the encoded element of the class node in DMO index file will look like this:

...
<encoded name="comments"/>
...

where comments is the column's converted Java name.

Foreign Relations

As with the permanent tables, when a natural join between two temporary tables is involved, FWD needs to determine the foreign side of the relation. The conversion logic and the output result is the same as for permanent tables: for each child table of a foreign key relation, foreign elements will be emitted under its class element. See the Foreign Relations sections in the DMO Index for Permanent Tables for details.

Indexes

As the DDL for the temporary tables can not be kept in the Hibernate configuration files, the indexes defined for the temporary tables are collected during conversion and saved in the DMO index file. At runtime, after the temporary table is created, FWD will generate the DDL for the the indexes stored in the DMO index file and create them in the temporary database.

The information stored for each index is about the index direction, if it's an unique index or not and its columns. Also, for each column, its case-sensitive state will be stored.

If the tt-book table has the following indexes defined:

def temp-table tt-book
    field book-title as char case-sensitive
    field comments as char
    field copies as integer
    index idx-book-title is unique
       book-title asc
    index idx-copies
       copies desc
       book-title asc.

this will result in the following index elements, emitted under the class node for this table's DMO:

...
<index name="idx__tt1_idx_book_title" unique="true">
  <column ignore-case="false" name="book_title"/>
</index>
<index name="idx__tt1_idx_copies">
  <column name="copies"/>
  <column name="book_title"/>
</index>
...

The index name will always start with the idx__ prefix followed by the converted temporary table name (tt1 in this case) and the converted 4GL index name (idx_book_title). For unique indexes, the unique attribute at the index element will be set to true. Each index will have as children column elements; the order of these elements is important, as it determines the order of the indexed columns.

For each column element, the mandatory name attribute will contain the table's column name as specified in the .hbm.xml file for this table's DMO. If the column is case-sensitive, then the ignore-case attribute will be emitted and set to false.


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