ログ出力
Log4jやcommons loggingのようなロギング機能です
initialize-logプロシージャで、ロギング機能の設定をセットします。そのあと、以下のように利用します。
def logger = {LogFactory.get-log}
{logger.fatal “致命的エラーです。”} {logger.error “エラーです。”} {logger.warn “ワーニングです。”} {logger.info “情報です。”} {logger.debug “デバッグです。”} {logger.trace “トレースです。”} |
ログ・ローテーション
rotate-logプロシージャを利用して、Apache LogRotateのように、ローテーションができます。
詳細については、Curlドキュメンテーションを参照ください。
パッケージ名:COM.CURLAP.LIB.LOGGING
environment-switch
これは、開発時、テスト時、本番時ごとに処理を変えたい場合に、切り替えることのできるマクロです。
例えば下記の例は、”development”, “test”, “production”という環境ごとにincludeするファイルを変更したい場合に以下のようにコーディングできます。
{environment-switch case “development” do {include “foo-dev.scurl”} case “test” do {include “foo-test.scurl”} case “production” do {include “foo.scurl”} else } |
全体の設定として、”development”, “test”, “production”を指定するには、manifest.mcurlファイルにx-environmentというキーワードを記述します。
{curl 6.0 manifest} {manifest TESTS, x-environment = “development” } |
この例ですと、”development”というモードで稼動しますので、environment-switchの”development”が実行され、”foo-dev.scurl”がincludeされます。
ちなみに、”development”, “test”, “production”などは、任意の文字列が指定できます。
パッケージ名:COM.CURLAP.LIB.ENVIRONMENT
キャッシング機能
javaで有名なJCacheやEHCacheなどのように、クライアントでのキャッシングができます。これらは、例えばほとんど変わらないマスタデータを毎回サーバに取得するのではなく、一定期間、メモリもしくはディスクにキャッシングしておき、サーバ負荷を軽減するために利用できます。
まずは、キャッシュという1つの塊をCacheManager.create-cacheメソッドにて作成します。このとき、キャッシュ内の各オブジェクトの生存期限、キャッシュの最大数などを指定できます。最大数を越えた場合は、一番アクセスされていないオブジェクトを破棄します。
|| キャッシュの作成 def cm = {CacheManager.get-instance} def cache1 = {cm.create-cache “cache1”, max-elements-in-cache = 3, expire-idle-time = 1s } || キャッシュ”cache1”にオブジェクト登録 {cache1.set “k1”, {Array}} {cache1.set “k2”, {HashTable}} {cache1.set “k3”, 10}
|| キャッシュからオブジェクト取得 def v = cache1[“k1”] |
メモリ上にあるキャッシュをディスクへ書き出すには、キャッシュ作成時にpersistent-disk引数にURLを指定しておくと、flushメソッドを実行した場合にディスクへ書き出します。
def cm = {CacheManager.get-instance} def cache = {cm.create-cache “disk-cache”, persistent-disk = {url “file/disk.cache”}} set cache[“k1”] = “val1” set cache[“k2”] = “val2” {cache.flush} || persistent disk |
もうちょっと簡単にキャッシュを利用するために、with-cacheマクロが利用できます。このマクロは、もしキャッシュ内にオブジェクトがなければ、with-cacheの中身が実行され、結果がキャッシュへ格納され、戻り値を返します。キャッシュ内にオブジェクトがある場合、キャッシュから取得した値を戻します。
def v1 = {with-cache “k1” of “cache1” do def v = “test” v } |
パッケージ名:COM.CURLAP.LIB.CACHING
ほとんどのアプリケーションで利用されるメッセージ・リソースファイルのためのAPIです。
このAPIでは、メッセージを管理し、アプリケーション内からメッセージを取得することができます。以下にメッセージAPI(MessageList)のサンプルを掲載しておきます。
|| メッセージ定義(通常はメッセージファイルとして管理) def messages = {MessageList “MSG01”, “あいうえお”, “MSG02”, “Hello %s!” }
|| “あいうえお”が取得できます。 {messages[“MSG01”].create-message}
|| Hello Curl!が取得できます。 {messages[“MSG02”].create-message “Curl”}
|
詳細は、COM.CURLAP.LIB.MESSAGESパッケージを参照してください。
コンテナからコントロールの検索
あるコンテナ上からその下にあるコントロール(TextField, TextArea, ComboBoxなど)やコンテナ(Frame, Canvas, VBox, HBoxなど)を検索することができます。
def root = {Frame {VBox {TextField name=”name1″, value=”value1″}, {TextField name=”name2″, value=”value2″}, {Frame {VBox {TextField name=”name3″}, {TextArea name=”name4″, value=”value4″}, {TextField value=”value5″} } } } }
{walk-graphics || 第1引数: 検索対象のコンテナ root, || 第2引数: Graphic(コンテナやコントロール)ごとに、以下のプロシージャが実行される || 以下のサンプルでは、GraphicがValueControlの場合に、valueをコンソールに表示している例 {fn g => {if g isa ValueControl then def v = g asa ValueControl {dump v.name, v.value-as-any} } } } |
データクラスから各コントロールに一度に値をセットすることができます。これにはset-values-to-contorlsプロシージャを利用します。下記の例では、Fooクラスから、フィールド名がコントロールのnameが一致するものへ値をセットしています。
set-values-to-controlsのset-value-proc引数は、nameが一致しない場合や、コントロールのvalueとデータクラスのフィールドの型が一致しない場合に、変換ロジックを記載できるものです。
def tf1 = {TextField name=”tf-1″} def tf2 = {TextField name=”tf-2″} def tf3 = {TextField name=”tf-3″} def tf4 = {TextField} def tf5 = {TextField name=”no-name”} def tf6 = {TextField name=”tf-1″}
def td = {TextDisplay name=”td”} def df = {DateField name=”df”} def cb = {CommandButton name=”cb”} def root-graphic = {VBox {HBox tf1, tf2, tf3}, {HBox td, tf4, tf5, tf6}, df, cb } || set values of graphic {set-values-to-controls {Foo}, root-graphic, set-value-proc = {fn v, p, c => {if p.name == c.name then {if-non-null value = {p.get-value v} then set c.value-as-any = {if p.type == int and c.value-type == String then (value * 3) & “” else value } } } } }
|
逆に、Fooオブジェクトからコントロールへ値をセットするには、set-values-from-controlsを使用します。
パッケージ名:COM.CURLAP.LIB.UI
数学関数のAPIです
以下は最大公約数、最小公倍数のサンプルです。
def (a,b,c) = (3,12,24) {gcd a,b,c} == 3
def (a,b,c) = (2,3,12) {lcm a,b,c} == 12
|
パッケージ名:COM.CURLAP.LIB.MATH
都道府県ユーティリティ
都道府県の操作ができるユーティリティです。以下はサンプルとなります。
{get-japanese-prefecture-from-prefecture-code “40”}.name || “福岡県”
{get-japanese-prefecture-from-prefecture-code “40”}.capital-city || “福岡市”
{get-japanese-name-from-prefecture-code “40”} || “福岡県”
{get-japanese-prefectures-from-area “九州”}.size || 8 |
パッケージ名:COM.CURLAP.LIB.JAPAN
郵便番号を操作するユーティリティ
これを利用するには、日本郵便のページから郵便番号CSVをダウンロードして利用します。from-csvでダウンロードしたCSVデータを取り込みます。
def pcs = {PostalCodes.from-csv {url “file/postal-data/13TOKYO.CSV”}, {url “file/postal-data/09TOCHIG.CSV”} } || 検索 pc = {pcs.search-by-postal-code “1000004”}
|
パッケージ名:COM.CURLAP.LIB.JAPAN
オブジェクトの保存・読み込み
オブジェクトをファイルに保存することができます。また、もとに戻すこともできます。
let src:#HashTable = {HashTable “key1”, 10, “key2”, 20, “key3”, {DateTime}} def obj-url = {url “file/obj.bin”}
|| 保存 {save-object-to-url obj-url, src}
|| 読み込み def dst = {read-object-from-url obj-url} asa HashTable
|
パッケージ名:COM.CURLAP.LIB.IO
RecordSetのファイル保存・読み込み
RecordSetをファイルに保存、また、そのデータを読み込みすることができます。
def record = {RecordSet {RecordFields {RecordField “c1”, domain = int, index-type = RecordFieldIndexType.unique}, {RecordField “c2”, domain = String}, {RecordField “c3”, domain = DateTime} }, {RecordData c1 = 1, c2 = “v1”, c3 = {DateTime}}, {RecordData c1 = 2, c2 = “v2”, c3 = {DateTime}}, {RecordData c1 = 3, c2 = “v3”, c3 = {DateTime}}, {RecordData c1 = 4, c2 = “v4”, c3 = {DateTime}}, {RecordData c1 = 5, c2 = “v5”, c3 = {DateTime}} } def path = “file/record.bin” {save-record-set-to-url {url path}, record} def restore = {read-record-set-from-url {url path}} |
パッケージ名:COM.CURLAP.LIB.IO
DirectoryUtil
ディレクトリやファイルの検索を簡単にできる便利ツールです。
|| search by name def r1 = {DirectoryUtil.search-by-name {url “file”}, || directory “a-1.txt”, recurse? = true } || search by proc def r2 = {DirectoryUtil.search {url “file”}, || directory {proc {u:Url}:bool def name = u.filename {return name == “c-1.txt” or name == “test1”} }, recurse? = true } |
パッケージ名:COM.CURLAP.LIB.IO
if-local-appletマクロ
アプレットがローカルで起動されたかどうかに基づく条件付コンパイルを行います。
{if-local-applet {output “local”} else {output “remote”} } |
パッケージ名:COM.CURLAP.LIB.ENVIRONMENT
create-tableマクロ
CurlのRecordSetを定義するには、長いコードを記述しなければなりません。そこで、簡単に、かつSQLのCREATE TABLE文に似た構文でRecordSetを定義することができるマクロを用意しています。
def rs = {create-table col1 String not null, col2 int, col3 DateTime NOT NULL, col4 {StandardStringDomain}, col5 , || any col6 not null || any } |
これは以下のものに相当します。
def rs = {RecordSet {RecordFields {RecordField “col1” domain = String, nullable? = false}, {RecordField “col2” domain = int}, {RecordField “col3”, domain = DateTime, nullable? = false}, {RecordField “col4”, domain = {StandardStringDomain}, {RecordField “col5”}, || any {RecordField “col6”, nullable? = false} || any } }
|
パッケージ名:COM.CURLAP.LIB.DATA-ACCESS
メッセージダイジェスト
メッセージダイジェスト(SHA-1, MD5)を利用できます。以下のようにsha-1もしくはmd5プロシージャを実行することで、暗号化された文字列を取得できます。
def str = {sha-1 “abcd1234”} def str = {md5 “abcd1234”} |
またバージョン0.7から、SHA-1については、HMACにも対応しています。これにはhmac-sha-1プロシージャを利用してください。
将来的に、SHA-256,SHA-512などにも対応していく予定です。
秘密鍵暗号
秘密鍵暗号(トリプルDES、RC2、RC4)を利用できます。encrypt-with-common-keyで暗号化でき、decrypt-with-common-keyで複合化できます。
|| 暗号化 {encrypt-with-common-key ”key1234″, || かぎ “this is a text.”, || メッセージ {write-open-byte {url secret-file}} || OutputStream(書き出し先) }
|| 複合化 def result = {decrypt-with-common-key “key1234”, || かぎ {read-open-byte {url secret-file}} || InputStream 読み込み元 }
|
パッケージ名:COM.CURLAP.LIB.CRYPTO
hex-encode / hex-decode
これは、16進数のバイト列から文字列へエンコード、文字列から16進数のバイト列にデコードするユーティリティです。
{hex-encode {ByteVec 11, 7, 10}} || == “0b070a” {hex-encode {ByteVec 255, 7, 10}} || == “ff070a” def b = {hex-decode “0b070a”} || b[0] == 11 || b[1] == 7 || b[2] == 10 |
パッケージ名:COM.CURLAP.LIB.CODEC
with-busy-viewマクロ
CommandButtonの2度押し防止をするためのマクロです。以下のサンプルのようにvというView内で、with-busy-view内に記述された処理が実行されている間は、CommandButtonがdisableとなり、押下することができません。
let v:View = ….. {with-busy-view v do {for i:int = 0 below 100000 do {output “押せない!!”} } }
|
パッケージ名:COM.CURLAP.LIB.UI
Propertiesクラス
javaのpropertiesファイル形式を取り扱うためのクラスです。
hello.english=abcde hello.test1= hello.test2=jdbc.abc%s %d hello.test3=jdbc.abc%s %d
|
def props = {Properties} {props.load {read-open {url “file/properties/resource_ja.properties”}}} props.size ||== 4 props[“hello.english”] ||== “abcde”
|
パッケージ名:COM.CURLAP.LIB.UTIL
stop-watchマクロ
stop-watchマクロを利用することで、stop-watchマクロ内のブロックのある処理からある処理までの実行速度を計測することができます。
{stop-watch finish-proc = {proc {elapsed-time:Time}:void {output “elapsed time=” & elapsed-time} } do {for i = 0 below 100000 do {output “i = ” & i} } }
|| もしくはfinish-procを省略 {stop-watch do {for i = 0 below 100000 do {output “i = ” & i} } } }
|
上記結果は、「elapsed time=10s」のように出力されます。また、finish-procを省略できます。省略した場合は、実行時間のみコンソールに表示されます。
パッケージ名:COM.CURLAP.LIB.UTIL
Advanced UIで提供されているオートコンプリートのAPIを利用して、VLEで利用できるようにしました。
まずは以下のファイルをダウンロードしてください。
vle-auto-complete.zip
ファイルを適当な場所に配置して解凍すると、以下のファイルが格納されています。
- autocomplete.gif
- autocomplete_blue.gif
- autocomplete_red.gif
- autocomplete_s.gif
- autocomplete_s_blue.gif
- autocomplete_s_red.gif
- AUTOCOMPLETE.scurl
- vle-auto-complete.scurl
次にCurl IDEを起動し、「ツール」から「ビジュアル レイアウト エディタ」を選択します。するとVLEが起動しますので、「表示」⇒「パレット機能拡張」を選択してください。すると「パレット機能拡張」というダイアログが表示されますので、『新規』ボタンを押下して、上記のvle-auto-complete.scurlを選択します。選択すると、以下のように一覧にファイルが追加されます。
この状態でVLEでファイルの新規作成を行うと、以下のように「Developer Center」のタブが追加され、オートコンプリートの機能を持つ3種類のAPIがアイコンとして表示されます。
これらの部品の機能は、以下の通りです。
AutoCompleteTextField
入力補完の機能を持つテキストフィールドです。入力候補となる文字列は自分で指定することが出来ます。
AutoCompleteComboBox
入力補完の機能を持つコンボボックスです。基本的な機能はAutoCompleteTextFieldと同様ですが、右側のプルダウンより入力候補を選択することが出来ます。
ReminderAutoCompleteTextField
入力履歴を記憶し、入力候補として表示するテキストフィールドです。テキストフィールドに名前をつけることにより、入力欄を識別することが可能です。
これらの部品を画面上に配置するとこれらの部品をパッケージに含むAUTOCOMPLETE.scurlがプロジェクトにコピーされ、追加されます。
注意
一度VLEにファイルを追加した後、vle-auto-complete.scurlとAUTOCOMPLETE.scurlのファイルを削除しないでください。また、VLE拡張機能はCurl Pro/IDEでのみ使用することができます。