ヘッダーをスキップ
Oracle Application Development Framework Forms/4GL開発者のための開発者ガイド
10g(10.1.3.0)
B40013-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

31 データ・コントロール・アダプタの作成

JDeveloperに付属のデータ・コントロール以外のコントロールを使用する必要がある場合は、自分で作成できます。ADFでは、主に次の2つの方法でデータ・コントロールを作成できます。

この章では、2番目のデータ・コントロール・アダプタの作成について説明します。データ・コントロールの詳細は、第1章「Oracle ADFアプリケーションの概要」を参照してください。

この章のトピックは次のとおりです。

31.1 シンプルなCSVデータ・コントロール・アダプタの概要

この章では、カスタム・データ・コントロール・アダプタの例として、シンプルなCSVデータ・コントロール・アダプタについて説明します。このアダプタは、JDeveloperに付属のCSVデータ・コントロール・アダプタの簡略化バージョンです。

この章では、シンプルなCSVデータ・コントロール・アダプタの機能およびアダプタを構成するクラスについて説明します。

シンプルなCSVデータ・コントロール・アダプタは、ファイルからカンマ区切り値を取得し、ページに表示します。JDeveloperでアダプタを使用するには、次のいずれかを行います。

どちらの場合も、ノードはCSVテキスト・ファイルにマッピングされ、ファイル名には.csv拡張子が必要です。シンプルなCSVデータ・コントロール・アダプタはノードからメタデータを抽出するため、メタデータを入力する必要はありません。

シンプルなCSVアダプタを使用してデータ・コントロールを作成すると、データ・コントロールがデータ・コントロール・パレットに表示されます。これをビュー・ページにドラッグ・アンド・ドロップできます。

一部の詳細な設定を簡略化するために、シンプルなCSVアダプタは、次のようにハードコード化されています。

(JDeveloperに付属のCSVアダプタではこれらの値を設定できます。)

データ・コントロール・アダプタを作成する場合、ソース・インスタンスではなくソース・タイプを表すように作成します。CSVアダプタの場合、ソース・タイプはCSVファイルです。特定のCSVファイルなど、特定のデータ・インスタンスを指定するには、データ・コントロール・アダプタを使用してデータ・コントロールを作成し、インスタンスをメタデータと関連付けます。メタデータでは、インスタンスのデータを指定します。シンプルなCSVアダプタでは、メタデータには特定のCSVファイルへのパスが含まれています。

データ・コントロール・アダプタは次のことを行います。

データ・コントロール・アダプタは、アダプタ・フレームワーク内で動作します。アダプタ・フレームワークは、メタデータの格納、データ・コントロール・アダプタとADFライフサイクルの統合、設計時のJDeveloperとの統合を処理します。

31.2 データ・コントロール・アダプタの作成手順の概要

データ・コントロール・アダプタの作成手順:

  1. 抽象クラスを拡張するクラスを作成し、アダプタ・フレームワークでインタフェースを実装します。これらのクラスは、設計時および実行時に使用されます。次の項で説明する3つのクラスを作成する必要があります。

    アダプタの必要に応じて追加クラスを作成することもできます。シンプルなCSVアダプタには、2つの追加クラス、CSVHandlerCSVParserが含まれています。これらのクラスについては、31.6項「必要なサポート・クラスの作成」で説明します。

  2. 定義ファイルadapter-definition.xmlを作成して、アダプタをADFに登録します。このファイルにはアダプタ実装のクラス名が含まれ、アダプタが実行する必要があるライブラリを参照します。31.7項「アダプタを定義するXMLファイルの作成」を参照してください。

  3. クラス・ファイルと定義ファイルをJARファイルにパッケージ化して、そのJARファイルをJDeveloperのクラスパスに置いて、JDeveloperにデータ・コントロール・クラスをインストールします。31.9項「アダプタのパッケージ化とJDeveloperへのデプロイ」を参照してください。

アダプタの起動

JDeveloperにデータ・コントロール・アダプタをインストールした後、このアダプタを起動するには、データ・コントロール・アダプタがサポートするJDeveloperのノードを右クリックし、ポップアップ・メニューから「データ・コントロールの作成」を選択します。データ・コントロール・アダプタは、そのadapter-definition.xml構成ファイルでサポートするノード・タイプを宣言します(31.7項「アダプタを定義するXMLファイルの作成」を参照)。

たとえば、アダプタがデータベース接続ノードをサポートしている場合、データベース接続を右クリックすると、ポップアップ・メニューから「データ・コントロールの作成」を選択して、アダプタを起動できます。

この章では、ウィザードの作成方法およびウィザードからアダプタへの値の渡し方については説明しません。

31.3 抽象アダプタ・クラスの実装

AbstractAdapterクラスの実装はオプションです。このクラスは、ユーザーがデータ・コントロール・パレットにノードをドラッグ・アンド・ドロップして、データ・コントロールを作成できるようにする場合にのみ必要です。この場合、ドロップしたノードは、作成しているデータ・コントロールに関連付けられたデータソースを表します。この機能が必要ない場合は、このクラスを実装する必要はありません。たとえば、JDeveloperに付属のCSVデータ・コントロール・アダプタは、ドラッグ・アンド・ドロップ操作をサポートしていないため、このクラスを実装していません。このアダプタでは、ユーザーから情報を収集するウィザードが表示されます。

シンプルなCSVアダプタはAbstractAdapterを実装します。ユーザーがデータ・コントロール・パレットにノードをドラッグ・アンド・ドロップすると、JDeveloperはドロップされたタイプのノードを処理できるアダプタを確認します。adapter-definition.xmlファイルで、アダプタが処理できるノード・タイプを指定します。このファイルは、アダプタをJDeveloperに登録するために使用します。このファイルの詳細は、31.7項「アダプタを定義するXMLファイルの作成」を参照してください。

クラスでは、次の項で説明するように、AbstractAdapterクラスにいくつかのメソッドを実装する必要があります。

31.3.1 JARファイルの場所

抽象クラスoracle.adf.model.adapter.AbstractAdapterは、JDEV_HOME/bc4j/lib/adfm.jarファイルにあります。

31.3.2 抽象アダプタ・クラスの概要

例31-1に、AbstractAdapterクラスを実装するクラスの概要を示します。

例31-1 AbstractAdapterを実装するクラスの概要

import oracle.adf.model.adapter.AbstractAdapter;
import oracle.adf.model.adapter.DTContext;
import oracle.adf.model.adapter.AbstractDefinition;

public class MyAdapter extends AbstractAdapter
{
   public void initialize(Object sourceObj, DTContext ctx)
   {
      // you need to implement this method.
      // see Section 31.3.4, "Implementing the initialize Method".
   }

   public boolean invokeUI()
   {
      // you need to implement this method.
      // see Section 31.3.5, "Implementing the invokeUI Method".
   }

   public AbstractDefinition getDefinition()
   {
      // you need to implement this method.
      // see Section 31.3.6, "Implementing the getDefinition Method".
   }
}

31.3.3 SampleDCAdapterクラスの完全なソース

例31-2に、SampleDCAdapterクラスの完全なソースを示します。これは、シンプルなCSVアダプタ用のAbstractAdapterを実装するクラスです。その後の項では、このクラスのメソッドについて説明します。

例31-2 SampleDCAdapterの完全なソース

package oracle.adfinternal.model.adapter.sample;

import java.net.URL;

import oracle.adf.model.adapter.AbstractAdapter;
import oracle.adf.model.adapter.AbstractDefinition;
import oracle.adf.model.adapter.DTContext;

import oracle.ide.Context;

public class SampleDCAdapter extends AbstractAdapter
{
   // JDev Context
   private Context              mJdevCtx    = null;

   // Source object of data
   private Object               mSrc        = null;
   // Source Location
   private String               mSrcLoc     = null;
   // data control name
   private String               mDCName     = null;
   // data control definition
   private AbstractDefinition   mDefinition = null;

   public SampleDCAdapter()
   {
   }

   /**
    * Initializes the adapter from a source object.
    * <p>
    * The source object can be different thing depending on the context of the
    * design time that the adapter is used in. For JDeveloper, the object will
    * be a JDeveloper node.
    * </p>
    * <p>
    * Adapter implementations will check the <code>"ctx"</code> parameter to
    * get the current design time context. The source object will be used to
    * extract the information for the data source.
    * </p>
    * @param sourceObj Object that contains information about the data source
    *            that will be used to define the data control.
    * @param ctx Current design time context.
    */
   public void initialize(Object sourceObj, DTContext ctx)
   {
      mSrc = sourceObj;
      mJdevCtx = (Context) ctx.get(DTContext.JDEV_CONTEXT);
   }

   /**
    * Invlokes the UI at the design time.
    * <p>
    * This method is a call back from the JDeveloper design time environment to
    * the adapters to bring up any UI if required to gather information about
    * the data source they represent.
    * </p>
    *
    * @return false if the user cancels the operation. The default retrun value
    * is true.
    */
   public boolean invokeUI()
   {
      // First check if this is a JDev environment.
      if (mJdevCtx != null && mSrc != null)
      {
         if (extractDataSourceInfo(mSrc))
         {
            SampleDCDef def = new SampleDCDef(mSrcLoc,mDCName);
            mDefinition = def;
            return true;
         }
         return false;
      }
      return false;
   }

    /**
    * <p>
    * The Definition instance obtained can be used by the ADF design time to
    * capture the data control metadata.
    *</p>
    *
    * @return The definition instance describing the data control design time.
    */
   public AbstractDefinition getDefinition()
   {
      return mDefinition;
   }

   /**
    * @param source the data source object.
    * @return false if data type is unknown.
    */
   public boolean canCreateDataControl(Object source)
   {
      return extractDataSourceInfo(source);
   }

   /**
    * Extracts information from a data source. This method extracts name
    * from the object.
    * @param obj the data source object.
    */
   private boolean extractDataSourceInfo(Object obj)
   {
      mDCName = "SampleDC";

      // See if the node dropped is a text node of CSV type.
      // We will assume that the CSV data file must end with .csv
      if (obj instanceof oracle.ide.model.TextNode)
      {
         oracle.ide.model.TextNode tn = (oracle.ide.model.TextNode) obj;
         URL url = tn.getURL();
         String loc = url.getFile();
         // Check if the file has a matching extension
         if (loc.endsWith(".csv"))
         {
            mSrcLoc = loc;
            String path = url.getPath();
            int index = path.lastIndexOf('/');

            if (index != -1)
            {
               String fileName = path.substring(index+1);
               int dotIndex = fileName.lastIndexOf('.');
               mDCName = fileName.substring(0,dotIndex);
            }
            return true;
         }
      }
      return false;
   }

}

31.3.4 initializeメソッドの実装

フレームワークは、ユーザーがデータ・コントロール・パレットにノードをドラッグ・アンド・ドロップするとinitializeメソッドをコールします。メソッドには次のシグネチャがあります。

例31-3 initializeのシグネチャ

public abstract void initialize(Object sourceObj, DTContext ctx);

sourceObjパラメータでは、ドロップされたノードを指定します。このパラメータをチェックして、アダプタが処理できるノード・タイプであることを確認できます。

ctxパラメータでは、設計時のコンテキストを指定します。DTContextのパッケージ・パスはoracle.adf.model.adapter.DTContextです。

initializeメソッドでは、次のタスクを実行する必要があります。

  • ソース・ノードがサポートされているかどうかをチェックします。

  • ノードがサポートされている場合は、ソース・ノードからデータ・コントロール・インスタンスの作成に必要なすべての情報を抽出します。情報がデータ・コントロール・インスタンスの作成に十分ではない場合、invokeUIメソッドでユーザーが必要な情報を入力するUIを表示できます。

シンプルなCSVアダプタでは、initializeメソッドはいくつかのクラス変数のみを設定します。これらのクラス変数は、後でinvokeUIメソッドでチェックされます。

例31-4 initializeメソッド

   public void initialize(Object sourceObj, DTContext ctx)
   {
      mSrc = sourceObj;
      mJdevCtx = (Context) ctx.get(DTContext.JDEV_CONTEXT);
   }

31.3.5 invokeUIメソッドの実装

このメソッドでは、ドロップされたデータソースに関する情報をユーザーから収集するためのUIを表示できます。メソッドにはAbstractAdapterに次のシグネチャがあります。

例31-5 invokeUIのシグネチャ

public boolean invokeUI()
{
   return true;
}

メソッドは、ユーザーがUIでの操作を取り消した場合にfalseを返す必要があります。この場合、データ・コントロールは作成されません。

情報を収集するためのUIが実行された場合は、trueを返す必要があります(デフォルトの実装)。

シンプルなCSVアダプタでは、initializeメソッドを使用して、次のことを実行するextractDataSourceInfoをコールする必要があります。

  • ユーザーが右クリックしたノードがテキスト・ファイルを表し、ファイル名に.csv拡張子があることをチェックします。

  • CSVファイルのファイル名を取得します。

  • mSrcLocおよびmDCNameクラス変数を設定します。mSrcLocはCSVファイルの場所をポイントします。mDCNameはデータ・コントロールに使用する名前です。この場合、.csv拡張子のないCSVファイルの名前です。

    invokeUIは、これらの変数を使用してSampleDCDefオブジェクトをインスタンス化します。SampleDCDefオブジェクトというクラスも実装する必要があります。このクラスについては、31.4項「データ・コントロール定義クラスの実装」で説明します。

例31-6に、invokeUIメソッドを示します。

例31-6 invokeUI

   public boolean invokeUI()
   {
      // First check if this is a JDev environment.
      if (mJdevCtx != null && mSrc != null)
      {
         if (extractDataSourceInfo(mSrc))
         {
            SampleDCDef def = new SampleDCDef(mSrcLoc,mDCName);
            mDefinition = def;
            return true;
         }
         return false;
      }
      return false;
   }

31.3.6 getDefinitionメソッドの実装

このメソッドは、ドロップされたソース・ノードから収集した情報に基づいて作成されたデータ・コントロールの定義を返します。メソッドには次のシグネチャがあります。

例31-7 getDefinitionのシグネチャ

public abstract AbstractDefinition getDefinition();

AbstractDefinitionクラスは、作成されたデータ・コントロール定義クラスです。31.4項「データ・コントロール定義クラスの実装」を参照してください。

シンプルなCSVアダプタでgetDefinitionメソッドが返すクラス変数mDefinitionの値は、invokeUIメソッドで設定された値です。mDefinitionは、ユーザーによって作成されたデータ・コントロール定義クラス(シンプルなCSVアダプタの場合はSampleDCDef)を参照します。

例31-8 getDefinition

   public AbstractDefinition getDefinition()
   {
      return mDefinition;
   }

31.4 データ・コントロール定義クラスの実装

このクラスは、設計時および実行時にフレームワークがデータ・コントロールをインスタンス化するために必要なすべての情報を提供する必要があります。このクラスは、次の操作を行います。

31.4.1 JARファイルの場所

データ・コントロール定義クラスは、抽象クラスoracle.adf.model.adapter.AbstractDefinitionを展開する必要があります。このクラスは、JDEV_HOME/bc4j/lib/adfm.jarファイルにあります。

31.4.2 データ・コントロール定義クラスの概要

例31-9に、データ・コントロール定義クラスの作成時に実装する必要があるメソッドの概要を示します。SampleDCDefからのサンプルです。これは、シンプルなCSVデータ・コントロール・アダプタのデータ・コントロール定義クラスです。

例31-9 データ・コントロール定義クラスの概要

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 31.4.4, "Creating a Default Constructor".
   }

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

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

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

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

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

31.4.3 SampleDCDefクラスの完全なソース

例31-10に、SampleDCDefクラスの完全なソースを示します。

例31-10 SampleDCDefクラスの完全なソース

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";
   }
}

31.4.4 デフォルト・コンストラクタの作成

データ・コントロール定義クラスのデフォルト・コンストラクタを作成する必要があります。シンプルなCSVアダプタには空のデフォルト・コンストラクタがあります。

例31-11 SampleDCDefのデフォルト・コンストラクタ

public SampleDCDef()
{
}

デフォルト・コンストラクタは、実行時にのみ使用されます。設計時には使用されません。

31.4.5 ユーザーからのメタデータの収集

データ・コントロール・アダプタのメタデータは、データソースに関する情報を提供します。データ・コントロール定義クラスは、メタデータを使用してデータ・コントロールを作成します。完全な機能を備えたCSVデータ・コントロール・アダプタのメタデータには、CSVファイルへのURL、フィールド・セパレータ文字、引用文字などが含まれています。シンプルなCSVアダプタの場合、メタデータにはCSVファイルの場所のみが含まれています。

データ・コントロール・アダプタは、様々な方法でメタデータを収集できます。次に例を示します。

  • JDeveloperに付属のCSVデータ・コントロール・アダプタは、ウィザードを使用してユーザーからメタデータを収集します。

  • Webサービスのデータ・コントロール・アダプタも、ウィザードを使用してメタデータを収集します。ユーザーがWebサービス接続ノードをドラッグして、データ・コントロール・パレットにドロップすることもできます。Webサービス・アダプタは、ウィザードを起動せずにノードからメタデータを抽出します。

    ユーザーがデータ・コントロール・パレットにノードをドラッグ・アンド・ドロップすると、アダプタ・フレームワークは、登録されたデータ・コントロール・アダプタを検索して、ドロップされたタイプのノードを処理できるアダプタを探します。データ・コントロール・アダプタは、サポートするノード・タイプを宣言します。ノードは、特定のソース・タイプを表すJDeveloperノードです。ドロップされたタイプのノードをサポートするアダプタが検出された場合、フレームワークはデータ・コントロール・アダプタを起動し、ノードから必要な情報を抽出します。

  • シンプルなCSVアダプタは、ユーザーがノードを右クリックし、ポップアップ・メニューから「データ・コントロールの作成」を選択すると、ノードからメタデータを抽出します。

データ・コントロール・アダプタがメタデータを取得する方法に関係なく、データ・コントロール定義クラスにgetMetadataメソッドを実装する必要があります。フレームワークはこのメソッドをコールして、メタデータを取得します。

このメソッドは、Nodeオブジェクトの形でメタデータを返します。getMetadataメソッドには次のシグネチャがあります。

例31-12 getMetadataのシグネチャ

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

シンプルなCSVアダプタでは、getMetadataメソッドは、mCSVUrlクラス変数からメタデータを取得し、値をElementオブジェクトに挿入します。

例31-13 getMetadataメソッド

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

フレームワークは、getMetadataの戻り値(Nodeオブジェクト)から情報を抽出し、情報をDataControls.dcxファイルに書き込みます。たとえば、ユーザーがCSVデータ・コントロールを作成すると、ファイルは次のようになります。

例31-14 DataControls.dcxファイル

<?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>

AdapterDataControlタグのid属性の値(testdata)は、CSVファイルの名前から抽出されます。AdapterDataControlタグの他の属性には、シンプルなCSVアダプタ本体に関する情報が含まれます。Definition要素には、ノードから提供されたメタデータが書き込まれます。SourceLocation属性では、CSVファイルの場所を指定します。

31.4.6 データ・コントロールの構造の定義

データ・コントロール定義の構造では、ユーザーがデータ・コントロール・パレットでデータ・コントロールを展開したときに表示する項目を説明します。表示可能な項目には、ユーザーが起動または表示できる基礎となるサービスのメソッド、アクセッサおよび属性が含まれます。ユーザーは、これらの項目をビュー・ページにドラッグ・アンド・ドロップできます。

データ・コントロール定義クラスでは、getStructureメソッドを実装する必要があります。ユーザーがデータ・コントロール・パレットでデータ・コントロールを展開すると、フレームワークは、このメソッドをコールします。

getStructureメソッドには次のシグネチャがあります。

例31-15 getStructureのシグネチャ

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

StructureDefinitionはインタフェースです。このインタフェースの詳細は、JDeveloperのオンライン・ヘルプの「リファレンス」→「Oracle ADF Model API Reference」を参照してください。

例31-16 getStructureメソッド

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;
}

31.4.7 データ・コントロールのインスタンスの作成

フレームワークはデータ・コントロール定義クラスのcreateDataControlメソッドをコールして、データ・コントロール・インスタンスを作成します。createDataControlメソッドには次のシグネチャがあります。

例31-17 createDataControlのシグネチャ

public oracle.binding.DataControl createDataControl();

メソッドによって返されるDataControlオブジェクトは、作成するデータ・コントロール・クラスのインスタンスです。このクラスについては、31.5項「データ・コントロール・クラスの実装」を参照してください。

シンプルなCSVアダプタのデータ・コントロール定義では、createDataControlメソッドは次のとおりです。

例31-18 createDataControlメソッド

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

SampleDataControlクラスについては、31.5項「データ・コントロール・クラスの実装」で詳しく説明します。

31.4.8 実行時のメタデータの設定

ユーザーがデータ・コントロールを参照するビュー・ページを実行すると、フレームワークはDCXファイルからメタデータを読み取り、データ・コントロール定義クラスのloadFromMetadataメソッドを起動して、設計時に保存されたメタデータとともにデータ・コントロールをロードします。

フレームワークは、getMetadataメソッドでDCXファイルにメタデータを書き込んでいます。31.4.5項「ユーザーからのメタデータの収集」を参照してください。

loadFromMetadataメソッドには次のシグネチャがあります。

例31-19 loadFromMetadataのシグネチャ

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

nodeパラメータにメタデータが含まれています。シンプルなCSVアダプタのメソッドは次のとおりです。

例31-20 loadFromMetadataメソッド

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);
   }
}

31.4.9 データ・コントロールの名前の設定

データ・コントロール・パレットのデータ・コントロール・インスタンスの識別に使用される文字列を返すgetDCNameメソッドを実装する必要があります。getDCNameには次のシグネチャがあります。

例31-21 getDCNameのシグネチャ

public String getDCName();

シンプルなCSVアダプタでは、メソッドは、SampleDCDef(String csvURL, String dcName)コンストラクタによって設定されたmNameクラス変数の値のみを返します。このコンストラクタは、SampleDCAdapterクラスでコールされました。mNameは、.csv拡張子のないCSVファイルの名前です。

例31-22 getDCNameメソッド

public String getDCName()
{
   return mName;
}

各データ・コントロール・インスタンスには、アプリケーション内で一意の名前が必要です。たとえば、アプリケーションに2つのCSVデータ・コントロールがある場合は、これらに「CSV1」、「CSV2」という名前を付けることができます。JDeveloperに付属のCSVデータ・コントロール・アダプタでは、ユーザーはウィザードで名前を入力できます。シンプルなCSVアダプタの場合、名前は.csv拡張子のないCSVファイルの名前になります。

31.5 データ・コントロール・クラスの実装

データ・コントロール・クラスは、設計時に保存されたメタデータに基づいて、データソースにアクセスできる必要があります。このクラスは、データ・コントロール定義クラスのcreateDataControlメソッドによってインスタンス化されます(31.4.7項「データ・コントロールのインスタンスの作成」を参照)。

このクラスは、次のことを行う必要があります。

表31-1 データ・コントロール・インタフェース

インタフェース 使用するとき

oracle.binding.DataControl

リクエストの開始と終了を区別する必要がなく、トランザクション・サポートが必要ない場合に、このインタフェースを実装します。

oracle.binding.ManagedDataControl

リクエストの開始と終了を区別する必要がある場合に、このインタフェースを実装します。このインタフェースはDataControlを展開するため、DataControlのメソッドも実装する必要があります。

oracle.binding.TransactionalDataControl

トランザクション・サポートが必要な場合に、このインタフェースを実装します。このインタフェースは、DataControlインタフェースのメソッドに加えて、rollbackTransactionメソッドとcommitTransactionメソッドも実装する必要があります。(TransactionalDataControlDataControlインタフェースを拡張します。)


31.5.1 JARファイルの場所

抽象クラスoracle.adf.model.AbstractImplは、JDEV_HOME/bc4j/lib/adfm.jarファイルにあります。

データ・コントロール・インタフェースは、JDEV_HOME/bc4j/lib/adfbinding.jarファイルにあります。

31.5.2 データ・コントロール・クラスの概要

次のクラス概要に、データ・コントロール・クラスで実装する必要があるメソッドを示します。

例31-23 データ・コントロール・クラスの概要

import oracle.adf.model.adapter.AbstractImpl;
import oracle.binding.DataControl;
import java.util.HashMap;

public class SampleDataControl extends AbstractImpl implements ManagedDataControl
{
   public boolean invokeOperation(java.util.Map map,
                                  oracle.binding.OperationBinding action)
   {
      // you need to implement this method.
      // see Section 31.5.4, "Implementing the invokeOperation Method".
   }

   public String getName()
   {
      // you need to implement this method.
      // see Section 31.5.5, "Implementing the getName Method".
   }

   public void release(int flags)
   {
      // you need to implement this method.
      // see Section 31.5.6, "Implementing the release Method".
   }

   public Object getDataProvider()
   {
      // you need to implement this method.
      // see Section 31.5.7, "Implementing the getDataProvider Method".
   }
}

31.5.3 SampleDataControlクラスの完全なソース

例31-24に、SampleDataControlクラスの完全なソースを示します。

例31-24 SampleDataControlクラスの完全なソース

package oracle.adfinternal.model.adapter.sample;

import java.io.InputStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.naming.Context;

import oracle.binding.ManagedDataControl;
import oracle.binding.OperationInfo;

import oracle.adf.model.adapter.AdapterException;
import oracle.adf.model.adapter.AbstractImpl;
import oracle.adf.model.adapter.dataformat.CSVHandler;

import oracle.adfinternal.model.adapter.url.SmartURL;

// Data control that represents a URL data source with CSV data format.
public class SampleDataControl extends AbstractImpl
   implements ManagedDataControl
{
   //URL to access the data source
   private String mCSVUrl = null;

   public SampleDataControl()
   {
   }

   public SampleDataControl(String csvUrl)
   {
      mCSVUrl = csvUrl;
   }

   public boolean invokeOperation(java.util.Map map,
                                  oracle.binding.OperationBinding action)
   {
      Context ctx = null;
      try
      {
         // We are interested of method action binding only.
         if (action == null)
         {
            return false;
         }

         OperationInfo method = action.getOperationInfo();
         // No method defined, we are not interested.
         if (method == null)
         {
            return false;
         }

         // Execute only when the adapter execute is invoked
         if (METHOD_EXECUTE.equals(method.getOperationName()))
         {
            Object retVal = null;
            if (mCSVUrl != null)
            {
               SmartURL su = new SmartURL(mCSVUrl);
               InputStream isData = su.openStream();
               CSVHandler csvHandler =
                                 new CSVHandler(isData,true,"UTF-8",",","\"");
               Map properties = new HashMap();
               retVal = csvHandler.getResult(properties);
            }

            Map rootDataRow = new java.util.HashMap(2);
            rootDataRow.put(SampleDCDef.RESULT_ACC_NAME, retVal);
            ArrayList aRes = new ArrayList(2);
            aRes.add(rootDataRow);

            processResult(aRes.iterator(), map, action);
            return true;
         }
      }
      catch (AdapterException ae)
      {
         throw ae;
      }
      catch (Exception e)
      {
         throw new AdapterException(e);
      }
      return false;
   }

   /**
   * Perform request level initialization of the DataControl.
   * @param requestCtx a HashMap representing request context.
   */
   public void beginRequest(HashMap requestCtx)
   {
   }

   /**
   * perform request level cleanup of the DataControl.
   * @param requestCtx a HashMap representing request context.
   */
   public void endRequest(HashMap requestCtx)
   {
   }

   /**
   * return false as resetState was deferred to endRequest processing
   */
   public boolean resetState()
   {
      return false;
   }

   /**
   * returns the name of the data control.
   */
   public String getName()
   {
      return mName;
   }

   /**
   * releases all references to the objects in the data provider layer
   */
   public void release(int flags)
   {
   }

   /**
   * Return the Business Service Object that this datacontrol is associated with.
   */
   public Object getDataProvider()
   {
      return null;
   }

}

31.5.4 invokeOperationメソッドの実装

データ・コントロール・クラスでinvokeOperationメソッドを実装する必要があります。フレームワークは、ユーザーがビュー・ページを実行すると、このメソッドを起動します。

このメソッドは、DataControlインタフェースで宣言されます。メソッドには次のシグネチャがあります。

例31-25 invokeOperationのシグネチャ

public boolean invokeOperation(java.util.Map bindingContext,
                               oracle.binding.OperationBinding action);

bindingContextパラメータには、データソースからフェッチされた戻り値が入ります。値を取得するキーは、フレームワークによって生成されます。通常、値をフィルタリングまたは変換する必要がないかぎり、値を処理する必要はありません。

actionパラメータでは、値を生成したメソッドを指定します。メソッドには、Webサービスの場合のように、基礎となるサービスでサポートされているメソッドを指定できます。データ・コントロールでデフォルトの動作を無効にする必要がある場合、フレームワークは、一部の組込みアクションにもデータ・コントロールをコールします。このパラメータをチェックして、アクションを処理する必要があるかどうかを確認できます。メソッドを公開しないデータソースを表すデータ・コントロールの場合、フレームワークはアクションAbstractImpl.METHOD_EXECUTEを作成して、データ・コントロールの問合せを実行します。

アクションを処理しない場合、メソッドはfalseを返します。

シンプルなCSVアダプタでは、invokeOperationメソッドは、データをフェッチする前にメソッドがMETHOD_EXECUTEであることをチェックします。CSVHandlerクラスが起動され、次にCSVParserクラスが起動されて、CSVファイルからデータが取得されます。

例31-26 invokeOperationメソッド

   public boolean invokeOperation(java.util.Map map,
                                  oracle.binding.OperationBinding action)
   {
      Context ctx = null;
      try
      {
         // We are interested in method action binding only.
         if (action == null)
         {
            return false;
         }

         OperationInfo method = action.getOperationInfo();
         // No method defined, we are not interested.
         if (method == null)
         {
            return false;
         }

         // Execute only when the adapter execute is invoked
         if (METHOD_EXECUTE.equals(method.getOperationName()))
         {
            Object retVal = null;
            if (mCSVUrl != null)
            {
               SmartURL su = new SmartURL(mCSVUrl);
               InputStream isData = su.openStream();
               CSVHandler csvHandler =
                                 new CSVHandler(isData, true, "UTF-8", ",", "\"");
               Map properties = new HashMap();
               retVal = csvHandler.getResult(properties);
            }

            Map rootDataRow = new java.util.HashMap(2);
            rootDataRow.put(SampleDCDef.RESULT_ACC_NAME, retVal);
            ArrayList aRes = new ArrayList(2);
            aRes.add(rootDataRow);

            processResult(aRes.iterator(), map, action);
            return true;
         }
      }
      catch (AdapterException ae)
      {
         throw ae;
      }
      catch (Exception e)
      {
         throw new AdapterException(e);
      }
      return false;
   }

invokeOperationは、データのフェッチ後にprocessResultメソッドをコールする点に注意してください。詳細は、次の項を参照してください。

31.5.4.1 processResultのコールについて

invokeOperationは、processResultをコールしてフレームワークに更新された値を提供します。メソッドは結果をバインディング・コンテキストに入れて、フレームワークから取り出せるようにします。メソッドの構文は次のとおりです。

例31-27 processResultの構文

public void processResult(Object result,
                          Map bindingContext,
                          oracle.binding.OperationBinding action)

resultパラメータでは、更新された値を指定します。

bindingContextパラメータでは、バインディング・コンテキストを指定します。通常は、invokeOperationメソッドに渡されたバインディング・コンテキストと同じです。

actionパラメータでは、操作を指定します。通常は、invokeOperationメソッドに渡されたアクション値と同じです。

31.5.4.2 invokeOperationの戻り値

メソッドでアクションを処理した場合、invokeOperationからtrueが返されます。フレームワークでアクションを処理する必要がある場合はfalseが返されます。

31.5.5 getNameメソッドの実装

バインディング・コンテキストで使用されるデータ・コントロール名を返す、getNameメソッドを実装します。

このメソッドは、DataControlインタフェースで宣言されます。次のシグネチャがあります。

例31-28 getNameのシグネチャ

public String getName();

シンプルなCSVアダプタでは、メソッドは単純にmNameを返します。これはAbstractImplクラスで宣言された変数です。

例31-29 getNameメソッド

public String getName()
{
   return mName;
}

31.5.6 releaseメソッドの実装

フレームワークはreleaseメソッドをコールして、データ提供レイヤーでのオブジェクトへのすべての参照を解放します。

このメソッドは、DataControlインタフェースで宣言されます。次のシグネチャがあります。

例31-30 releaseのシグネチャ

public void release(int flags);

flagsパラメータは、解放する参照を示します。

  • REL_ALL_REFS: データ・コントロールは、ビュー・オブジェクトとモデル・オブジェクトへのすべての参照を解放します。

  • REL_DATA_REFS: データ・コントロールは、データ・プロバイダ・オブジェクトへの参照を解放します。

  • REL_VIEW_REFS: データ・コントロールは、ビュー・オブジェクトまたはUIレイヤー・オブジェクトへのすべての参照を解放します。

シンプルなCSVデータ・コントロール・アダプタでは、releaseメソッドは空白です。ただし、データ・コントロールで接続を使用する場合、このメソッドで接続を閉じ、解放する必要があります。

31.5.7 getDataProviderメソッドの実装

このメソッドは、このデータ・コントロールに関連付けられているビジネス・サービス・オブジェクトを返します。

このメソッドは、DataControlインタフェースで宣言されます。次のシグネチャがあります。

例31-31 getDataProviderのシグネチャ

public Object getDataProvider();

シンプルなCSVデータ・コントロール・アダプタでは、このメソッドはnullのみを返します。

31.6 必要なサポート・クラスの作成

ADFインタフェースを実装する必須クラスに加えて、必要に応じてアダプタのサポート・クラスを作成できます。シンプルなCSVアダプタには、2つの追加クラス、CSVHandlerCSVParserが含まれています。これらのクラスは、CSVファイルを行とフィールドに読み込み、解析します。これらのクラスの完全なソース・リストは、31.11項「サポート・ファイルの内容」を参照してください。

31.7 アダプタを定義するXMLファイルの作成

JDeveloperのアダプタを定義するには、adapter-definition.xmlと呼ばれるファイルを作成し、meta-infと呼ばれるディレクトリに入れます。ファイル名とディレクトリ名では、大文字と小文字が区別されます。

一般的なadapter-definition.xmlファイルには、次のエントリがあります。

例31-32 adapter-definition.xmlファイルの説明

<AdapterDefinition>
   <Adapter Name="unique name for the adapter"
            ClassName="full name of class that implements AbstractAdapter">

      <Schema Namespace="name of schema that defines the data control metadata for this adapter"
              Location="location of schema definition file"/>

      <Source>
         <Type Name="name of source type that the adapter can handle to create a data control"
               JDevNode="full class name of supported node"/>
      </Source>

      <JDevContextHook Class="full name of class that provides the JDeveloper context hook, if any"/>

      <Dependencies>
         <Library Path="full path name of the JAR file that the adapter needs in order to run"/>
      </Dependencies>

   </Adapter>
</AdapterDefinition>

AdapterDefinitionタグは、すべてのアダプタのコンテナ・タグです。

Adapterタグは、アダプタを説明します。次の属性があります。

Schemaタグでは、アダプタのメタデータのネームスペースとスキーマ定義を定義します。JDeveloperは、設計時にメタデータを検証できるように、スキーマを登録します。アダプタがサポートするすべてのネームスペースとスキーマを定義できます。これはオプションです。

Sourceタグでは、アダプタがサポートするノード(またはデータソース)のタイプを指定します。次の属性があります。

JDevContextHookタグでは、ポップアップ・メニュー(ユーザーが構造ペインでデータ・コントロール・インスタンスのメタデータ・ノードを右クリックすると表示されるメニュー)に追加するメニューを指定します。

Dependenciesタグは、アダプタが実行時に必要とするライブラリ・ファイルをリストします。フレームワークは、ユーザーがアダプタに基づくデータ・コントロールを使用すると、プロジェクトにライブラリ・ファイルを追加します。

シンプルなCSVデータ・コントロール・アダプタのadapter-definition.xmlファイルは、次のとおりです。

例31-33 シンプルなCSVアダプタのadapter-definition.xmlファイル

<AdapterDefinition>
   <Adapter Name="oracle.adfm.adapter.SampleDataControl"
            ClassName="oracle.adfinternal.model.adapter.sample.SampleDCAdapter">
      <Schema Namespace="http://xmlns.oracle.com/adfm/adapter/sample"
            Location="/oracle/adfinternal/model/adapter/sample/sampleDC.xsd"/>
      <Source>
         <Type Name="csvNode" JDevNode="oracle.ide.model.TextNode"/>
      </Source>
      <Dependencies>
         <Library Path="${oracle.home}/jlib/sampledc.jar"/>
      </Dependencies>
   </Adapter>
</AdapterDefinition>

sampleDC.xsdファイルについては、31.11.1項「sampleDC.xsd」を参照してください。

31.8 アダプタのビルド

アダプタをビルドするには、プロジェクトに次のライブラリを追加する必要があります。

  1. JDeveloperの「プロジェクト・プロパティ」ダイアログの左側で「ライブラリ」を選択します。

  2. 右側の「ライブラリの追加」をクリックして、次のライブラリを追加します。

    • JSR-227 API

    • ADF Model Generic Runtime

    • Oracle XML Parser v2

  3. 右側の「Jar/ディレクトリの追加」をクリックして、次のライブラリを追加します。

    • JDEV_HOME/ide/lib/ide.jar

    • JDEV_HOME/ide/lib/javatools.jar

    • JDEV_HOME/bc4j/jlib/dc-adapter.jar

31.9 アダプタのパッケージ化とJDeveloperへのデプロイ

アダプタをJDeveloperにデプロイするには、次の手順を実行します。

  1. meta-infディレクトリ(adapter-definition.xmlファイルが入っているディレクトリ)にextension.xmlファイルを作成します。

    これは、アダプタをJDeveloperの拡張機能としてデプロイしているためです。extension.xmlを使用して、JARファイルをJDeveloperのクラスパスに追加します。

    extension.xmlファイルには、次の行があります。

    例31-34 extension.xml

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <extension xmlns="http://jcp.org/jsr/198/extension-manifest"
                id="oracle.adfm.sample-adapters"
                version="10.1.3.36.45"
                esdk-version="1.0">
       <name>ADFm Sample Adapter</name>
       <owner>Oracle Corporation</owner>
       <dependencies>
          <import>oracle.BC4J</import>
          <import>oracle.j2ee</import>
       </dependencies>
       <classpaths>
          <classpath>../../BC4J/jlib/dc-adapters.jar</classpath>
          <classpath>../../jlib/sampledc.jar</classpath>
       </classpaths>
    
       <hooks>
          <!-- Adapter-specific data control library definitions -->
          <libraries xmlns="http://xmlns.oracle.com/jdeveloper/1013/jdev-libraries">
             <library name="Sample Data Control" deployed="true">
                <classpath>../../jlib/sampledc.jar</classpath>
             </library>
          </libraries>
       </hooks>
    </extension>
    

    extension.xmlファイルのタグの詳細は、JDEV_HOME/jdev/doc/extension/ide-extension-packaging.htmlというファイルを参照してください。

  2. アダプタのクラス・ファイル(adapter-definition.xmlファイルとextension.xmlファイル)を含むJARファイルを作成します。XMLファイルは、meta-infディレクトリに入れる必要があります。

    シンプルなCSVアダプタでは、このJARファイルはsampledc.jarと呼ばれ、次のファイルが含まれています。

    例31-35 sampledc.jar

    connections.xml
    extension/meta-inf/extension.xml
    meta-inf/adapter-definition.xml
    meta-inf/Manifest.mf
    oracle/adfinternal/model/adapter/sample/CSVHandler$1.class
    oracle/adfinternal/model/adapter/sample/CSVHandler.class
    oracle/adfinternal/model/adapter/sample/CSVParser.class
    oracle/adfinternal/model/adapter/sample/SampleDataControl.class
    oracle/adfinternal/model/adapter/sample/SampleDCAdapter.class
    oracle/adfinternal/model/adapter/sample/SampleDCDef.class
    
  3. JARファイルをJDEV_HOME/jlibディレクトリにコピーします。

  4. meta-infディレクトリに、extension.xmlファイルとmanifestファイルのみを含む別のJARファイルを作成します。シンプルなCSVアダプタでは、このJARファイルはoracle.adfm.sampledc.10.1.3.jarと呼ばれ、次のファイルが含まれています。

    例31-36 oracle.adfm.sampledc.10.1.3.jar

    meta-inf/extension.xml
    meta-inf/Manifest.mf
    
  5. 2番目のJARファイル(oracle.adfm.sampledc.10.1.3.jarなど)をJDEV_HOME/jdev/extensionsディレクトリにコピーします。

  6. JDeveloperを実行している場合は停止します。

  7. JDeveloperを起動します。アダプタがサポートするノード・タイプを右クリックすると、「データ・コントロールの作成」メニュー項目が表示されます。

JDeveloper拡張機能の詳細は、Extension SDKをダウンロードしてください。

  1. JDeveloperで、「ヘルプ」→「更新の確認」を選択します。更新の確認ウィザードが起動します。

  2. ウィザードの「ようこそ」ページで、「次へ」をクリックします。

  3. 「ソース」ページで「更新センターの検索」を選択し、そのセクションにリストされているすべての場所を選択します。「次へ」をクリックします。

  4. 「更新」ページで「Extension SDK」を選択します。「次へ」をクリックして、Extension SDKをダウンロードし、インストールします。

  5. サマリー・ページで「終了」をクリックします。Extension SDKファイルにアクセスするには、JDeveloperを再起動する必要があります。

    Extension SDKのヘルプは、JDeveloperのオンライン・ヘルプを開き、「JDeveloperの拡張」→「Extention SDKでJDeveloperを拡張」に移動して参照できます。

31.10 Javadoc情報の場所

JDeveloperオンライン・ヘルプには、この章で説明したクラスに関する説明がJavadocフォーマットで記載されています。

表31-2 Javadocの場所

クラス/インタフェース オンライン・ヘルプでのJavadocの場所

AbstractDefinition

AbstractImpl

AbstractAdapter

「リファレンス」→「Oracle ADF Model API Reference」→「Packages」→「oracle.adf.model.adapter」→「Class Summary」

StructureDefinition

「リファレンス」→「Oracle ADF Model API Reference」→「Packages」→「oracle.binding.meta」→「Interface Summary」

DataControl

ManagedDataControl

TransactionalDataControl

「リファレンス」→「Oracle ADF Model API Reference」→「Packages」→「oracle.binding」→「Interface Summary」


31.11 サポート・ファイルの内容

この項では、次のファイルの内容を示します。

31.11.1 sampleDC.xsd

例31-37に、sampleDC.xsdファイルの内容を示します。

例31-37 sampleDC.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://xmlns.oracle.com/adfm/adapter/test"
            xmlns="http://xmlns.oracle.com/adfm/adapter/test"
            elementFormDefault="qualified">
   <xsd:element name="Definition">
      <xsd:complexType>
         <xsd:attribute name="SourceLocation" type="xsd:string"/>
      </xsd:complexType>
   </xsd:element>
</xsd:schema>

31.11.2 CSVHandlerクラス

例31-38に、CSVHandlerクラスの内容を示します。

例31-38 CSVHandler

package oracle.adfinternal.model.adapter.sample;

import java.io.InputStream;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import oracle.binding.meta.DefinitionContext;
import oracle.binding.meta.StructureDefinition;

import oracle.adf.model.utils.SimpleStringBuffer;

import oracle.adf.model.adapter.AdapterException;
import oracle.adf.model.adapter.dataformat.AttributeDef;
import oracle.adf.model.adapter.dataformat.StructureDef;
import oracle.adfinternal.model.adapter.sample.CSVParser;
import oracle.adf.model.adapter.utils.Utility;

/**
 * Format handler for character separated values.
 * <p>
 * This class generates structures according to the JSR 227 specification from
 * a CSV data stream by parsing the data. The data types are guessed from the
 * value of the first data line. It can extract values from a CSV data stream
 * as well.
 * <p>
 * Data controls that deals with CSV data can use this class to generate data
 * and structure.
 *
 * @version 1.0
 * @since 10.1.3
 */
public class CSVHandler
{
  // stream containing the data.
  private InputStream mDataStream;

  // if the first row contains the names
  private boolean mIsFirstRowNames = false;

  // Encoding styles
  private String mEncStyle;

  // Character value separator
  private String mDelimiter;

  // Character used to quote a multi-word string
  private String mQuoteChar;

  // Column names
  private List mColNames = null;

  ////////////////////////////// Constructors //////////////////////////////////

  /**
   * Creats a CSV format handler object.
   *
   * @param is input stream that contains the CSV data.
   * @param isFirstRowNames flag to indicate if the first row of the CSV data
   *        can be treated as column names.
   * @param encodingStyle encoding style of the data.
   * @param delim character value separators.
   * @param quoteChar value that can be treated as quote.
   */
  public CSVHandler(
    InputStream is,
    boolean isFirstRowNames,
    String encodingStyle,
    String delim,
    String quoteChar)
  {
    mDataStream = is;
    mIsFirstRowNames = isFirstRowNames;
    mEncStyle = encodingStyle;
    mDelimiter = delim;
    mQuoteChar = quoteChar;
}


  ///////////////////// Impl of FormatHandler //////////////////////////////////

  /**
   * Returns the structure definition extracted for the data format.
   * <p>
   *
   * @param name name of the root structure.
   * @param ctx definition context information.
   * @return the structure information extracted.
   */
  public StructureDefinition getStructure(String name, DefinitionContext ctx)
  {
    StructureDef attrParent = null;
    try
    {
      CSVParser parser;

      if (mEncStyle == null)
      {
        parser = new CSVParser(mDataStream);
      }
      else
      {
        parser = new CSVParser(mDataStream, mEncStyle);
      }

      parser.setSeparators(mDelimiter.toCharArray());
      if (mQuoteChar != null && mQuoteChar.length() != 0)
      {
        parser.setQuoteChar(mQuoteChar.charAt(0));
      }

      // Get the column names
      Iterator colNames = getColNames(parser).iterator();

      // Create the structure definition
      attrParent = new StructureDef(name);

      // Parse the data to get the attributes
      if (mIsFirstRowNames)
      {
        parser.nextLine();
      }

      String[] vals = parser.getLineValues();
      if (vals != null)
      {
        int i = 0;
        while (colNames.hasNext())
        {
          String type = "java.lang.String";
          if (i < vals.length)
          {
            type = checkType(vals[i]);
            ++i;
          }
          AttributeDef attr =
            new AttributeDef((String) colNames.next(), attrParent, type);
          attrParent.addAttribute(attr);
        }
      }
      else
      {
        while (colNames.hasNext())
        {
          AttributeDef attr =
            new AttributeDef((String) colNames.next(),
                             attrParent, "java.lang.String");
          attrParent.addAttribute(attr);
        }
      }
    }
    catch (Exception e)
    {
      throw new AdapterException(e);
    }
    return attrParent;

  }


  /**
   * Returns the resulting data extracted from the input.
   * @param params parameters passed containig the context information.
   * @return <code>Iterator</code> of <code>Map</code> objects for the result.
   *         If no data found it can return null. The <code>Map</code>
   *         contains the value of attributes as defined in the data structure.
   *         For complex data, <code>Map</code>s can contain other iterator of
   *         <code>Map</code>s as well.
   */
  public Iterator getResult(Map params)
  {
    try
    {
      final CSVParser parser;
      if (mEncStyle == null)
      {
        parser = new CSVParser(mDataStream);
      }
      else
      {
        parser = new CSVParser(mDataStream, mEncStyle);
      }

      parser.setSeparators(mDelimiter.toCharArray());
      if (mQuoteChar != null && mQuoteChar.length() != 0)
      {
        parser.setQuoteChar(mQuoteChar.charAt(0));
      }

      final List cols = getColNames(parser);
      final boolean bEndOfData = (mIsFirstRowNames) ? !parser.nextLine() : false;
      //return the data iterator
      return new Iterator()
      {
        CSVParser _parser = parser;
        Iterator _colNames = cols.iterator();
        boolean _eof = bEndOfData;

        public void remove()
        {
        }

        public boolean hasNext()
        {
          return !_eof;
        }

        public Object next()
        {
            try
                {
                  if (_eof)
                  {
                    return null;
                  }

                  java.util.HashMap map = new java.util.HashMap(5);

                  // Create the current row as Map
                  String[] data = _parser.getLineValues();
                  int i = 0;
                  while (_colNames.hasNext())
                  {
                    String val = null;
                    if (i < data.length)
                    {
                      val = data[i];
                    }

                    map.put(_colNames.next(), val);
                    i++;
                  }

                  // get the next data line.
                  _eof = !_parser.nextLine();

                  return map;
            }
              catch (Exception e)
              {
                throw new AdapterException(e);
              }
            }

      };

    }
    catch (AdapterException ae)
    {
      throw ae;
    }
    catch (Exception e)
    {
      throw new AdapterException(e);
    }
  }


  //============================================================================
  // Class Helper Methods
  //============================================================================

   /**
    * Attempts to obtain the Java type from the string value.
    * @param data String value whose datatype has to be guessed.
    * @return Java type name.
    */
   private String checkType(String data)
   {
     try
     {
       // We first try to convert the value into a long number.
       // If successful, we will use long; if it throws NumberFormatException,
       // we will attempt to convert it to float. If this too fails, we return
       // string.
       if (data != null)
       {
         try
         {
           // Try to conver the value into an integer number.
           long numTest = Long.parseLong(data);
           return "java.lang.Long"; //NOTRANS
         }
         catch (NumberFormatException nfe)
         {
           // Try to convert the value into float number.
           float numTest = Float.parseFloat(data);
           return "java.lang.Float"; //NOTRANS
         }
       }
       else
       {
         return "java.lang.String"; //NOTRANS
       }
     }
     catch (NumberFormatException nfe)
     {
       // If conversion failed, we assume this is a string.
       return "java.lang.String";
     }
   }


  /**
   * Gets the column names.
   */
  /**
   * Gets the column names.
   */
  private List getColNames(CSVParser parser)
  {
    try
    {
      if (mColNames == null)
      {
        // Get the first row. If the first row is NOT the column names, we need
        // to generate column names for them.

        if (!parser.nextLine())
        {
          // No data found.
          // ToDo: resource
          new Exception("No data");
        }

        mColNames = new java.util.ArrayList(10);

        String[] cols = parser.getLineValues();
        if (mIsFirstRowNames)
        {
          makeValidColumnNames(cols);
          for (int i = 0; i < cols.length; i++)
          {
            mColNames.add(cols[i]);
          }
        }
        else
        {
          for (int i = 0; i < cols.length; i++)
          {
            String colName =
              new SimpleStringBuffer(20).append("Column").append(i).toString();
            mColNames.add(colName);
          }
        }
      }

      return mColNames;
    }
    catch (Exception e)
    {
      throw new AdapterException(e);
    }
  }


  /**
    * Make valid column names for all columns in CSV data source.
    *
    * This method applies the following rules to translate the given string
    * to a valid column name which can be accepted by EL:
    *
    * 1. If the first character of the string is digit,
    *    prefix the string with '_'.
    * 2. Translate any characters other than letter, digit, or '_'  to '_'.
    *
    *
    */
  private String[] makeValidColumnNames(String[] cols)
  {
    for (int i = 0; i <cols.length; i++)
    {
       // Trim out leading or ending white spaces
      if (cols[i] != null && cols[i].length() > 0)
      {
        cols[i] = cols[i].trim();
      }

      if (cols[i] == null || cols[i].length() == 0)
      {
         // Default as "column1", "column2", ... if column name null
        cols[i] = new SimpleStringBuffer("column").append(i+1).toString();
      }
      else
      {
        // Check special characters
        try
        {
          cols[i] = Utility.normalizeString(cols[i]);
        }
        catch (Exception e)
        {
           // On error, simply default to "columnX".
          cols[i] = new SimpleStringBuffer("column").append(i+1).toString();
        }
      }
    }
    return cols;
  }

}

31.11.3 CSVParser

例31-39に、CSVParserクラスの内容を示します。

例31-39 CSVParser

package oracle.adfinternal.model.adapter.sample;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;

import oracle.adf.model.utils.SimpleStringBuffer;

public final class CSVParser
{
  /////////////////////////////// Constants ////////////////////////////////////

  /** UTF8 encoding, used for hadling data in different languages. */
  public static final String UTF8_ENCODING = "UTF8";

  /** Quote character */
  private static char CHAR_QUOTE = '"';

  /** Comma (seperator) character */
  private static char CHAR_COMMA = ',';


  /////////////////////////////// Class Variables //////////////////////////////

  /**
   * CSV stream reader
   */
  private LineNumberReader mReader;

  /** Buffer to store one line of values.  */
  private ArrayList mValueArrayList = new ArrayList();

  /** Buffer to store one string value.  */
  private SimpleStringBuffer mValueBuffer = new SimpleStringBuffer(256);

  /** Current processed line.  */
  private String mLine = null;

  /** Current character position in the current line.  */
  private int mLinePosition = -1;

  /** Length of current line. */
  private int mLineLength = 0;

  /** If last character is comma. */
  private boolean mLastCharIsComma = false;

  /** Value separator character set. The separator can be one of these values.*/
  private char[] mSepCharSet = {CHAR_COMMA};

  /** Quote character. */
  private char mQuoteChar = CHAR_QUOTE;


  ////////////////////////////// Constructors //////////////////////////////////

  /**
   * Constructor
   *
   * @param pInputStream CSV input stream
   * @throws Exception any error occurred
   */
  public CSVParser(InputStream pInputStream) throws Exception
  {
    // If no encoding is passed in, use "UTF-8" encoding
    this(pInputStream, UTF8_ENCODING);
  }

  /**
   * Constructor
   *
   * @param pInputStream CSV input stream
   * @param pEnc character encoding
   * @throws Exception any error occurred
   */
  public CSVParser(InputStream pInputStream, String pEnc) throws Exception
  {
    if (pInputStream == null)
    {
      throw new Exception("Null Input Stream."); //TODO: Resource
    }

    mReader = new LineNumberReader(new InputStreamReader(pInputStream, pEnc));
  }

  ///////////////////////////// Public Methods /////////////////////////////////

  /**
   * Sets the separator characters as a list of possible separators for the
   * data. CSV data may have more than one separators. By default this parser
   * considers comma (,) as the data separator.
   * @param seps  Array of separator charactors.
   */
  public void setSeparators(char[] seps)
  {
    if ((seps != null) && (seps.length > 0))
    {
      mSepCharSet = seps;
    }
  }

  /**
   * Sets the quote character.
   * @param ch Quote character.
   */
  public void setQuoteChar(char ch)
  {
    mQuoteChar = ch;
  }

  /**
   * Moves to the next line of the data.
   * @return returns false if the end of data reached.
   * @throws Exception any error occurred
   */
  public boolean nextLine() throws Exception
  {
    setLine(mReader.readLine());
    if (mLine == null)
    {
      // End of file
      mValueArrayList.clear();
      return false;
    }

    parseLine();

    return true;
  }

  /**
   * Gets values of next line.
   * @return next line elements from input stream. If end of data reached,
   *         it returns null.
   * @throws Exception any error occurred
   */
  public String[] getLineValues() throws Exception
  {
    if (mValueArrayList.size() > 0)
    {
      String[] ret = new String[mValueArrayList.size()];
      return (String[]) mValueArrayList.toArray(ret);
    }

    return null;
  }



  //////////////////////////// Class Helpers ///////////////////////////////////

  /**
   * Checks if the character is a valid separator.
   */
  private boolean isSeparator(char ch)
  {
    for (int i = 0; i < mSepCharSet.length; i++)
    {
      if (ch == mSepCharSet[i])
      {
        return true;
      }
    }

    return false;
  }

  /**
   * Tests if end of line has reached.
   * @return true if end of line.
   */
  public boolean isEndOfLine()
  {
    // If last char is comma, must return at least one more value
    return (mLinePosition >= mLineLength) && (!mLastCharIsComma);
  }


  /**
   * Sets current line to be processed
   *
   * @param line the line to be processed
   */
  private void setLine(String line)
  {
    mLine = line;

    if (line != null)
    {
      mLineLength = line.length();
      mLinePosition = 0;
    }

  }

  /**
   * If next character is quote character
   *
   * @return true if next character is quote
   */
  private boolean isNextCharQuote()
  {
    if ((mLinePosition + 1) >= mLineLength)
    {
      // no more char in the line
      return false;
    }
    else
    {
      char ch = mLine.charAt(mLinePosition + 1);
      if (ch == mQuoteChar)
      {
        return true;
      }
      else
      {
        return false;
      }
    }
  }

  /**
   * Parse one line.
   *
   * @return values of the line
   * @throws Exception any error occurred
   */
  private void parseLine() throws Exception
  {
    mValueArrayList.clear();

    String[] values = null;
    String value = null;

    while (!isEndOfLine())
    {
      value = getNextValue();
      mValueArrayList.add(value);
    }
  }

  /**
   * Gets next value from current line.
   * @return next data value.
   */
  private String getNextValue() throws Exception
  {
    mLastCharIsComma = false;

    // Clean up value buffer first
    if (mValueBuffer.length() > 0)
    {
      mValueBuffer.setLength(0);
    }

    boolean insideQuote = false;
    boolean firstChar = true;
    boolean endValue = false;

    // Scan char by char
    while ((mLinePosition < mLineLength) && !endValue)
    {
      boolean copyChar = true;
      char ch = mLine.charAt(mLinePosition);

      // If first char
      if (firstChar)
      {
        // Only check quote at first char
        if (ch == mQuoteChar)
        {
          insideQuote = true;
          copyChar = false;
        }
        // Also need to check comma at first char
        else if (isSeparator(ch))
        {
          copyChar = false;
          endValue = true;
          mLastCharIsComma = true;
        }

        firstChar = false;
      }
      // Not first char but inside quote
      else if (insideQuote)
      {
        // Check end quote
        if (ch == mQuoteChar)
        {
          copyChar = false;
          // Two sucesstive quote chars inside quote means quote char itself
          if (isNextCharQuote())
          {
            mLinePosition++;
          }
          // Otherwise it is ending quote
          else
          {
            insideQuote= false;
          }
        }
      }
      // Not first char and outside quote
      else
      {
        // Check comma
        if (isSeparator(ch))
        {
          copyChar = false;
          endValue = true;
          mLastCharIsComma = true;
        }
      }

      if (copyChar)
      {
        mValueBuffer.append(ch);
      }

      mLinePosition++;
    }

    if (mValueBuffer.length() > 0)
    {
      return mValueBuffer.toString();
    }
    else
    {
      return null;
    }
  }

}