外部ソースのデータの管理

Curl 言語 API には RecordSet と外部ソースのデータを接続するメカニズムがあります。 データ ソースとしては、データ ベース サーバ、データ ベースとなるファイル グループ、 コンマ区切り値を含むファイルを使用できます。 CsvRecordSet も、(書式を変換するための) CSV ファイル、または固定幅カラムとしてフォーマット済みのデータ ファイルからデータをインポートできます。 CSV ファイルおよび FileConnection はバージョン 5.0 の新しい機能です。
外部ソースの詳細は 「 ファイルやその他のリソースへのアクセス 」をご覧ください。

レコード セットおよびデータ ファイルの使用

Curl 言語 にはファイル一式をデータベースとしてシミュレートする API が用意されています。
Curl 言語 には FileConnection をサポートするための API もあり、 ローカルに保存されている RecordSet を使って作業する手助けとなります。 この API には、データファイルを読み書きするためのクラスが用意されています。

データ ファイル接続の使用

接続ファイルの作成

FileConnection を使用するには、 ファイル ベースの接続をサポートするファイル一式を最初に作成する必要があります。 各ファイルは特別の機能を持ち、所定の構造でなければなりません。 全てのファイルは CSV 形式を使用します。 アプリケーションによって、このファイルは、最初に開発者が作成するもの、 管理者や IT スタッフが別の処置を加えたもの、 または全てのユーザが利用できるものとなります。 データ ベース記述子ファイルは、Excel のようなスプレッド シートを使用して作成できます。 また、アプレットにコードを入れて、(エンドユーザーまたはシステム管理者が) 必要とする時にデータ ベース記述子ファイル作成することもできます。
次に FileConnection を使用するために必要なファイルのリストを示します。
次の図は、このセクションの例で使われる具体的な値を用いる、 データ ベース記述子ファイルおよびテーブル記述子ファイルの構造を示しています。
データ ベース記述子ファイル (index.csv) の内容は次のとおりです。
Figure: データ ベース記述子ファイルの構造
テーブル記述子ファイル (task-index.csv) の内容は次のとおりです。
Figure: テーブル記述子ファイルの構造
接続ファイルは任意のツールで作成できます。 スプレッドシートを使用する場合は、ヘッダー行はカラム ヘッダーを提供する必要があります。 API は Curl アプレットで接続ファイルを簡単に作成することができます。
クラス定数 FileConnection.table-fields はデータ ベース記述子ファイルの構造を RecordFields オブジェクト使って定義します。 次のコードで示す構造は API ドキュメンテーションからコピーされています。
FileConnection.table-fields:RecordFields =
    {RecordFields 
        {RecordField 
            "database", 
            domain = String, 
            caption = "Database" 
        }, 
        {RecordField
            "table", 
            domain = String, 
            caption = "Table" 
        }, 
        {RecordField 
            "data-url", 
            domain = String, 
            caption = "Location" 
        }, 
        {RecordField 
            "fields-url", 
            domain = String, 
            caption = "Fields Location", 
            nullable? = true 
        }, 
        {RecordField 
            "header-line-count", 
            domain = int, 
            caption = "Header Lines" 
        }, 
        {RecordField 
            "character-encoding", 
            domain = String, 
            caption = "Encoding" 
        }, 
        {RecordField 
            "cached-fields", 
            domain = {TransientAnyDomain}, 
            caption = "Fields", 
            nullable? = true 
        } 
    }
クラス定値 FileConnection.column-fields はテーブル記述子ファイルの構造を RecordFields オブジェクトを使って定義します。

次のコードで示す構造は API ドキュメンテーションからコピーされています。
FileConnection.column-fields:RecordFields = 
    {RecordFields 
        {RecordField 
            "name", 
            domain = String, 
            caption = "Name", 
            index-type = RecordFieldIndexType.unique 
        }, 
        {RecordField 
            "caption", 
            domain = String, 
            caption = "Caption", 
            nullable? = true 
        }, 
        {RecordField 
            "domain", 
            domain = String, 
            caption = "Domain" 
        }, 
        {RecordField 
            "default-value", 
            domain = String, 
            caption = "Default", 
            nullable? = true 
        }, 
        {RecordField 
            "index-type", 
            domain = RecordFieldIndexType, 
            caption = "Index", 
            nullable? = true }, 
        {RecordField 
            "modifiable?", 
            domain = bool, 
            caption = "Modifiable?", 
            nullable? = true 
        }, 
        {RecordField 
            "nullable?", 
            domain = bool, 
            caption = "Nullable?", 
            nullable? = true } 
    }
アプレットを使ってデータ ベース記述子ファイルを作成する場合は、次の方法で進めます。
最初に、作成予定のデータ ベース記述子ファイルをポイントする url がある CsvRecordSet を作成します。 FileConnection.table-fields をフィールド パラメータとして渡し、header パラメータを使って1行のヘッダーを指定します。 RecordData オブジェクトはファイル レコードを提供します。 次に、FileConnection.column-fields を使用して、 同様の方法で各テーブル記述子ファイルの CsvRecordSet を作成します。 各レコード セットをコミットして、関連付けられている CSV 形式のファイルにデータを書き込みます。
次の例では、Curl アプレットで ファイル ベースの接続を作成するプロセスを示します。 接続は1つのテーブル (task) を含む 1つのデータ ベース (example) を定義します。 CsvRecordSet db-tables はデータベース記述子ファイル (connection.csv) を作成します。
CsvRecordSet task-fields はテーブル task のテーブル 記述子ファイルを作成します。db-tables で指定されているとおり、このファイル名は task-fields.csv です。
データを保存するファイル名は task.csv で、 db-tables で指定されているとおりです。 task-fields.csv の 3 つの RecordData オブジェクトは task.csv の 3 つのフィールドを定義します。
CsvDataWriter は、task-fields.csv のレコードを使って、 データ ファイル task.csv を作成し、カラム ヘッダーを作成します。
この例で作成されるファイルは IDE インストレーションの一部として、 次のロケーションで提供されています。
/.automount/gamera/local/releases6/releases/user/amori/jackson/trunk-3/curl-2008-03-25-004514/build/linux/docs/default/support/
この例は、接続ファイル名を入力するよう要求します。 例では、提供ファイルが既定ロケーションに置かれています。 別のファイルを使うこともできますが、choose-file は既存ファイルを指定するよう要求します。 データベース記述子ファイルには、任意の名前を指定できます。 (connection.csv が推奨名です。 ) しかし、テーブル記述子ファイルは task-fields.csv、 そしてデータファイルは task.csv と名前を付ける必要があります。 これは、例が作成する記述子ファイルにこれらの名前が指定されているためです。 次の内容の三つのファイルが結果となります。
データ ベース記述子ファイル (推奨名 connection.csv ) には次の内容が含まれています:
    database,table,url,fields-url,header-line-count,character-encoding
    example,task,task.csv,task-fields.csv,2,,
task-fields.csv には次の内容が含まれています:
    Name,Caption,Domain,Default,Index,Modifiable?,Nullable?,
    task,Task,string,(enter task),none,true,false
    assignee,Assignee,string,(assigned to),none,true,true
    date,Date,date,01/01/2006,none,true,true
task.csv には次の内容が含まれています:
    Created 2005-12-10 11:13:17.908999 -0500
    Task,Assignee,Date

例: データ ベース ファイルの作成
{import * from CURL.DATA-ACCESS.CONNECTED}

{define-proc {create-files index-url:Url, task-index-url:Url, task-url:Url}:void
    let fbuf:StringBuf = {StringBuf}
    let n:int = 0
    
    let db-tables:CsvRecordSet = 
        {CsvRecordSet.create
            index-url,
            FileConnection.table-fields,
            header = || FileConnection requires a one line header
                {StringArray "database,table,url,fields-url,header-line-count,character-encoding"},
            {RecordData
                database = "example",
                table = "task",
                data-url = "task.csv",
                fields-url = "task-fields.csv",
                header-line-count = 2
            }
        }
    let task-fields:CsvRecordSet = 
        {CsvRecordSet.create
            task-index-url,
            FileConnection.column-fields,
            header =  || FileConnection requires a one line header
                {StringArray "Name,Caption,Domain,Default,Index,Modifiable?,Nullable?,"},
            {RecordData
                name = "task",
                caption = "Task",
                domain = "string",
                default-value = "(enter task)",
                index-type = "none",
                modifiable? = true,
                nullable? = false
            },
            {RecordData
                name = "assignee",
                caption = "Assignee",
                domain = "string",
                default-value = "(assigned to)",
                index-type = "none",
                modifiable? = true,
                nullable? = true
            },
            {RecordData
                name = "date",
                caption = "Date",
                domain = "date",
                default-value = "01/01/2006",
                index-type = "none",
                modifiable? = true,
                nullable? = true
            }
        }
    {db-tables.commit}
    {task-fields.commit}
    {for r:Record in task-fields do
        {if n > 0 then
            {fbuf.append ','}
        }
        {fbuf.concat r["caption"] asa String}
        {inc n}
    }
    let new-file:CsvDataWriter = 
        {CsvDataWriter
            task-url,
            header = 
                {StringArray "Created " & 
                    {DateTime}.info.iso-full, {fbuf.to-String}}
        }
    {new-file.close}
}
{HBox
    {CommandButton
        label = "Create database files",
        {on Action do
            let index-url:#Url =  
                {choose-file
                    style = "edit",
                    default-location = 
                        {url "../../default/support/connection.csv"}
                }
            let task-index-url:#Url = 
                {choose-file
                    style = "edit",
                    default-location = 
                        {url "../../default/support/task-fields.csv"}
                }
            let task-url:#Url = 
                {choose-file
                    style = "edit",
                    default-location = 
                        {url "../../default/support/task.csv"}
                }
            {if (index-url == null or 
                 task-index-url == null or task-url == null) then
                {popup-message
                    "Cannot use null URL"
                }
             else
                {create-files 
                    index-url asa Url, 
                    task-index-url asa Url, 
                    task-url asa Url
                }
                {popup-message "Database files created"}
            }
        }
    }
}

接続の確立

サポート ファイルを作成後、ファイル接続を確立します。次の例は、 前の例で作成したファイルを使って FileConnection を作成します。その後、接続から情報を表示します。

例: データベースの内容を表示
{import * from CURL.DATA-ACCESS.CONNECTED}
{value
    let dbc:FileConnection = 
        {FileConnection {url "../../default/support/connection.csv"}}
    let vbox:VBox = {VBox spacing = 2pt}

    {VBox
        {CommandButton
            label = "Show database files",
            {on Action do
                {for db:String in {dbc.get-database-names} do
                    {vbox.add "database: " & {value db}}

                    {for tbl:String in {dbc.get-tables db} do
                        {vbox.add "table: " & {value tbl}}
                        {for col:RecordField in {dbc.get-fields db, tbl} do
                            {vbox.add "column: " & {value col.name}}                            }
                    }
                }            
            }
        },
        vbox
    }
}

RecordSet の作成

FileConnection を作成すると、接続記述子ファイルにリストされている任意のテーブルの ConnectedFileRecordSet を作成することができます。 メソッド FileConnection.create-record-set は、指定されたデータ ベース名およびテーブル名を含むクエリ文字列を利用して、レコード セットを作成します。 CSV 形式 ファイルは、データ ベース Connection で使用できるクエリよりも複雑なクエリはサポートしません。
次の例は、FileConnection.create-record-set を使って、接続の、 最初のデータ ベースの最初のテーブルのためのレコード セットを作成します。 この例は、3 つの RecordData オブジェクトをレコード セットに付加し、 RecordGrid 内に RecordSet を表示します。 付加されるレコードは、テーブル記述子ファイル (task-fields.csv) で定義される既定値を含むことに留意してください。
次のコードは例ではコメントに入っています。 このコードは ConnectedFileRecordSet コンストラクタを使用して同一のレコードセットを作成する別のアプローチを示します。
let rs:RecordSet = 
    {ConnectedFileRecordSet 
        dbc, 
        db, 
        tbl, 
        request-modifiable? = true
    }

例: RecordSet の作成
{import * from CURL.DATA-ACCESS.CONNECTED}

{let dbc:FileConnection = 
    {FileConnection 
        {url "../../default/support/connection.csv"}
    }
}
{let vbox:VBox = {VBox spacing = 2pt}}
{VBox
    {CommandButton
        label = "Create RecordSet",
        {on Action do
            {vbox.clear}
            let db:String = {dbc.get-database-names}[0]
            {vbox.add "database: " & {value db}}
            let tbl:String = {dbc.get-tables db}[0]
            {vbox.add "table: " & {value tbl}}
            let rs:RecordSet = 
                {dbc.create-record-set 
                    db, 
                    tbl, 
                    request-modifiable? = true
                }
||--                let rs:RecordSet = 
||--                    {ConnectedFileRecordSet 
||--                        dbc, 
||--                        db, 
||--                        tbl, 
||--                        request-modifiable? = true
||--                    }
            {rs.append {RecordData}}
            {rs.append {RecordData}}
            {rs.append {RecordData}}
            {vbox.add 
                {RecordGrid 
                    width = 7in, 
                    record-source = rs, height = 2in
                }
            }
        }        
    },
    vbox
}

DomainTable の作成と使用

データ接続ファイルは、レコード セットを記述する情報を含む全てのデータを、 カンマ区切りフィールド内でテキスト文字列として保存します。 テーブル記述子ファイルは、各フィールドのドメインをテキスト文字列で保存します。 レコード セットがデータを CSV ファイルに書き込む際、全てのデータ はテキスト文字列として表されます。 データがテキストデータ以外の場合 (例:数値、日付、列挙型)、 ファイル接続は、実際のデータに変換するために、どのように文字列を解析するかを知る必要があります。 接続は DomainTable を使ってこの解読を行います。 DomainTable はテキスト文字列とデータ ドメインの関連付けを記録します。 ファイル接続が、テーブル記述子ファイルのドメイン フィールドの文字列に境遇すると、 対応するドメインを使ってテーブル データ ファイルのデータを解析します。
ドメイン テーブルを指定しない場合、接続は一般的なデータ型をマップする default-domain-table を使用します。
次の例は、コードで定義されている 3 つの列挙型を含むドメイン テーブルを作成し使用します。 ドメイン テーブルは、テーブル データ ファイルで見つかったデータを正しく解析するため、接続を可能にします。 RecordGrid 内の結果となるレコード セットを閲覧すると、列挙型ドメインのフィールドは 利用可能な値を含むドロップ ダウンのリストを提示します。
この例は、接続からの情報を利用して、ユーザーが、接続で利用可能なデータベースを選択し、 そのデータ ベースからテーブルを選択する方法を示しています。

例: DomainTable の使用
{import * from CURL.DATA-ACCESS.BASE}
{import * from CURL.DATA-ACCESS.CONNECTED}

{define-enum Priority
    normal,
    high,
    low,
    hold
}
{let priority-domain:Domain = {new {EnumDomain-of Priority}}}

{define-enum Status
    unstarted,
    ongoing,
    done
}
{let status-domain:Domain = {new {EnumDomain-of Status}}}

{define-enum ExpenseType
    meal,
    transportation,
    other
}
{let expense-domain:Domain = {new {EnumDomain-of ExpenseType}}}

{let public constant expense-domains:DomainTable = 
    {DomainTable
        bool = {StandardBoolDomain},
        date = {StandardDateDomain},
        double = {StandardDoubleDomain},
        string = {StandardStringDomain},
        expense = expense-domain,
        priority = priority-domain,
        status = status-domain
    }
}
{value
    let display-width:Distance = 15cm
    let database-list-model:DefaultListModel = {DefaultListModel}
    let table-list-model:DefaultListModel = {DefaultListModel}
    let hb:HBox = {HBox}
    let vb:VBox = {VBox width = display-width}
    let rg-box:VBox = {VBox}
    let gb:GroupBox = {GroupBox label = "select database and table"}
    let title:String = ""
    
    {gb.add hb}
    {vb.add 
        {CommandButton
            label = "Run the Example",
            {on Action do
            let dbc:FileConnection = 
                {FileConnection 
                    {url "../../default/support/sample-connection.csv"},
                    domain-table = expense-domains
                }
                {vb.clear}
                {vb.add gb}
                {for db:String in {dbc.get-database-names} do
                    {database-list-model.append db}
                }
                let table-dropdown-list:DropdownList = 
                    {DropdownList prompt = "Select a table"}
                let database-dropdown-list:DropdownList = 
                    {DropdownList
                        prompt = "Select a database",
                        data-model = database-list-model,
                        {on ValueFinished do
                            {table-list-model.clear}
                            {rg-box.clear}
                            {for tbl:String in 
                                {dbc.get-tables database-dropdown-list.value asa String} do
                                {table-list-model.append tbl}
                            }
                            set table-dropdown-list.data-model = table-list-model
                            {table-dropdown-list.add-event-handler
                                {on ValueFinished do
                                    let rs:RecordSet = 
                                        {dbc.create-record-set 
                                            database-dropdown-list.value asa String, 
                                            table-dropdown-list.value asa String
                                        }
                                    {vb.clear}
                                    {rg-box.clear}
                                    {vb.add gb}
                                    set title = 
                                        database-dropdown-list.value asa String  & ": " 
                                    & table-dropdown-list.value asa String
                                    {rg-box.add 
                                        {text  
                                            font-size = 12pt, 
                                            font-weight = "bold", 
                                            {value title}
                                        }
                                    }
                                    {rg-box.add 
                                        {RecordGrid 
                                            record-source = rs asa #RecordSet,
                                            width = display-width, 
                                            height = 2in
                                        }
                                    }
                                    {vb.add rg-box}
                                }                    
                            }
                            {hb.add table-dropdown-list}
                        }
                    }
                {hb.add database-dropdown-list}
            }
        }
    }
    vb
}

ファイル接続の拡張例

簡単な Personal Information Manager (PIM) を実装する FileConnection API を使う拡張例は次のロケーションにあります。
/.automount/gamera/local/releases6/releases/user/amori/jackson/trunk-3/curl-2008-03-25-004514/build/linux/docs/default/examples/dguide/file-connection.zip
この .zip ファイルの使用に関しては 「拡張例」を参照してください。

CSV データ ファイルの使用

CsvRecordSet の使用

Curl 言語では、CSV 形式のデータ ファイルを直接使う作業を簡単にする下位レベル API が提供されてます。 CsvRecordSetRecordSet のサブクラスで、CSV 形式のデータ ファイルを読み書きします。 ユーザーは、データ構造を定義する RecordFields オブジェクトを提供できます。 この場合、CsvRecordSet は、対応する RecordField で指定された Domain において、データファイルの各フィールドの解析を試みます。 ファイルの文字列データが適切な型のオブジェクトに変換しない場合はエラーがスローされます。 DomainDetector.get-fields を使用して、CSV ファイル データに基づく RecordFields オブジェクトを生成することもできます。 「DomainDetector の使用」を参照してください。
次の例は、データを CSV ファイルから CsvRecordSet へ読み込み、RecordForm に表示します。

例: CsvRecordSet を使用したデータファイルの読み込み
{import * from CURL.DATA-ACCESS.BASE}
{import * from CURL.DATA-ACCESS.CONNECTED}

{value
    let vb:VBox ={VBox}
    {vb.add 
        {CommandButton
            label = "Run the Example",
            {on Action do
                let maritime-signal-flags:CsvRecordSet =
                    {CsvRecordSet
                        {url "../../default/support/flag-data.csv"},
                        fields = 
                            {RecordFields
                                {RecordField 
                                    "letter", caption = "Letter", domain = any,
                                    index-type = RecordFieldIndexType.unique
                                },
                                {RecordField 
                                    "phonetic", caption = "NATO Phonetic",domain = String
                                },
                                {RecordField 
                                    "flag", caption = "Flag",
                                    domain = String
                                }
                            } 
                    }
                let rv:RecordView = 
                    {RecordView
                        maritime-signal-flags,
                        sort = "letter"
                    }
                {vb.clear}
                {vb.add
                    {RecordForm
                        record-source = rv,
                        {VBox
                            {TextDisplay
                                {bind value to "letter"}
                            },
                            {TextDisplay
                                {bind value to "phonetic"}
                            },
                            {Frame
                                height = 42px,
                                width = 53px,
                                {bind background to "flag",
                                    {format data:String as
                                        {if data != "" then
                                            {url data}
                                         else
                                            DataBinding.unset
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }  
        }
    }
    vb
}

CSV データの読み書き

CsvDataReader および CsvDataWriter クラスは CSV 形式のファイルのレコードを読み書きします。 次の例は CSV ファイルからデータを読み込み Table に表示します。

例: CsvDataReader を使用したデータファイルの読み込み
{import * from CURL.DATA-ACCESS.BASE}
{import * from CURL.DATA-ACCESS.CONNECTED}

{let display:Table = 
    {Table
        border-width=1pt, border-color="black",
        cell-border-width = 1pt,
        cell-border-color="silver",
        columns = 4
    }
}

{value
    let vb:VBox ={VBox}
    {vb.add 
        {CommandButton
            label = "Run the Example",
            {on Action do
                {let csv-reader:CsvDataReader = 
                    {CsvDataReader
                        {url "../../default/support/person-data.csv"}
                    }
                }
                {let values:StringArray = {StringArray}}
                {let first-row:bool = true}
                {while {csv-reader.read-record out = values} != null do
                    {if first-row then
                        {for ci = 0 below values.size do
                            {display.add {text font-weight = "bold", {value values[ci]}}}
                        }
                        set first-row = false
                     else
                        {for ci = 0 below values.size do
                            {display.add values[ci]}
                        }
                    }
                }
                {csv-reader.close}
            }
        }
    }
    {VBox
        vb,
        display
    }
}

DomainDetector の使用

DomainDetector は CSV データ ファイルの各フィールドの適切なドメインを検証するためのクラスです。 DomainDetector.domains プロパティは Domain の配列です。 DomainDetector.get-fields メソッドは、 url 引数で指定される CSV ファイルの 1 行の各フィールドを検証します。 配列の各 Domain に対し、Domain.parse に基づいて、 そのフィールドを解析します。 フィールドの解析が成功すると、次のフィールドに移動します。
DomainDetector は、Domain を配列に置かれている順に検証します。 Domain 配列を指定しない場合は、 DomainDetector.default-domains が使用されます。 この既定の配列には、最も一般なデータ型が含まれます。 ドメイン配列を作成する場合、解析の間違いが発生しない順番でドメインを追加する必要があります。 例えば、CSV ファイルの全てのデータは文字列として解析されるため、 StandardStringDomain は最後に配置する必要があります。
次の例は、既定のドメイン配列を使って CSV ファイルのフィールドを解析します。 DomainDetector.get-fields を使って、 ファイルのデータをロードする CsvRecordSet の構造を定義する RecordFields オブジェクトを作成します。 例はその後、レコード グリッドのレコード セットを表示します。

例: DomainDetector を使ってデータ構造を調べる
{import * from CURL.DATA-ACCESS.BASE}
{import * from CURL.DATA-ACCESS.CONNECTED}

{let detect-it:DomainDetector = {DomainDetector}}

{value
    let vb:VBox ={VBox}
    {vb.add 
        {CommandButton
            label = "Run the Example",
            {on Action do
                let rec-set:CsvRecordSet =
                    {CsvRecordSet
                        {url "../../default/support/domains.csv"}, 
                        header-line-count = 1,        
                        fields = 
                            {detect-it.get-fields 
                                {url "../../default/support/domains.csv"},
                                header-line-count = 1
                            }
                    }
                let rg:RecordGrid = 
                    {RecordGrid
                        record-source = rec-set
                    }
                
                {vb.add rg}
            }
        }
    }    
    vb
}

データベースからレコード データを取得

CURL.DATA-ACCESS.CONNECTED パッケージでエクスポートされる API を使って、データベース サーバーに接続する RecordSet を作成できます。Curl® 統合開発環境には基本データベース接続サーバーが含まれており、Apache TomcatJBossResin® などの標準 Java サーブレット エンジンで稼動します。サーブレット コンテナのほかに、JDBC ドライバ搭載のデータベースが必要です。
接続レコードセットは 2 つの手順で作成します。最初に BasicConnection オブジェクトを作成し、Connection.create-record-set メソッドを呼び出します。接続が確立したら、任意の RecordSet と同じ方法で ConnectedRecordSet を使用します。レコードセットが変更可能で、データベース サーバーが変更を許可する場合は、ConnectedRecordSet への変更をコミットするとデータベース サーバーのデータが更新されます。
ConnectionConnectedRecordSet クラスは抽象インターフェイス クラスです。上級の開発者の方はこれらをサブクラス化して、他の種類のデータベース サーバーに接続するカスタム実装を作成してください。Curl IDE が提供する接続プロトコルは BasicConnectionBasicConnectedRecordSet クラスで実装され、さらに ConnectedField の各種サブクラスもこれを実装しています。この実装のソース コードは Curl IDE の次のディレクトリにあります。
/.automount/gamera/local/releases6/releases/user/amori/jackson/trunk-3/curl-2008-03-25-004514/build/linux/ide/data-access/connected
このコードは、特別な実装を独自に開発する際にモデルとして使用できるよう提供されているものです。

基本データベース サーバー

ConnectedRecordSet を使用するにはデータベース サーバーが必要です。このセクションでは、Apache Tomcat をサーブレット エンジン、mySQL をデータベース エンジンとして、Curl 統合開発環境に含まれているサーバーを Windows にインストールする方法について簡単に説明します。
バージョン 6.0の Curl API では Oracle データベースと、UTF-8 を使用してエンコードしたデータベースでの外国語の文字列のサポートを追加しました。
最初のステップは、Apache Jakarta Project から Apache Tomcat をダウンロードしてインストールすることです。以下の情報は、バージョン 5.5.23 に基づいています。
さらに、データベース サーバーとこれに対応する JDBC ドライバも必要です。これには、たとえば mySQL データベース エンジンとその JDBC ドライバ を使用できます。
以下の説明は、mySQL と Apache Tomcat が既定の場所にインストールされていることを前提にしています。これらのインストールが完了したら、Curl データベース接続サーブレットをインストールし、JDBC ドライバを適切な場所にコピーし、Apache Tomcat を構成して実行します。

サーブレット エンジンの構成

Apache Tomcat の構成は簡単ないくつかのステップに沿って設定します。Apache の規則にしたがって、$CATALINA_HOME は Apache がインストールされているディレクトリを参照するのに使用されます。Windows では既定の場所は C:\Program Files\Apache Group\Tomcat 5.5 です。
  1. JDBC ドライバを適切な Tomcat のディレクトリに置いてください。次のディレクトリが使用できます。$CATALINA_HOME/common/lib (TomCat 6 では $CATALINA_HOME/lib)
    適切な場所の選択についての詳細は、Apache Tomcatの「Tomcat Classloader HOWTO」を参照してください。
  2. Curl IDE のインストール ディレクトリから Tomcat webaapsディレクトリ $CATALINE_HOME/webappsに Curl Database Connection (CDBC) サーブレットの Web アーカイブ (.war) ファイルをコピーします。CDBC war ファイルは次の場所にあります。/.automount/gamera/local/releases6/releases/user/amori/jackson/trunk-3/curl-2008-03-25-004514/build/linux/ide/data-access/jdbc-server/cdbc/cdbc-server.war
  3. 以下に示されているように Tomcat conf ディレクトリにある server.xml ファイルを編集してください。
  4. 以下に示されているように $CATALINA_HOME/conf/Catalina/localhost/cdbc-server.xml ファイルを作成してください。
  5. Tomcat サーバーを停止し再起動してください。
cdbc-server サーブレットは JNDI を使って JDBC ドライバの場所を見つけます。Tomcat 5.5 または 6.0 では、$CATALINE_HOME/conf/server.xmlにある Tomcat サーバーの構成ファイルに、以下を参照してコードを追加します。以下に示されているように、GlobalNamingResources 要素内に3つの Environment 要素と Resource 要素を追加します。
Tomcat 5.5 または 6.0の場合
    <!-- CDBC configuration -->
    <Environment name="cdbc/database"
        type="java.lang.String"
        value="mysql"
    />

<Environment name="cdbc/transaction-control" type="java.lang.String" value="mysql" />

<Environment name="cdbc/table-type" type="java.lang.String" value="TABLE,VIEW,SYNONYM" />

<Resource name="cdbc-mysql" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" driverClassName="org.gjt.mm.mysql.Driver" url="jdbc:mysql://localhost/cdbc_test?useUnicode=true&amp;characterEncoding=utf-8" username="your_cdbc_user" password="your_password" maxActive="20" maxIdle="10" />
ここでは以下のパラメーターの設定ができます。
最初に設定するパラメーターは cdbc/database です。CDBC サーブレットで使用するデータベースによって、値は "mysql" または "oracle" となります。JDBC ドライバを構成するのに使われるリソースを選択するのに使用され、"cdbc-mysql" または "cdbc-oracle" となります。他の値を使用して、対応する server.xml ファイル内の Resource 要素や cdbc-server.xml ファイル内の ResourceLink 要素を指定することもできます(以下を参照)。指定されない場合、既定値は "mysql" で、JDBC ドライバの構成には "cdbc-mysql" リソースが使用されます。
cdbc/transaction-control リソースは "mysql"、 "jdbc"、および "none" といった値を持つ可能性のある文字列です。値には次のような意味があります。
cdbc/table-type リソースはカンマ区切りのテーブル型のリストをもつ文字列で CDBC コネクションを通じて表示されます。TABLEVIEW、および SYNONYM が選べます。指定されない場合は、すべての型が返されます。
"cdbc-mysql" と呼ばれるリソースは "mysql" がデータベース サーバーの時に JDBC コネクションのパラメーターを与えます。url は jdbc:mysql://<host>/<database> というフォームです。 host はデータベース サーバーのホストネームです。 database の名前は既存のどのデータベースの名前でもかまいません。JDBC API は実行時にどのデータベースでも選択でき、ここで与えられる実際のデータベースの名前はそれが存在する限り重要ではなく、指定されたユーザー名にアクセス可能です。
このサンプルの設定では、文字フィールドでの unicode 使用、さらに、データベースでの UTF-8 エンコーディングの使用の許可をリクエストするために、2 つの特別なパラメータが JDBC ドライバにパスされていることに注意してください。 あなたのアプリケーションが非 ASCII 文字をデータベースに保存する必要がある場合、JDBC ドライバのドキュメンテーションを参照し、類似のパラメータがサポートされているかチェックしてください。
次のコンテンツを持つ $CATALINA_HOME/conf/Catalina/localhost/cdbc-server.xml ファイルを作成してください。CDBC サーブレットが使用可能な server.xml ファイルからバインディングします。既に存在していない場合は Catalina/localhost ディレクトリを作成しなければならないことに注意してください。

    <Context path="/cdbc-server" reloadable="false">

<Logger className="org.apache.catalina.logger.SystemOutLogger" verbosity="4" timestamp="true"/>

<ResourceLink name="cdbc/transaction-control" global="cdbc/transaction-control" type="java.lang.String" />

<ResourceLink name="cdbc/table-type" global="cdbc/table-type" type="java.lang.String" />

<ResourceLink name="jdbc/cdbc" global="cdbc-mysql" type="javax.sql.DataSource" />

<ResourceLink name="jdbc/cdbc-mysql" global="cdbc-mysql" type="javax.sql.DataSource" />

<ResourceLink name="jdbc/cdbc-oracle" global="cdbc-oracle" type="javax.sql.DataSource" />

<ResourceLink name="cdbc/default-schema/oracle/en" global="cdbc/default-schema/oracle/en" type="java.lang.String" />

<ResourceLink name="cdbc/default-schema/oracle/ja" global="cdbc/default-schema/oracle/ja" type="java.lang.String" />

</Context>
すべてが適切にセットアップされていることを確認するには、指定されたユーザーネームとパスワードでログインしてmysql コマンドライン クライアントを開始することで簡単にチェックできます。
    C:\>mysql --user cdbc_user -p
    Enter password: ********
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 9
    Server version: 5.0.37-community-nt MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> connect cdbc_test Connection id: 10 Current database: cdbc_test

mysql> quit Bye
Tomcat を起動します。Web ブラウザで次の場所を参照します。
http://localhost:8080/cdbc-server/CdbcServlet
(ここでは、Tomcat がポート 8080 でリクエストを受信していると仮定しています。) 次のような出力が表示されるはずです。
This is class com.curl.cdbc.CdbcServlet 
Sessions: 1 
Servlets: 1 
Init param:null 
op=null 

CDBC 1.1.0 2007-05-01 0000
これは、クエリ パラメータが存在しない場合にサーブレットが生成する出力です。
サーブレットが実行していて正しくデーターベースに接続されていることを確認するために、 次のクエリをブラウザに入力してアウトプットを検証してください。
http://localhost:8080/cdbc-server/CdbcServlet?op=getdbinfo
データーベースのカタログ名およびその他のデータベース属性がこのクエリから返されます。
BasicConnection のコードおよび関連するクラスのソースコードは、 IDE と共に、/.automount/gamera/local/releases6/releases/user/amori/jackson/trunk-3/curl-2008-03-25-004514/build/linux/ide/data-access/connected 内にインストールされています。必要に応じてそれを変更することができます。

ConnectedRecordSet の作成と使用

接続レコードセットのインターフェイスは、ConnectionConnectedRecordSet の 2 つの抽象クラスで定義されています。実際には、ConnectionBasicConnection のサブクラスをインスタンス化して、その create-record-set メソッドを使い BasicConnectedRecordSet を作成します。
BasicConnection コンストラクタの唯一のパラメータは URL です。前述のセクションのテスト サーバー設定の場合、この URL は http://localhost:8080/cdbc-server/CdbcServlet になります。
ConnectedRecordSetRecordSet のサブクラスで、ほとんどの API と動作を共有しています。ただし、これにレコードを直接追加するのではなく、そのプロパティを使って CDBC データベース サーバーからのポピュレートを実現します。最も重要なプロパティは次のとおりです。
size-limitrequest-modifiable? パラメータにより、サイズ制限や ConnectedRecordSet が変更可能かどうかの指定もそれぞれ可能です。
接続レコードセットを作成して表示するには、次のようなコードを使用できます。
{import * from CURL.DATA-ACCESS.BASE}
{import * from CURL.DATA-ACCESS.CONNECTED}
{let connection:BasicConnection = 
    {BasicConnection {url "http://localhost:8080/cdbc-server/CdbcServlet"}}
}
{RecordGrid
    record-source={connection.create-record-set "example","employee"}
}
ConnectedRecordSet を作成するファクトリー メソッド create-record-set を提供するほかに、Connection クラスはサーバーにあるアクセス可能なデータベースやテーブルに関する情報も提供することができます。したがって、利用可能なデータ テーブルを調べるためのアプレット作成も可能です。すべての API に関する詳細は API マニュアルを参照してください。