Skip Headers
Oracle® Application Development Framework Developer's Guide
10g Release 3 (10.1.3)
B25386-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

20.4 Implement the Data Control Definition Class

This class needs to provide all the information that the framework needs to instantiate a data control during design time and runtime. This class is responsible for performing these operations:

20.4.1 Location of JAR Files

The data control definition class needs to extend the abstract class oracle.adf.model.adapter.AbstractDefinition. This class is located in the JDEV_HOME/bc4j/lib/adfm.jar file.

20.4.2 Data Control Definition Class Outline

Example 20-9 is an outline showing the methods you have to implement when you create a data control definition class. The sample is taken from SampleDCDef, which is the data control definition class for the simple CSV data control adapter.

Example 20-9 Outline for the Data Control Definition Class

import oracle.adf.model.adapter.AbstractDefinition;
import org.w3c.dom.Node;
import oracle.binding.meta.StructureDefinition;
import oracle.binding.DataControl;
import java.util.Map;

public class SampleDCDef extends AbstractDefinition
{
   // default constructor
   public SampleDCDef ()
   {
      // you need a default constructor.
      // see Section 20.4.4, "Creating a Default Constructor".
   }

   public Node getMetadata()
   {
      // you need to implement this method.
      // see Section 20.4.5, "Collecting Metadata from the User".
   }

   public StructureDefinition getStructure()
   {
      // you need to implement this method.
      // see Section 20.4.6, "Defining the Structure of the Data Control".
   }

   public DataControl createDataControl()
   {
      // you need to implement this method.
      // see Section 20.4.7, "Creating an Instance of the Data Control".
   }

   public void loadFromMetadata(Node node, Map params)
   {
      // you need to implement this method.
      // see Section 20.4.8, "Setting the Metadata for Runtime".
   }

   public String getDCName()
   {
      // you need to implement this method.
      // see Section 20.4.9, "Setting the Name for the Data Control".
   }
}

20.4.3 Complete Source for the SampleDCDef Class

Example 20-10 shows the complete source for the SampleDCDef class:

Example 20-10 Complete Source for the SampleDCDef Class

package oracle.adfinternal.model.adapter.sample;

import java.io.InputStream;

import java.util.Map;
import oracle.binding.DataControl;
import oracle.binding.meta.StructureDefinition;

import oracle.adf.model.adapter.AbstractDefinition;

import oracle.adf.model.adapter.AdapterDCService;
import oracle.adf.model.adapter.AdapterException;
import oracle.adf.model.adapter.dataformat.AccessorDef;
import oracle.adf.model.adapter.dataformat.StructureDef;
import oracle.adf.model.adapter.utils.NodeAttributeHelper;

import oracle.adf.model.utils.SimpleStringBuffer;

import oracle.adfinternal.model.adapter.sample.CSVHandler;
import oracle.adfinternal.model.adapter.sample.SampleDataControl;
import oracle.adfinternal.model.adapter.url.SmartURL;

import oracle.xml.parser.v2.XMLDocument;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SampleDCDef extends AbstractDefinition
{
   // Name of the root accessor for a definition
   public static final String RESULT_ACC_NAME = "Result";

   // Namespace for the metadata definition.
   public static final String SAMPLEDC_NS = 
                           "http://xmlns.oracle.com/adfm/adapter/sampledc";

   // Definition tag as the root
   public static final String DEFINITION = "Definition";

   // Attribute to contain the source URL
   public static final String SOURCE_LOC = "SourceLocation";

   // Name of the data control
   private String mName = "SampleDC";

   // the structure definition
   private StructureDef mStructDef = null;

   // URL for this definition.
   private String mCSVUrl = null;

   public SampleDCDef()
   {
   }

   public SampleDCDef(String csvURL,String dcName)
   {
      mCSVUrl = csvURL;
      mName = dcName;
   }

   public Node getMetadata()
   {
      XMLDocument xDoc = new XMLDocument();
      Element metadata = xDoc.createElementNS(SAMPLEDC_NS, DEFINITION);
      metadata.setAttribute(SOURCE_LOC, mCSVUrl.toString());
      return metadata;
   }

   public StructureDefinition getStructure()
   {
      if (mStructDef == null)
      {
         // create an empty StructureDefinition
         mStructDef = new StructureDef(getName());
         SmartURL su = new SmartURL(mCSVUrl.toString());
         InputStream isData = su.openStream();
         CSVHandler csvHandler = new CSVHandler(isData, true, "UTF-8", ",", "\"");

         // Name of the accessor or the method structure to hold the attributes
         String opName = new SimpleStringBuffer(50).append(getDCName())
                                                   .append("_")
                                                   .append(RESULT_ACC_NAME)
                                                   .toString();

         StructureDef def = (StructureDef)csvHandler.getStructure(opName, null);
         // Create the accessor definition
         AccessorDef accDef =
                       new AccessorDef(RESULT_ACC_NAME, mStructDef, def, true);
         def.setParentType(StructureDef.TYPE_ACCESSOR);
         accDef.setBindPath(new SimpleStringBuffer(50)
                                        .append(mStructDef.getFullName())
                                        .append(".")
                                        .append(AdapterDCService.DC_ROOT_ACC_NAME)
                                        .toString());
         mStructDef.addAccessor(accDef);
      }
      return mStructDef;
   }

   public void loadFromMetadata(Node node, Map params)
   {
      try
      {
         // Get the information from the definition
         NodeList listChld = node.getChildNodes();
         int cnt = listChld.getLength();
         Node chld;

         for (int i = 0; i < cnt; i++)
         {
            chld = listChld.item(i);
            // System.out.println("Tag: " + chld.getNodeName());
            if (DEFINITION.equalsIgnoreCase(chld.getNodeName()))
            {
               // Load the required attributes
               NodeAttributeHelper attribs = 
               new NodeAttributeHelper(chld.getAttributes());
               mCSVUrl = attribs.getValue(SOURCE_LOC);
            }
         }
      }
      catch (AdapterException ae)
      {
         throw ae;
      }
      catch (Exception e)
      {
         throw new AdapterException(e);
      }
   }

   public DataControl createDataControl()
   {
      SampleDataControl dcDataControl = new SampleDataControl(mCSVUrl);
      return dcDataControl;
   }

   public String getDCName()
   {
      return mName;
   }

   public String getAdapterType()
   {
   return "oracle.adfm.adapter.SampleDataControl";
   }
}

20.4.4 Creating a Default Constructor

You need to create a default constructor for the data control definition class. The simple CSV adapter has an empty default constructor:

Example 20-11 SampleDCDef Default Constructor

public SampleDCDef()
{
}

The default constructor is used only during runtime. It is not used during design time.

20.4.5 Collecting Metadata from the User

Metadata in a data control adapter provides information on the data source. The data control definition class uses the metadata to create a data control. Examples of metadata for the full-featured CSV data control adapter include the URL to the CSV file, the field separator character, and the quote character. For the simple CSV adapter, the metadata consists of only the location of the CSV file.

A data control adapter can collect metadata in different ways. Examples:

  • The CSV data control adapter that comes with JDeveloper uses a wizard to collect metadata from the user.

  • The web service data control adapter also uses a wizard to collect metadata. Alternatively, users can drag a web service connection node and drop it on the Data Control Palette. The web service adapter extracts metadata from the node instead of launching the wizard.

    When the user drags and drops a node onto the Data Control Palette, the adapter framework looks for an adapter that can handle the type of node that was dropped by searching the registered data control adapters. Data control adapters declare which node types they support. The nodes are JDeveloper nodes that represent specific source types. When the framework finds an adapter that supports the type of node that was dropped, it invokes the data control adapter, which then extracts the required information from the node.

  • The simple CSV adapter extracts metadata from a node when the user right-clicks a node and selects "Create Data Control" from the context menu.

Regardless of how a data control adapter retrieves the metadata, you must implement the getMetadata method in your data control definition class. The framework calls the method to get the metadata.

This method returns the metadata in the form of a Node object. The getMetadata method has the following signature:

Example 20-12 getMetadata Signature

public org.w3c.dom.Node getMetadata();

In the simple CSV adapter, the getMetadata method retrieves the metadata from the mCSVUrl class variable and inserts the value in an Element object.

Example 20-13 getMetadata Method

public Node getMetadata()
{
   XMLDocument xDoc = new XMLDocument();
   Element metadata = xDoc.createElementNS(SAMPLEDC_NS, DEFINITION);
   metadata.setAttribute(SOURCE_LOC, mCSVUrl.toString());
   return metadata;
}

The framework extracts the information from getMetadata's return value (the Node object) and writes the information to the DataControls.dcx file. For example, after the user has created a CSV data control, the file looks like the following:

Example 20-14 DataControls.dcx File

<?xml version="1.0" encoding="UTF-8" ?>
<DataControlConfigs xmlns="http://xmlns.oracle.com/adfm/configuration"
                  version="10.1.3.36.45" Package="view" id="DataControls">

   <AdapterDataControl id="testdata"
                  FactoryClass="oracle.adf.model.adapter.DataControlFactoryImpl"
                  ImplDef="oracle.adfinternal.model.adapter.sample.SampleDCDef"
                  SupportsTransactions="false"
                  SupportsSortCollection="false" SupportsResetState="false"
                  SupportsRangesize="false" SupportsFindMode="false"
                  SupportsUpdates="false" Definition="testdata"
                  BeanClass="testdata"
                  xmlns="http://xmlns.oracle.com/adfm/datacontrol">

      <Source>
         <Definition
               SourceLocation="/C:/Application1/ViewController/public_html/testdata.csv"/>
      </Source>
   </AdapterDataControl>
</DataControlConfigs>

The value of the id attribute of the AdapterDataControl tag ("testdata") is extracted from the name of the CSV file. The other attributes in the AdapterDataControl tag contain information about the simple CSV adapter itself. In the Definition element, the framework writes the metadata provided by the node; the SourceLocation attribute specifies the location of the CSV file.

20.4.6 Defining the Structure of the Data Control

Structure in a data control definition describes the items that appear when the user expands the data control in the Data Control Palette. Items that can appear include methods, accessors, and attributes of the underlying service that are available to the user to invoke or display. The user can drag these items onto a view page.

In your data control definition class, you need to implement the getStructure method. The framework calls this method when the user expands the data control in the Data Control Palette.

The getStructure method has the following signature:

Example 20-15 getStructure Signature

public oracle.binding.meta.StructureDefinition getStructure();

StructureDefinition is an interface. You can find more information about this interface in the online help in JDeveloper, under Reference > Oracle ADF Model API Reference.

Example 20-16 getStructure Method

public StructureDefinition getStructure()
{
   if (mStructDef == null)
   {
      // create an empty StructureDefinition
      mStructDef = new StructureDef(getName());
      SmartURL su = new SmartURL(mCSVUrl.toString());
      InputStream isData = su.openStream();
      CSVHandler csvHandler = new CSVHandler(isData, true, "UTF-8", ",", "\"");

      // Name of the accessor or the method structure to hold the attributes
      String opName = new SimpleStringBuffer(50).append(getDCName())
                                                .append("_")
                                                .append(RESULT_ACC_NAME)
                                                .toString();

      StructureDef def = (StructureDef)csvHandler.getStructure(opName, null);
      // Create the accessor definition
      AccessorDef accDef =
                       new AccessorDef(RESULT_ACC_NAME, mStructDef, def, true);
      def.setParentType(StructureDef.TYPE_ACCESSOR);
      accDef.setBindPath(new SimpleStringBuffer(50)
                                        .append(mStructDef.getFullName())
                                        .append(".")
                                        .append(AdapterDCService.DC_ROOT_ACC_NAME)
                                        .toString());
      mStructDef.addAccessor(accDef);
   }
   return mStructDef;
}

20.4.7 Creating an Instance of the Data Control

The framework calls the createDataControl method in the data control definition class to create a data control instance. The createDataControl method has the following signature:

Example 20-17 createDataControl Signature

public oracle.binding.DataControl createDataControl();

The DataControl object returned by the method is an instance of the data control class that you create. Section 20.5, "Implement the Data Control Class" describes this class.

In the data control definition for the simple CSV adapter, the createDataControl method looks like the following:

Example 20-18 createDataControl Method

public DataControl createDataControl()
{
   SampleDataControl dcDataControl = new SampleDataControl(mCSVUrl);
   return dcDataControl;
}

The SampleDataControl class is described in more detail in Section 20.5, "Implement the Data Control Class".

20.4.8 Setting the Metadata for Runtime

When the user runs the view page that references your data control, the framework reads the metadata from the DCX file and invokes the loadFromMetadata method in the data control definition class to load the data control with the metadata saved during design time.

Recall that the framework wrote the metadata to the DCX file in the getMetadata method. See Section 20.4.5, "Collecting Metadata from the User".

The loadFromMetadata method has the following signature:

Example 20-19 loadFromMetadata Signature

public void loadFromMetadata(org.w3c.dom.Node node, java.util.Map params);

The node parameter contains the metadata. In the simple CSV adapter, the method looks like the following:

Example 20-20 loadFromMetadata Method

public void loadFromMetadata(Node node, Map params)
{
   try
   {
      // Get the information from the definition
      NodeList listChld = node.getChildNodes();
      int cnt = listChld.getLength();
      Node chld;

      for (int i = 0; i < cnt; i++)
      {
         chld = listChld.item(i);
         // System.out.println("Tag: " + chld.getNodeName());
         if (DEFINITION.equalsIgnoreCase(chld.getNodeName()))
         {
            // Load the required attributes
            NodeAttributeHelper attribs = 
            new NodeAttributeHelper(chld.getAttributes());
            mCSVUrl = attribs.getValue(SOURCE_LOC);
         }
      }
   }
   catch (AdapterException ae)
   {
      throw ae;
   }
   catch (Exception e)
   {
      throw new AdapterException(e);
   }
}

20.4.9 Setting the Name for the Data Control

You need to implement the getDCName method to return a string that is used to identify the data control instance in the Data Control Palette. getDCName has the following signature:

Example 20-21 getDCName Signature

public String getDCName();

In the simple CSV adapter, the method just returns the value of the mName class variable, which was set by the SampleDCDef(String csvURL, String dcName) constructor. This constructor was called in the SampleDCAdapter class. mName is the name of the CSV file without the .csv extension.

Example 20-22 getDCName Method

public String getDCName()
{
   return mName;
}

Note that each data control instance must have a unique name within an application. For example, if you have two CSV data controls in an application, you can name them "CSV1" and "CSV2". For the CSV data control adapter that is shipped with JDeveloper, the user can enter the name in the wizard. For the simple CSV adapter, the name is the name of the CSV file without the .csv extension.