OBAQシェル

OBAQシェルとは何か?

OBAQシェルとは「オブジェクト指向に基づく汎用の構成定義ファイルパーサ」です。

例えば、Apacheの構成定義ファイル(httpd.conf)を見てみましょう。

# サーバ全体に対する指定
ServerType standalone
ServerRoot /etc/httpd
LockFile /var/lock/httpd.lock
PidFile /var/run/httpd.pid

# ディレクトリに対する指定
<Directory /home/httpd/icons>
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

# VirtualHostに対する指定
<VirtualHost ip.address.of.host.some_domain.com>
    ServerAdmin webmaster@host.some_domain.com
    DocumentRoot /www/docs/host.some_domain.com
    ServerName host.some_domain.com
    ErrorLog logs/host.some_domain.com-error_log
    CustomLog logs/host.some_domain.com-access_log common

   <Directory /home/httpd/icons>
     ....
   </Directory>
</VirtualHost>

一般にapacheのように複雑なソフトでは、このように構成定義ファイルも複雑になります。 OBAQシェルは、このような複雑な構造を持つ構成定義ファイルを読んで、 プログラムの初期設定を行なう処理を記述するためのフレームワークです。

OBAQシェルでは「構成定義=モデルオブジェクトの生成」という考え方で、 次のようなプログラミングモデルを想定しています。

つまりOBAQシェルは、外界(処理対象)の「モノ」に対応する(シミュレーションする)オブジェクトの生成を行なうライブラリです。 これを利用することで、以下のようなメリットがあります。

もし、上記のhttpd.confをOBAQで記述するとしたら、以下のようになります。

# サーバ全体に対する指定
Server
 type=standalone
 root=/etc/httpd
 lockfile=/var/lock/httpd.lock
 pidFile=/var/run/httpd.pid

  # ディレクトリに対する指定
  Directory /home/httpd/icons
    .set_ptions Indexes MultiViews
    allowOverride=false
    .set_order allow,deny
    .allow from all

  # VirtualHostに対する指定
  VirtualHost ip.address.of.host.some_domain.com
    admin=webmaster@host.some_domain.com
    root=/www/docs/host.some_domain.com
    serverName=host.some_domain.com
    errorLog=logs/host.some_domain.com-error_log
    customLog=logs/host.some_domain.com-access_log common

   Directory /home/httpd/icons
     ....

このテキストファイルをOBAQファイルに渡すだけで、 ServerとかDirctoryとかVirtualHostというオブジェクトが生成され、 それぞれ必要な属性が設定され、各オブジェクト間の関係が設定されます。

もちろん、Server, Directory, VirtualHost というクラスとそれが実際に動作するためのメソッドは記述する必要がありますが、 上記の構成ファイルからオブジェクトモデルを生成する処理はOBAQシェルが行ないます。

これによって、プログラマーは実際に処理に専念でき、ユーザは個別のフォーマットを学習する必要がなくなります。 また、両者にとって最も少い負担で機能を拡張することができます。

OBAQフォーマット

Obaqフォーマットの行の種類
種類 判別方法 処理内容
オブジェクト生成行 先頭文字が大文字 指定したクラスのオブジェクトを生成する Folder xxxx
オプション設定行 先頭文字が小文字 直前のオブジェクトに対するオプション設定 recuresive=true
メソッド行 先頭文字が.(ピリオド) 直前のオブジェクトに対するメソッド呼び出し .add_subfolder yyy
内部コマンド行 先頭文字が% OBAQシェルに対する処理指示
コメント行 先頭文字が#l コメント
Folder                                   # オブジェクト生成行
 title="Walrus sample(navigation_bar)"   # オプション設定
 target_dir=target                       # オプション設定
.def_acq header_title ' parent.title.to_s + "--" + title.to_s '
                                         # ↑メソッド呼びだし行

HtmlDocument index.html                  # オブジェクト生成行
 prettyprint                             # オプション設定
 role=index                              # オプション設定

HtmlDocument java.html                   # オブジェクト生成行
 title=javaについて

HtmlDocument perl.html                   # オブジェクト生成行
 title=perlの特徴

オブジェクト生成行

OBAQフォーマットでは、単にクラス名を書くとそのクラスのオブジェクトを生成します。 生成時に渡すパラメータは、クラス名の後に空白を置いて記述します。 生成時のパラメータの種類や指定方法は各クラスの仕様を参照してください。

オブジェクト生成行に--があると、その後はオプション設定行と見なします。

HtmlDocument java.html                   
 title=javaについて

上と下は同じ意味になります。

HtmlDocument java.html --  title=javaについて

クラス名の前にある空白の数(インデント)によってオジェクト間の親子関係が決定します。

Folder aaa
  HtmlDocument xxx.html

  Folder bbb
    HtmlDocument yyy.html
    HtmlDocument zzz.html        

この例では、xxx.htmlはaaaの子供、 yyy.htmlとzzz.htmlはbbbの子供になります。

オプション設定行

オプション設定行は、○○=××という形式で記述して○○というオプションに××という値を設定します。

○○としてどのようなオプションが許されるのかは、各クラスの仕様を参照してください。

=の前後にはスペースがあってもいいしなくてもかまいません。××は"や'で挟むことも可能です。

イコールと値が省略されていた場合は,○○ == trueが省略さてているものと します。

メソッド呼び出し行

メソッド呼び出し行には、メソッド名と(必要ならば)引数を記述します。 OBAQシェルから呼び出すメソッドは、全ての引数を文字列として受けつけるようにします。

ヒアドキュメント

OBAQシェルは、bashやRubyと同様のヒアドキュメントを理解します。 オプションに複数行にわたる内容を設定する時に使用します。

HtmlDocument
  title = Rubyについて
  .description = <<END
このドキュメントにはRubyについての説明が記述してあります。
Ruby言語についてよく知っている人は飛ばしてください。
END
ヒアドキュメントの記述方法
開始マーク 終了マーク 備考
>>END 行の先頭のEND ENDの所には任意の文字列を指定可能
>>-END ENDだけの行 -があると終了マークをインデントできる
>* *だけの行 *のかわりに任意の文字を指定可能
{ }だけの行 [] <> ()も同様
{{ }}だけの行 [[]] <<>> (())も同様

メソッド定義

.def メソッド名 メソッド本体という形式でオブジェクトにメソッドを定義できます。 メソッド本体にはヒアドキュメント形式を使用することができます。

SomeObject xxxx
.def method1 "puts hello"
.def method2 {
  puts "hello"
}
.def method3 <*
  puts "hello"
*

同様に、 .def_acq メソッド名 メソッド本体でACQメソッドを定義できます。 ACQメソッドについては「環境獲得」を参照してください。

内部コマンド

内部コマンドの種類
コマンド 引数 処理内容
%load ファイル名 Rubyソースを読みこむ
%require ファイル名 Rubyソースを読みこむ(既に読まれていれば処理しない)
%eval Rubyスクリプト Rubyの命令として評価する
%include モジュール名 Rubyのモジュールを利用可能にする
%import ファイル名 別のOBAQフォーマットのソースを読みこむ
%get_object クラス名 オブジェクト名 OBAQオブジェクトを呼び出す
%model_class クラス名 Rubyスクリプト クラスを定義する
%comment コメント コメント

Rubyソースの読みこみ

%load, %require, %evalはほぼRubyの同名の命令に対応しています。

%get_object

%get_objectは、OBAQオブジェクトを分割して記述した場合に、 他のファイルで定義されたオブジェクトを修正するために使用します。

a.walの中でa.htmlというオブジェクトが定義されていて、 b.walからa.walを引用したとします。

(a.wal)
HtmlDocument a.html

(b.wal)
%import a.wal
%get_object HtmlDocument a.html
  title=yyy

この時、上記のように%get_objectjを使用すると、 あたかも a.htmlに対してtitle=yyyというオプションが指定されていたのと同じ意味になります。

%model_class

OBAQフォマーットの中でRubyのクラスを定義する略記法です。 下記の2つは同じ意味になります。

%eval {{
  class AAA < ObaqModelObj
    def_option :xxx
  end
}}

%model_class lAAA ObaqModelObj {{
  def_option :xxx
}}

OBAQシェルの処理内容

OBAQオブジェクトの種類

OBAQ構成定義ファイルからオブジェクトを生成できるクラスは次の3種類に分かれています。

OBAQシェルの処理内容

  1. 構成定義ファイルの読みこみ

    メインの構成定義ファイルを読みこみます。 この中から、%require等で指定されたRubyソースも読みこみその中でクラス定義が行なわれます。 そして、OBAQオブジェクトを生成します。

  2. build_modelの実行 全てのモデルオブジェクトに対して、build_modelメソッドを呼び出します。
  3. コマンドセットの選択 実行するコマンドセットを選択します。
  4. ジョブクラスの実行 選択したコマンドセットに属するジョブクラスのdoitというメソッドを順番に実行していきます。

上記の一連の処理は、Obaq::ObaqApp.main に記述してあります。 アプリケーションから、このメソッドを呼びだすこともできますが、 これを実行する obaq というコマンドも用意してあります。

実行例

下記の内容を $ obaq sample.obaq として実行したとします。

# (1)
%model_class HelloMsg {
  def_option :message
}

# (2)
HelloMsg hello1
 message="Hello, world"

# (3)
CommandSet

 ObaqJob 
 .def doit {
   hello = app.get_object(HelloMsg, "hello1")
   puts hello.message
 }

この時、以下のような順番で処理が実行されます。

  1. class HelloMsgの定義(%model_class)

    OBAQオブジェクトを生成するためのクラス定義が行なわれます。 この例では、%model_classによって構成定義ファイルの中にクラスを定義していますが、 クラスの内容が複雑になる場合には、別ファイルに記述して %requireで読みこみます。

  2. HelloMsgオブジェクトの生成

    HelloMsgクラスのオブジェクトが生成されます。 このクラスには messageというオプションスロットがありますが、 このオプションには"Hello, world"という文字列が設定されます。

  3. コマンドセットオブジェクトとジョブオブジェクトの生成

    CommandSetとObaqJobは、組み込みのコマンドセットとジョブクラスです。 簡単な処理ではこのように組み込みのクラスを使用しますが、 複雑な処理では、ジョブオブジェクトやコマンドセットオブジェクトも個別に記述します。

    そして、このObaqJobオブジェクトに doit というメソッドを定義しています。

  4. コマンドセットの選択

    この構成定義にはコマンドセットがひとつしかないので、自動的にそれが選択されます。 複数のコマンドセットがある場合は、obaqコマンド --target xxx というオプションを与えて 実行すべきコマンドセットを指定します。

  5. ジョブの実行

    このコマンドセットにはジョブオブジェクトがひとつだけ付属していますので、 そのオブジェクトのdoitメソッドを実行します。

    doitメソッドの内容は、構成定義ファイル内にインラインで記述されています。

  6. モデルオブジェクトの機能を呼出す

    doitの中から app.get_object(クラス名、オブジェクト名)で、HelloMsgオブジェクトを呼び出します。 そして、おのオブジェクトに出力すべきメッセージの内容を問合せます。

    このようにジョブは実行に際して、モデルオブジェクトに指示したり、問い合わせたりして、 ユーザの指定した構成に従った処理を行います。

OBAQオブジェクトの記述

OBAQモデルオブジェクトの定義

OBAQシェルによってオブジェクトを生成するためには、 classが以下の条件を満たしている必要があります。

OBAQモデルオブジェクトの提供すべきメソッド

OBAQモデルオブジェクトの利用できる主なメソッド

親子関係の自動設定

親子関係の自動設定