A script-enabled browser is required for this page to function properly.

Writing Generic Code Using Metadata

Like the C API, JDAPI allows you to write completely generic code for processing multiple Forms objects of different types. All classes representing Forms objects implement the JdapiObject interface, and this type can be used as the base type. Additionally, there is an abstract type, JdapiModule, which also implements JdapiObject and from which the real module types extend (this is illustrated in the example in Loading and Saving Modules).

When getting and setting Forms object properties generically you will need to use the generic accessors, getStringProperty(), setStringProperty() and so on, since the specific property accessors are not supported by the JdapiObject interface (the exception is getName()).

There are several classes in JDAPI which deal with the Forms model metadata, these are:

The class JdapiMetaData contains a complete description of the metadata for each Forms object. For each Forms object type there is also a corresponding JdapiMetaObject which can be obtained from JdapiMetaData (or from an instance of the object) by calling getJdapiMetaObject(), and describes the set of metaproperties for the corresponding Forms object. It is possible to obtain iterators of all properties or specific types. The iterators operate on sets of JdapiMetaProperty type. For example:

JdapiIterator stringProps = metaObject.getStringMetaProperties();

For each property there is a corresponding JdapiMetaProperty which can be obtained and which describes the property. For example it can describe its data type, whether it can be set, and so on. For example:

  
...
while (stringProps.hasNext())
{
  JdapiMetaProperty prop = (JdapiMetaProperty)stringProps.next();
  if (prop.allowGet())
  {
    // this line returns the equivalent value to the JdapiTypes.<prop>_PTID constant
    int propNum = prop.getPropertyID();
    System.out.println(
	        "Property No. " + propNum + " has value " + jo.getStringProperty(propNum));
  }
} 

This is where the generic accessors together with the metadata can be very powerful since code can be written to process a whole module object by object, reusing the same processing code and without catering for each specific type of object. The alternative would be to use a large switch statement or chained if/else if... code structure and select on the specific object type.

Example

The following code sample illustrates how to use generic methods to traverse a form and get and manipulate Forms object properties.


import oracle.forms.jdapi.*;
 
 /**
   * Example to traverse a Form Module object tree in a generic way
   */
 public class TraverseFormExample
 {
    public static void main(String[] args)
    {
      FormModule fmb = FormModule.open("myform.fmb");
      traverse(fmb);
    }
 
    /**
     * Recursive method for tree-walking a Form via object ownership metadata
     *
     * This method will inspect the passed object for any possible
     * child objects and process them recursively
     *
     * @param jo Forms object representing start point of traversal
     */
    public static void traverse(JdapiObject jo)
    {
      // first do any processing on the passed object we want to
      System.out.println("Found object " + jo.getName());
 
      // use the passed object's metadata object
      // to obtain its possible child object metaproperties
      JdapiMetaObject meta = jo.getJdapiMetaObject();
      JdapiIterator childProps = meta.getChildObjectMetaProperties();
 
      // iterate round the child object properties
      while(childProps.hasNext())
      {
         JdapiMetaProperty mprop = (JdapiMetaProperty)childProps.next();
        JdapiIterator childObjects = 
 jo.getChildObjectProperty();
 mprop.getPropertyId()
        // won't enter this loop if the object iterator is empty
        if(childObjects!=null)
		{
		   while (childObjects.hasNext())
           {
             // finally, recurse
             traverse((JdapiObject)childObjects.next());
           }
		}
      }
    }
 }

Comments: For each Forms object, get the corresponding metadata object from it, retrieve a list (iterator) of child object property types and test each one to see if any of those child objects exist. In the example there is only minimal "real" processing (the System.println() statement), whereas in practice you could call any Java/JDAPI methods here. Note that nowhere in the code is there a reference of specific object types (Block, Canvas, and so on).

This is a classic generic tree-walking algorithm which can be used with JDAPI to do almost any processing task. Comparing this example with the generic traversal example in the C API white paper will illustrate the ease of use and clarity of using a Java API.