org.dspace.core
パッケージはDSpaceプログラム全体で使用される基本的なクラスを提供します。
ConfigurationManager
)設定マネージャは、メインプロパティファイルdspace.cfg
の読み込み、Apacheなどの他のアプリケーション向けの「テンプレート」設定ファイルの管理、電子メール通知文の取得を担当します。
システム設定の章で説明したように、システムの設定は、/dspace/config
にある該当するファイルを修正することで行います。
ApacheなどのDSpaceが使用するアプリケーションの設定ファイルを修正する際は、「実際に使用している」ファイルを直接修正するのではなく、/dspace/config/templates
にあるファイルを修正して、/dspace/bin/install-configs
を実行することを忘れないでください。
ConfigurationManager
クラスは以下の2つの方法で、コマンドラインツールとして実行することもできます。
/dspace/bin/install-configs
システム設定の章で説明したように、DSpace以外のアプリケーションの設定ファイルを処理して、インストールする。
/dspace/bin/dsrun org.dspace.core.ConfigurationManager -property property.name
dspace.cfg
からproperty.name
の値を読み込んで、標準出力に出力する。
使用例については、/dspace/bin/start-handle-server
を参照のこと。
なお、プロパティに値が設定されていない場合は、何も出力されない。
このクラスは、データベースにおいてオブジェクトの種別およびアクションを表わすために使用される定数を保持しています。
たとえば、権限ポリシーは様々な種別のオブジェクトに関連していますので、resourcepolicy
テーブルは、オブジェクトの内部IDであるresource_id
カラム、オブジェクトがアイテム、コレクション、ビットストリームなどのいずれであるのかを示すresource_type_id
カラムを持っています。そして、
resource_type_id
の値は、たとえば、Constants.ITEM
のように、Constants
クラスから選ばれています。
Context
クラスは、DSpace操作の中心となるものです。
ビジネスロジック層のAPIを使用するプログラムはすべて、まず、自分自身をContext
オブジェクトとして作成する必要があります。
これは、データベースへのコネクションを開始することに似ています(これは実際行なわれる処理の1つです)
コンテクストオブジェクトはほとんどのメソッド呼び出しやオブジェクトコンストラクタの引数になっており、その結果、メソッドやオブジェクトは現在の操作についての情報にアクセスすることができます。 コンテクストオブジェクトが生成される際、以下の情報が自動的に初期化されます。
データベースへのコネクション。これはトランザクションセーフである。すなわち、「auto-commit」フラグがfalseに設定されている。
コンテンツ管理APIオブジェクトのキャッシュ。コンテンツオブジェクト(たとえば、Item
やBitstream
など)は作成されるたびに、Context
オブジェックトに格納される。
オブジェクトが再要求されると、キャッシュされたコピーが使用される。これは、データベースアクセスの削減に加えて、メモリ上に状態の異なる同一オブジェクトの2つのコピーを持つという問題に対処するものである。
以下の情報もコンテクストオブジェクトに保持されます。ただし、コンテクストオブジェクトを作成して、情報を正しく設定するのはアプリケーションの責任です。
もしいれば、現在認証されているユーザ。
ユーザが所属している「スペシャルグループ」。たとえば、e-パーソンレコードを持っていないユーザでも、DSpaceに接続しているIPアドレスにより自動的にあるグループの一員である場合がある。そのようなグループを「スペシャルグループ」と呼んでいる。
このコンテクスト内で出力されるログメッセージにアプリケーション層が追加すべき情報。 たとえば、ウェブユーザインターフェースはセッションIDを追加する。ログを分析する際、この情報を使って特定のセッションの特定のユーザの行動を追うことが可能となる。
権限付与を回避すべきか否かを示すフラグ。これが使用されることはまれで、特別な状況に限られるはずである。 たとえば、最初にシステムをインストールする場合である。この場合、管理者アカウントを作成することができる権限を持った管理者は存在しないからである。
すでに説明したように、公開APIはトラステッドであるので、このフラグを使用する責任は、アプリケーション層のアプリケーションにある。
コンテクストオブジェクトの一般的な使用法は、まず、コンテクストオブジェクトを作成して、現在のユーザが認証されている場合はユーザを設定します。
コンテクストオブジェクトを使っていくつかの操作を実行します。
すべてがうまくいったら、complete
を呼び出し、変更をコミットして、コンテクストが使用したリソースを開放します。
何かうまくいかなかった場合は、abort
を呼び出し、変更をロールバックし、リソースを開放します。
処理の途中で何らか
のエラーが発生した場合は、必ずコンテクストをabort
する必要があります。そうでないと、システム上のデータが不整合のまま放置されることになります。コンテクストをcommit
することもできます。これは、変更をデータベースに書きこみ、コンテクストをさらなる使用のために保存しておくことを意味します。
電子メールを送付することはきわめて簡単です。設定マネージャのgetEmail
メソッドを使って、引数と受信者を設定し、送付するだけです。
電子メールの本文は、/dspace/config/emails
にあります。
これは、標準的なjava.text.MessageFormat
で処理されます。
各電子メール本文の先頭には、送信者により埋め込まれるべき引数がリストアップされています。
使用例は、org.dspace.core.Email
のJavadoc API説明書にあります。
ログマネージャクラスは、標準的なログヘッダを作成し、ログ出力にふさわしい文字列でそれを返すメソッドで構成されています。 このクラスは実際にはログに何も出力しないことに注意してください。返されたログヘッダは、送信者が適当なLog4Jのメソッドを使って直接出力しなければなりません。そうするとログ出力がどこで実行されたかについての情報も設定されます。
ログ出力のレベルは、/dspace/config/templates/log4j.properties
を編集して、/dspace/bin/install-configs
を実行することにより、パッケージ単位あるいはクラス単位で設定することができます。
設定を有効にするためにはTomcatを終了させて、再立ち上げする必要があります。
一般的なログエントリは次のような形をしています。
2002-11-11 08:11:32,903 INFO org.dspace.app.webui.servlet.DSpaceServlet @ anonymous:session_id=BD84E7C194C2CF4BD0EC3A6CAD0142BB:view_item:handle=1721.1/1686
これは次のように分解することができます。
日付、時間、ミリ秒 | 2002-11-11 08:11:32,903 |
レベル(FATAL , WARN , INFO , DEBUG ) |
INFO |
Java クラス | org.dspace.app.webui.servlet.DSpaceServlet |
@ |
|
ユーザのメールアドレス、あるいは anonymous |
anonymous |
: |
|
コンテクストによる追加ログ情報 | session_id=BD84E7C194C2CF4BD0EC3A6CAD0142BB |
: |
|
アクション | view_item |
: |
|
追加情報 | handle=1721.1/1686 |
ログはこの形式をしているので簡単にパースして分析することができます。/dspace/bin/log-reporter
スクリプトはログを分析する簡単なツールです。次のコマンドを試してみてください。
/dspace/bin/log-reporter --help
サーバのパフォーマンスに影響を与えないように、このログリポータの「nice値」を調整すると良いでしょう。
Utils
クラスは、プログラムのいろいろな箇所で必要とされ、それゆえ、サブシステムに特定の「ホーム」を持たない、さまざまなユーティリティメソッドを含んでいます。
コンテンツ管理APIパッケージorg.dspace.content
は、DSpaceシステムに保存されているコンテンツを読み込んだり、操作したりするためのJavaクラスを含んでいます。
おそらくアプリケーション層のコンポーネンツがもっとも良く使用すると思われるAPIです。
DSpaceデータモデルの主要な要素(Community
, Collection
, Item
, Bundle
, Bitstream
)に対応するクラスは、抽象クラスDSpaceObject
のサブクラスです。
Item
オブジェクトはダブリンコアメタデータレコードを扱います。
一般に、各クラスはコンテンツオブジェクトのインスタンス化に使用する1つ以上のスタティックなfind
メソッドを持っています。
コンストラクタは外部からアクセスできず、内部的に使用されるだけです。その理由は以下のとおりです。
オブジェクトを「コンストラクトすること」が、DSpaceシステムにおいてオブジェクトを作成するアクションであると誤解されるおそれがある。たとえば、システムにおけるオブジェクトのインメモリインスタンスを単にインスタンス化するのではなく、次のようなコードでシステムにまったく新しいアイテムを作成することを期待する可能性がある。
Context dsContent = new Context(); Item myItem = new Item(context, id)
find
メソッドはしばしば不正なIDで呼び出される場合があるが、そのような場合はnull
を返す。コンストラクタは本来このような場合、例外を投げる必要がある。スタティックなメソッドが返すnull
値は、一般にプログラムをより簡単にすることができる。
同一のアーカイブエントリを表すインスタンスが既に存在する場合、find
メソッドは単にそのインスタンスを返し、複数のコピーができることやその結果生じる不整合を避けることができる。
Collection
, Bundle
, Bitstream
は、create
メソッドを持っていません。代わりに、そのコンテナが持つ関連メソッドを使ってオブジェクトを作成しなければなりません。
たとえば、コレクションを作成するには、次のように、コレクションが所属するコミュニティオブジェクトのcreateCollection
メソッドを呼び出さなければなりません。
Context context = new Context(); Community existingCommunity = Community.find(context, 123); Collection myNewCollection = existingCommunity.createCollection();
その第1の理由は、権限を決定することにあります。e-パーソンがオブジェクトを作成することができるかどうかを知るには、どのコンテナにオブジェクトが追加されるのかをシステムは知る必要があります。コミュニティの外にコレクションを作成しても意味がありませんし、権限付与システムはそれに対するポリシーを持っていません。
Item
は、まずInProgressSubmission
の実装の形で作成されます。
InProgressSubmission
は作成中のアイテムを表します。
そして、作成が完了すると、InstallItem
クラスを使ってアーカイブにインストールされ、該当するコレクションに追加されます。
org.dspace.content
パッケージは、WorkspaceItem
と呼ばれるInProgressSubmission
の実装を提供しています。これは、ウェブ投稿用ユーザインターフェースで使用されるいくつかのフィールドを持つ簡単な実装です。
org.dspace.workflow
パッケージにも、ワークフロー処理中の投稿を表すWorkflowItem
と呼ばれる実装があります。
先の章で、アイテム受入プロセスの概要を説明していますが、これを読めば上の説明が明らかになるでしょう。ワークフローシステムの節も参考にしてください。
Community
と BitstreamFormat
はスタティックなcreate
メソッドを持っています。しかし、これを実行する権限を持つのはサイト管理者だけです。
名前の先頭にDC
が付くクラスは、下で説明するように、ダブリンコアメタデータを操作するクラスです。
FormatIdentifier
クラスは、ビットストリームのフォーマットを推定します。
現在のところ、ビットストリーム名の拡張子を見て、フォーマットに対応するファイル拡張子と照らし合わせるという簡単な方法を採っています。
できれば、将来これをもっと改善できたらと考えています。
ItemIterator
クラスは、ストレージからアイテムを1つずつ取り出せるようにします。このクラスは、メモリ上に一度に持つことができる数より多くのアイテムを返すことがあるメソッドの戻り値になります。
ItemComparator
クラスは、標準的なjava.util.Comparator
を、任意のダブリンコアメタデータフィールドに基づいてアイテムを比較・整列できるように実装したものです。
コンテンツ管理APIでデータを作成、変更、理由はともあれ削除する場合、変更が、メモリ上ではいつ行なわれ、DSpaceの物理的なストレージ上ではいつ行なわれるのかを知っておくことが重要です。
まず、org.dspace.core.Context
オブジェクトを使用して行なった変更は、そのContext
上で、complete
あるいは commit
メソッドが呼び出されないかぎり、実際にストレージに反映することはないということに注意するべきです。
処理の途中で何か問題が生じた場合は、不整合な状態をストレージに書き込まないことを保証するために、必ずabort
メソッドを使ってコンテクストを異常終了させる必要があります。
さらに、オブジェクトに行なった変更がメモリ上でのみ行なわれる場合もあります。
この場合、update
メソッドを呼び出して、Context
がcommitあるいはcompleteされる際に、メモリ上の変更がストレージに反映されるように手配します。
一般に、(メタ)データを変更するメソッドはメモリ上でのみ変更を行います。一方、他のオブジェクトとの関連を有するメソッドはコンテクストがコミットされる際に変更が反映されるように手配します。
個々のメソッドについては、API Javadocを参照してください。
これを説明する例を以下に示します。
Context context = new Context(); Bitstream b = Bitstream.find(context, 1234); b.setName("newfile.txt"); b.update(); context.complete(); |
ストレージを変更する |
Context context = new Context(); Bitstream b = Bitstream.find(context, 1234); b.setName("newfile.txt"); b.update(); context.abort(); |
ストレージを変更しない(コンテクストがアボートしたため) |
Context context = new Context(); Bitstream b = Bitstream.find(context, 1234); b.setName("newfile.txt"); context.complete(); |
update が実行されていないので、新しい名前は保存されない |
Context context = new Context(); Bitstream bs = Bitstream.find(context, 1234); Bundle bnd = Bundle.find(context, 5678); bnd.add(bs); context.complete(); |
update を呼び出す必要はないので、ビットストリームはバンドルに追加される |
コンテンツオブジェクトのインスタンス化により、他のコンテンツオブジェクトがメモリにロードされることがあります。
Bitstream
オブジェクトのインスタンス化は、対応するBitstreamFormat
オブジェクトのインスタンス化を引き起こします。
もちろん、Bitstream
オブジェクトが、対応するビットストリームをビットストリーム格納場所からメモリにロードすることはありません。
Bundle
オブジェクトのインスタンス化は、対応するBitstream
オブジェクト(とBitstreamFormat
)のインスタンス化を引き起こします。
Item
オブジェクトのインスタンス化は、対応するBundle
オブジェクト(など)とBitstreamFormat
のインスタンス化を引き起こします。
また、アイテムに付随するすべてのダブリンコアメタデータもメモリにロードされます。
その理由は、アイテムオブジェクトをインスタンス化する時は、ほとんどの場合、それに含まれているバンドルやビットストームに関する情報も必要になるでしょうから、この方法がもっとも効率的、かつ、呼び出し元にとっても簡単だからです。 たとえば、ウェブユーザインターフェースでは、サーブレット(コントローラ)は、アイテムに関する情報をビューア(JSP)に渡す必要がありますが、その際、ビューアはすべての情報をメモリ上に持つ必要があります。アイテムを表示中に、エラーを生じる可能性のあるデータベースのアクセスをしなくてもすむようにするためです。
同一のオブジェクトのインスタンスがメモリ上に複数存在することや、その結果生じるかもしれない不整合について心配する必要はありません。
Context
オブジェクトはインスタンス化されたオブジェクトをキャッシュしているからです。
org.dspace.content
パッケージのクラスが持つfind
メソッドは、キャッシュされたオブジェクトがあれば、それを使用します。
この包含するオブジェクトの自動インスタンス化は、パフォーマンスが重要な状況でパフォーマンスを低下させることがあるかもしれません。もしそれが証明されたら、loadContents
のようなメソッドを追加したり、何をするのかを示す論理値パラメタをfind
メソッドに追加したりするといった変更を将来APIに加えるかもしれません。
Context
オブジェクトが完了、異常終了、ガーベッジコレクションされると、コンテクストを使ってインスタンス化されたオブジェクトは無効になりますので使用してはいけません(ウィンドウが削除されると、そこにあったボタンが無効になることと同じです)。
DCValue
クラスは単純なコンテナであり、ダブリンコアの1組の要素、(オプションの)限定子、値、言語を表します。
その他のDC
で始まる名前を持つクラスは、人名や日付など、その名前を持つダブリンコアのデータを処理するユーティリティクラスです。
提供されたファイルを見ればわかりますように、DSpaceの要素・限定子のレジストリは、ダブリンコアについての図書館応用プロファイル(LAP)に対応しています。
これらのユーティリティクラスは、その値があるシンタックスで書かれていることを仮定しています。これは、DSpaceで作成されたデータについてはすべて当てはまりますが、ダブリンコアはシンタックスに関しては厳密に定義しているわけではありませんので、DSpace以外で作成されたダブリンコアメタデータについては、この仮定が当てはまらない場合もあることに注意するべきです。
DSpaceは各フィールドが次のシンタックスに従うことを想定しています。
要素 | 限定子 | シンタックス | ヘルパークラス |
---|---|---|---|
日付(date) |
任意、あるいは、限定子なし |
協定世界時(UTC)のISO 8601日付形式。年、年月、年月日、年月日プラス秒精度時間、のいずれか。たとえば、以下のとおり。 2000 2002-10 2002-08-14 1999-01-01T14:35:23Z |
DCDate |
寄与者(contributor) |
任意、あるいは、限定子なし |
一般に、姓、カンマ、名、その他の情報(たとえば、"Jr."など)の形。 寄与者が団体の場合は、単にその名称。たとえば、以下のとおり。 Doe, John Smith, John Jr. van Dyke, Dick Massachusetts Institute of Technology |
DCPersonName |
言語(language) |
iso |
ISO 639の2文字コード。オプションとして後に、ISO 3166の2文字の国コードを付けてもよい。たとえば、以下のとおり。 en fr en_US |
DCLanguage |
関係(relation) |
ispartofseries |
シリーズ名、セミコロン、シリーズ内の番号。単に自由文でもよい。 MIT-TR; 1234 My Report Series; ABC-1234 NS1234 |
DCSeriesNumber |
主要なクラスは以下のとおりです。
org.dspace.content.WorkspaceItem |
ワークフローに入る前のアイテムを持つ |
org.dspace.workflow.WorkflowItem |
ワークフロー処理中のアイテムを持つ |
org.dspace.workflow.WorkflowManager |
イベントに応じて、WorkflowItem の状態を管理する |
org.dspace.content.Collection |
定義済みのワークフローステップのリストを持つ |
org.dspace.eperson.Group |
ワークフロータスクを処理できる者は、e-パーソングループで定義される |
org.dspace.core.Email |
グループメンバーおよび投稿者に電子メール通知をするために使用される |
ワークフローシステムは、アイテムの状態を5つの状態(SUBMIT, STEP_1, STEP_2, STEP_3, ARCHIVE)を持つ状態機械でモデル化したものです。 異なるグループのメンバーがアイテムを査読・修正できるように3つのオプションステップがあります。 実際には、むしろ、STEP_1_POOL, STEP_2_POOL, STEP_3_POOLを持つ8状態に近いものです。 このPOOL状態は、アイテムが本来のステップに入るために待機している状態です。
WorkflowManager
はイベントにより呼びだされます。
アイテムは投稿作業の間、WorkspaceItemとして保持されます。WorkflowManagerのstart()
メソッドを呼び出すと、WorkspaceItemからWorkflowItemに変換され、WorkflowItemの状態を処理することが開始されます。
ワークフローの3つのステップはすべてオプションですので、ステップが1つも定義されていない場合は、アイテムはただちにアーカイブされます。
ワークフローはコレクション毎に設定されます。ステップはworkflowGroup
と呼ぶリストに、対応するエントリを作成することで定義されます。
ステップ1のワークフローを設定したい場合は、管理ツールを使って、アイテムを査読・承認できるようにしたい者をメンバーとするワークフローグループをコレクションに作成します。
すると、workflowGroup[0]
にグループのIDが設定されます。
あるステップがコレクションのワークフローに定義されると、WorkflowItem
の状態が対応するstep_POOLに設定されます。
このPOOL状態は、グループのメンバーがそのステップのタスクの実行を宣言することをWorkflowItem
が待っている状態です。
WorkflowManagerは、グループのメンバーに実行するべきタスクがあることを知らせるメール(その本文は、config/emails
で定義されています)を送付します。
そして、1人のe-パーソンが自分の「My DSpace」にアクセスしてタスクの実行を宣言すると、WorkflowManager
の宣言イベントが呼び出され、WorkfowItem
の状態は、STEP_x_POOL
からSTEP_x
(ここで、xは対応するステップ)に進みます。
e-パーソンは「宣言取り消し」イベントを生成することもでき、この場合、WorkflowItem
の状態は、STEP_x_POOL
に戻ります。
WorkflowManager
が処理するその他のイベントに、advance()
があります。これは、WorkflowItem
を次の状態に進めます。
それ以上ステップがない場合は、WorkflowItem
は除去されて、アイテムはアーカイブされます。
タスクを実行するe-パーソンは、アイテムを却下することができます。するとワークフローは中断され、そのアイテムのためのWorkspaceItem
が再作成され、投稿者には却下理由が送付されます。
もっと抜本的には、管理ツールでabort()
イベントを生成するとワークフローは完全に取り消されます。
org.dspace.administer
パッケージはDSpaceシステムを管理するためのクラスを含んでいますが、一般に、ほとんどのアプリケーションにとっては必要がないでしょう。
CreateAdministrator
クラスは簡単なコマンドラインツールです。/dspace/bin/create-administrator
により実行され、標準入力から入力された情報を元に管理者を作成します。
これは一般に、DSpaceシステムのインストールの際に1度だけ使用されるもので、最初の管理者を作成します。この管理者は管理用ウェブユーザインターフェースを使ってさらにシステムを設定することができます。
このスクリプトは権限をチェックしません。なぜなら、このスクリプトは一般に権限を与えるべきe-パーソンが存在する前に実行されるものだからです。
このスクリプトはサーバマシン上でコマンドラインツールとして実行されるべきものですので、一般に問題を引き起こすことはないはずです。
可能性があるのは、システムにe-パーソンがまだいない状態でスクリプトを実行させるということだけですが、一般に、サーバ上のコマンドラインスクリプトにアクセスできる者は、どうせしたいことなら何でもできる立場にある人でしょう。
DCType
クラスは、org.dspace.content.BitstreamFormat
クラスと似たもので、
ダブリンコア・レジストリのエントリ、すなわち、特定の限定子付きの要素、あるいは、限定子なしの要素を表しています。
このクラスがadminister
パッケージにあるのは、一般にレジストリ自体を処理する際にしか必要とされないからです。
org.dspace.content.Item
メソッドやorg.dspace.content.DCValue
クラスでは、要素と限定子はリテラルとして指定されます。
ダブリンコア・レジストリを変更するのは管理者だけでしょう。
org.dspace.administer.RegistryLoader
クラスは、XMLファイルにあるエントリでダブリンコア・レジストリとビットストリームフォーマット・レジストリを初期化するメソッドを持っています。
一般に、これはシステムのビルドプロセスでコマンドラインから実行されます(ソースディレクトリのbuild.xml
を参照)。
XMLフォーマットの例は、ソースディレクトリのconfig/registries
にあるファイルを参照してください。XMLスキーマがありませんので、ロードの際に厳密な検証はされません。
DSpaceは、org.dspace.eperson.EPerson
クラスを使って登録ユーザを把握しています。
このクラスは、姓や名、メールアドレス、パスワードを取得・設定するメソッドなど、EPerson
オブジェクトを作成・操作するメソッドを持っています(実際は、getPassword()
メソッドはありません。パスワードはMD5ハッシュで格納されており、checkPassword()メソッドで検証することができるだけです)。
e-パーソンをメールアドレス(ユニーックであると想定されます)で見つけたり、システムに登録されたすべてのe-パーソンを見つけたりする
find
メソッドがあります。
EPerson
オブジェクトはおそらく、簡単な拡張ができるように改訂されるべきでしょう。
現在、EPerson
オブジェクトが把握しているものは、氏名、メールアドレス、電話番号など、MITが把握したいと考えている情報だけです。
アクセスメソッドはハードコーディングされていますので、EPersonオブジェクトに格納されている情報をカスタマイズしたい場合は、おそらくこのメソッドを名前と値の任意の組でアクセスできるメソッドで置き換える必要があるでしょう。
グループは単なるEPerson
オブジェクトのリストです。
メンバー以外にGroup
オブジェクトが持つ属性は名前だけです。
グループ名はユニークでなければなりませんので、私たちは、COLLECTION_100_ADD
のようにグループの役割をグループ名とする命名規約を採用しています。
グループにEPersonオブジェクトを追加するにはaddMember()
を、削除するにはremoveMember()
を使用します。
グループクラスについて知っておくべき重要なことは、update()
メソッドが呼ばれるまで、グループクラスはメンバーをメモリ上に置いているということです。従って、メンバーを変更した場合は、update()
を呼び出すことを忘れないでください。そうでないと、その変更は失われてしまいます。
グループメンバーの確認は権限付与システムで多用されますので、処理速度の速いisMember()
メソッドも提供されています。
DSpaceはもう1つ別の種類のグループ、スペシャルグループ、を実装しています。
各セッションのContext
オブジェクトは、ユーザが所属するグループのIDリストを持っています。
現在のところ、あるIPアドレスあるいは証明書を持つユーザのスペシャルグループのリストには、MITUserグループのIDが追加されています。
主要なクラスは以下のとおりです。
org.dspace.authorize.AuthorizeManager |
グループに対するポリシーをチェックして権限を付与する |
org.dspace.authorize.ResourcePolicy |
オブジェクトに対して許可するすべてのアクションを定義する |
org.dspace.eperson.Group |
すべてのポリシーはEPersonグループに対して定義されている |
権限付与システムはセキュリティについての古典的な「警察国家」モデルに基づいています。
つまり、ポリシーで表明されていない限り、どのようなアクションも許可されません。
ポリシーはリソースに付随しており(そのためResourcePolicy
と言います)、誰がアクションを実行できるかを列挙しています。
リソースは、org.dspace.core.Constants
にリストアップされているDSpaceの任意のオブジェクトタイプ(BITSTREAM
, COLLECTION
など)です。
「誰が」は、EPersonグループで指定します。
アクションもConstants.java
にリストアップされています(READ
、WRITE
、ADD
など)。
このうち、ADD
とREMOVE
アクションは説明が必要です。これらはコンテナオブジェクトに対する権限です。
たとえば、アイテムを作成するためには、アイテムのコンテナであるコレクションに対するADD
権限を持っていなければなりません(コミュニティ、コレクション、アイテム、バンドルはすべてコンテナオブジェクトです)。
現在のところ、READポリシーのチェックはほとんどアイテムについて行われています。コミュニティとコレクションは誰でも読むことができることが想定されていますが、アイテムとビットストリームはチェックされます。 アイテムとそのビットストリームをチェックするポリシーを別にすることで、アイテムは一般に読めるようにした上で、そのコンテンツの一部を特定のグループに制限することができます。
AuthorizeManager
クラスのauthorizeAction(Context, object, action)
メソッドがシステムにおけるすべての権限付与の主たる源です。
これは、オブジェクトとアクションにマッチするシステム上のすべてのリソースポリシーのリストを取得します。
そして、リスト上のポリシーを順に当たって、ポリシーからEPsersonグループを抽出し、コンテクストに設定されているEPersonIDがそのグループのメンバーであるかをチェックします。
すべてのポリシーに当たっても何の権限も見つからなかった場合は、AuthorizeException
例外を投げます。
ハイパフォーマンスを必要とするアプリケーションのために、論理値を返すauthorizeActionBoolean()
メソッドも提供されています。
リソースポリシーは非常に簡単なものであり、非常に多くのポリシーが存在します。 各ポリシーは、1グループ、1アクション、1オブジェクトをリストできるだけです。 従って、各オブジェクトはおそらく複数のポリシーを持つことになるでしょう。 また、もし複数のグループがあるオブジェクトに対するアクション権限を共有していても、各グループは自身のポリシーを得ることができます(小さいことはいいことだ)。
すべてのユーザはパブリックグループ(ID=0)のメンバーであると仮定されています。 DSpace管理者グループ(ID=1)のメンバーは、自動的にすべてのグループの一員となります。丁度、Unix OSにおけるスーパーユーザに似ています。 コンテクストオブジェクトはスペシャルグループのリストも持っており、このグループのメンバーであるか否かも最初にチェックされます。 MITにおいては、このスペシャルグループをユーザがMITコミュニティの一員であることを示すために使用しています。このコミュニティのメンバーをすべてデータベースに登録することは非常に難しいからです。 MITの証明書、あるいは、MITのIPアドレスでユーザがログインすると、ログインプログラムはユーザのコンテクストにこのMITユーザグループを追加します。
アイテムはどこで自身のreadポリシーを得るのでしょうか。自身が属するコレクションのreadポリシーからです。 かつて、各コレクションにはアイテムに関する独自のデフォルトread権限が存在しました。そして、おそらくこれは復活されそうです。 なぜなら、管理者はコレクションのreadポリシーを定義するのが苦手であると評判だからです。 また、期間指定(開始日付と終了日付を持つ)のポリシーを可能にするプログラムも用意されています。ただし、この種のポリシーを有効にするための管理ツールはまだ作成されていません。
org.dspace.handle
パッケージは2つのクラスを持っています。
HandleManager
クラスは、ハンドルの作成と照合に使用します。
HandlePlugin
クラスは、DSpaceのハンドルをCNRIハンドルサーバプログラムにより外部世界に公開・解決するために使用します。
ハンドルは、内部的には次の形で、データベースのhandle
テーブルに格納されています。
1721.123/4567
これがシステムの外で使用される場合は、一般に、次のように、URIか「URLプロキシー」の形で表示されます。
hdl:1721.123/4567 http://hdl.handle.net/1721.123/4567
どちらの形が使われているにせよ、表示形から基本形を取り出すのは呼び出し元の責任です。
handle
テーブルでは、ハンドルをリソースタイプとリソースIDの組にマッピングします。
ここで、リソースタイプは、org.dspace.core.Constants
で指定されている値であり、リソースIDは、オブジェクトの内部識別子(データベースの主キー)です。
これによりシステムの任意の型のオブジェクトにハンドルを割り当てることが可能ですが、機能概要で説明したように、現在のところハンドルが割り当てられるのは、コミュニティ、コレクション、アイテムだけです。
HandleManager
クラスは、次の機能を持つスタティックメソッドを持っています。
DSpaceObject
のハンドルの発見。ただし、DSpaceObject
はgetHandle
メソッドを持っているので、これは一般にオブジェクト自身により呼び出されるだけである。DSpaceObject
の検索。HandlePlugin
クラスは、ハンドルサーバのnet.handle.hdllib.HandleStorage
インターフェースの簡単な実装で、データベースのhandle
テーブルから情報を取得するという基本的なハンドル検索メソッドを実装しているだけです。
CNRIハンドルサーバがこのプラグインを使用するようconfig.dct
ファイルで設定します。
ハンドルサーバはウェブユーザインターフェースとは別のJVMとして実行しますので、別の「Log4J」設定を使用することに注意してください。なぜなら、Log4Jは、複数のJVMが1つの日次ログを共有することをサポートしていないからです。
このハンドルサーバ用の設定は、/dspace/config/templates/log4j-handle-plugin.properties
のテンプレートにありますので、install-configs
スクリプトを実行して、/dspace/config/log4j-handle-plugin.properties
に書き込んでください。
/dspace/bin/start-handle-server
スクリプトは、ハンドルサーバがこの設定を使用するように適当なコマンドラインパラメタを設定しています。
DSpaceの検索プログラムは現在のところ、Lucene検索エンジンをラップする簡単なAPIです。
検索タスクの半分は、索引作成です。org.dspace.search.DSIndexer
が索引作成のためのクラスで、indexContent()
メソッドを持っています。
このメソッドに、Item
、Community
、Collection
を渡すと、コンテンツフィールドを索引に追加します。
unIndexContent()
メソッドとreIndexContent()
メソッドは各々、コンテンツの索引情報を削除、更新します。
DSIndexer
クラスは、索引を完全に再作成するmain()
メソッドも持っています。これは、dspace/bin/index-all
スクリプトにより呼び出されます。
main()
メソッドが定期的に実行されると考えたのは、索引が破壊されることを防ぐことにあったのですが、今のところ問題は生じていません。
どのフィールドがDSIndexer
により索引化されるのでしょうか。
現在のところ、対象フィールドは indexItemContent()
、indexCollectionContent()
、indexCommunityContent()
メソッドにハードコーディングされています。
クエリクラスであるDSQuery
は3種類のdoQuery()
メソッドを持っています。1つはDSpaceサイト全体を、残りの2つはコレクションとコミュニティに検索対象を限定するものです。
クエリの結果は、3種類のハンドルリストとして返されます。各リストは結果の種別を表します。
リストのうち、1つはマッチしたアイテムのリストで、残りの2つはマッチしたコレクションとコニュニティのリストです。
この分離により、ユーザインターフェースは、まずすべてのハンドルを解決してハンドルがどんな種類のコンテンツを指しているかを調べる必要がなく、その種別の結果を直接処理することが可能になっています。
DSQuery
クラスは、コマンドライン検索を使ってデバッグするためにmain()
メソッドも持っています。
現在のところ、DSpaceは索引作成をカスタマイズするために独自のAnalyzer
クラスとTokenizer
クラスを持っています(DSAnalyzer
と DSTokenizer
)。
これらを使って、Luceneにおいてステミングとストップワード処理を実現しています。
DSpaceでは、クエリごとにIndexReader
を作成します。今では気づいていますが、これはリソースの最も効率的な使用法ではありません。
実際の高負荷状況においてはファイルハンドルを使い切ってしまうようです。(ワイルドカードクエリが多くのファイルハンドルをオープンするようです)。
Luceneはスレッドセーフですので、すべてのクエリで共有する1つのLucene IndexReaderを持ち、索引が変化した場合に無効にして再オープンする方法がより良い実装となると考えられます。
将来のAPIの改善には、適合スコア(Luceneはこれを生成していますが、DSpaceでは無視しています)の採用と、論理演算などのもっと高度な検索概念のための抽象化があげられます。
DSpaceに含まれているDSIndexer
クラスは、次のようにダブリンコアメタデータを索引化します。
検索フィールド | 対象となるダブリンコアフィールド |
---|---|
Authors | contributor.* creator.* description.statementofresponsibility |
Titles | title.* |
Keywords | subject.*
|
Abstracts | description.abstract description.tableofcontents |
Series | relation.ispartofseries |
MIME types | format.mimetype |
Sponsors | description.sponsorship |
Identifiers | identifier.* |
org.dspace.search
パッケージは、「ハーベスティング」APIも提供しています。
これにより呼び出し元は、特定の時間枠内で、あるいは、特定のスコープ(DSpace全体、あるコミュニティ、またはあるコレクション)内で変更されたアイテムの情報を抽出することが可能になります。
現在のところ、OAI-PMHアプリケーションと電子メール購読プログラムで使用されています。
Harvest.harvest
メソッドは、必要なスコープと開始日付、終了日付を付けて呼び出されます。
日付はどちらもオプションです。日付は、DSpaceの他の場所でも使用されているUTCのISO8601形式でなければなりません。
HarvestedItemInfo
オブジェクトが返されます。
このオブジェクトは、指定されたスコープと日付枠に該当するアイテムについての基本的な情報を持つ簡単なコンテナです。
harvest
メソッドにわたす引数により、containers
フィールドにはアイテムが所属するコミュニティやコレクションのIDが、item
フィールドには、該当するItem
オブジェクトが、設定されます。
これらのフィールドを設定しないことを選択すると、ハーベスト処理は極めて早く実行されます。
Harvest
クラスは、単一のHarvestedItemInfo
オブジェクトを作成するメソッドも提供しています。場合によっては、これを使った方が呼び出し元にとって都合がいいかもしれません。
ブラウズAPI は日付、著者、タイトルの索引をメンテナンスし、呼び出し元がこれらの一部を抽出できるようにします。
ダブリンコア要素title
(限定子なし)の値が索引化されます。冒頭の冠詞は除去され、大文字、小文字を区別せずにソートされます。たとえば、
The DSpace System
は、「T」ではなく、「D」の位置に現れます。
contributor
(任意の限定子付きの、もしくは、限定子なしの)要素の値が索引化されます。
一般に、contributor
の値は、「姓、名」の形ですので、単純な大文字、小文字を区別しないソートを使って、著者は姓順に並べられます。
これは、著者の索引であって、著者によるアイテムの索引ではないことに注意してください。 4つのアイテムが同じ著者を持っている場合、著者が索引に現れるのは、1回きりです。 したがって、著者索引は、タイトル索引にくらべて多い場合もあれば、少ない場合もあります。アイテムが2人以上の著者を持つ場合もありますし、逆に、1人の著者が複数のアイテムの著者の場合もあるからです。
ブラウズAPIにおける著者索引には、次のような制限があります。
理想的には、2つ以上のアイテムの著者として現れる名前は、著者索引には1回だけ出現するものである。 しかし、現実的には、著者の名前はしばしば次の例のように少しずつ違った形で現れることがある。
Doe, John Doe, John Stewart Doe, John S.
現在のところ、上の3つの名前は、たとえ、同一著者を意味しているとしても、著者索引としてはすべて別のエントリとして出現する。 複数の論文を書いている著者を、索引として正確に1回だけ出現させるには、各アイテムに同じ形の著者名を正確に指定する必要がある。ただし、これは実際には難しいものである。
もう1つの問題は、同姓同名の著者である。これは1つの機関内でも生じる可能性がある。この場合、索引には1人の著者として出現することになる。
これらの問題は、図書館では一般に著者名典拠レコードにより解決されています。 著者名典拠では、同姓同名の著者を区別するために(生没年などの)追加情報を使って、著者名の「優先」形を管理します。 そのようなレコードを保守・管理することは非常に手間のかかる作業であり、問題も多く発生します。 特に、訓練を受けた図書館の目録担当者ではなく教員からメタデータを直接受け取る場合はなおさらです。 このような理由から、DSpaceはまだ「典拠コントロール」機能を持っていません。
アイテムは発行日で索引化されます。
この日付は、アイテムがDSpaceに登録された日付ではありません。
アイテムはもともと、前もってどこか別の場所で出版されているものが多いからです。
使用されるダブリンコアフィールドは、date.issued
です。
この索引のソート順は逆にすることも可能ですので、「古いもの順」、「新しいもの順」のどちらも可能です。
この索引は、日付によるアイテムの索引であり日付の索引ではないことに注意してください。 たとえば、30のアイテムが同一の発行日(2002年とします)を持っている場合、2002年というエントリが1つ出現するだけではなく、索引上には30のアイテムがすべて並んで出現します。
ダブリンコアにおける日付は、すべてUTCのISO8601形式ですので、日付のソートは、さまざまな粒度をもつ日付表示の単純なアルファベット順で十分です。たとえば、次のようになります。
2001-12-10 2002 2002-04 2002-04-05 2002-04-09T15:34:12Z 2002-04-09T19:21:12Z 2002-04-10
もっとも最近現れたアイテムを決めるためには、発行日を使わずに、アイテムの登録日を使用します。これは、ダブリンコアのdate.accessioned
フィールドです。
この索引のその他の解釈は、発行日と同じです。
ブラウズAPIで行なうことができるもう1つの処理は、特定の著者のアイテムを抽出することです。 著者は、抽出されるアイテムの第1著者である必要はありません。 また、スコープを指定することもできます。すなわち、たとえば、コレクションYにおける著者Xのアイテムといった形で指定することができます。
この一風変ったブラウズは他のブラウズ機能よりいくぶん単純なものです。 現在のところ、結果の一部を返すように指定することはできません。 APIを呼び出すと、単に、あるスコープにある特定の著者のアイテムをすべて返すだけです。
抽出されるアイテムの著者は、APIに渡した著者の形と正確に一致するものだけであるということに注意してください。なぜそうなるのかは、著者索引によるブラウズの注意点についての説明を参照してください。
一般に、このAPIは、BrowseScope
オブジェクトを作成し、パラメタで抽出したい索引を設定することにより、呼び出されます。
次に、これは該当するBrowse
メソッドに渡され、処理の結果を含むBrowseInfo
オブジェクトが返されます。
BrowseScope
オブジェクトに設定するパラメタは次のとおりです。
以下の例を使って、説明します。
このパラメタを指定して、Browse.getItemsByTitle
を実行した結果は、次のような感じになります。
Rabble-Rousing Rabbis From Sardinia Reality TV: Love It or Hate It? FOCUS> The Really Exciting Research Video Recreational Housework Addicts: Please Visit My House Regional Television Variation Studies Revenue Streams Ridiculous Example Titles: I'm Out of Ideas
タイトルと日付によるブラウズの場合は、実際のタイトルではなくItem
オブジェクトが返さることに注意してください。
これらの場合、「フォーカス」としては、特定のアイテムや、リテラル値の一部、または、完全形を指定することができます。
リテラル値が指定された場合で、正確に一致する索引がない時には、一番近いものがフォーカスとして使用されます。
従って、たとえば、1文字のフォーカスを指定することはまったく問題ありません。
同一発行日を持つアイテムは多いでしょうから、特定のアイテムを開始点にできることは日付によるブラウズにとっては特に重要です。 たとえば、あるコレクションに発行日として2002年を持つアイテムが30あるとします。 1回あたり1ページに20アイテムの索引を見られるようにするには、2002年のどのアイテムがブラウズのフォーカスであるかを正確に指定できる必要があります。そうでないと、ブラウズを呼び出すたびに、発行日に2002年を持つ最初のアイテムから結果の表示が開始することになります。
著者によるブラウズは実際の著者名を持つString
オブジェクトを返します。
指定できるフォーカスは、リテラルString
の完全形あるいは部分形だけです。
もう一つ重要な注意点は、現在のところ、ブラウズ用の索引には権限ポリシーに関係なくアーカイブにあるすべてのアイテムのメタデータが含まれていることです。 これは、ブラウズの際には、アーカイブにあるすべてのアイテムがすべてのユーザに公開されることを意味します。 もちろん、非公開アイテムにアクセスしようとすると、一般的な権限メカニズムが適用されます。 このアプローチが望ましいものであるかは検討中です。 たとえば、抽出される結果にユーザの権限レベルを反映させるようなブラウズAPIの実装は可能だと思われますが、少し大変になるでしょう。
ブラウズAPIには、索引にアイテムを追加・削除するメソッドや、索引を1から再作成するメソッドが含まれています。 一般に、コンテンツ管理APIが必要なブラウズAPIメソッドを呼び出して、アーカイブにあるアイテムに同期させてブラウズ用の索引を管理しています。 ですので、ほどんどのアプリケーションはこれらのメソッドを呼び出す必要はありません。
もし何らかの原因でブラウズ用の索引に矛盾が生じた場合は、InitializeBrowse
クラスが索引を1から再作成するコマンドラインツールです(一般に、/dspace/bin/index-all
シェルスクリプトを使って実行します)。
現在のところ、ブラウズAPIはとほうもなく非効率的です。
「索引化」作業は、関連するダブリンコア値の抽出、その正規化(小文字化とタイトルの場合は冒頭の冠詞の除去)、正規化した値とアイテムIDを該当するブラウズテーブルへ登録、という単純な手順を取っています。
このテーブルのビューには、スコープを限定したブラウズ操作のために、コレクションIDとコミュニティIDが含まれています。
ブラウズ操作が実行されると、次のような単純なSELECT
クエリが実行されます。
SELECT item_id FROM ItemsByTitle ORDER BY sort_title OFFSET 40 LIMIT 20
これには主に2つの欠点があります。1つは、LIMIT
とOFFSET
が、PostgreSQL独自のキーワードであることです。
もう1つは、データベースにより動的にタイトルのソートを行なうので、現在のブラウズプログラムはスケーラビリティに欠けることです。
プログラムはBrowseInfo
オブジェクトをキャッシュしているので、共通のブラウズ操作の実行速度を上げることができますが、これは理想的な解ではありません。
履歴サブシステムの目的は、後々のリファクタリングや再利用で使えるように、DSpaceで生じた重要な変化を時間ベースの記録として残しておくことです。 履歴データはアーカイブについての現在の情報を提供するものではないことに注意してください。 単に過去に生じたことを記録するだけです。
Harmonyプロジェクトは、一時的なデータをモデル化する単純ですが強力な方法を提供しています。 DSpaceの履歴フレームワークはこのモデルを採用しています。 Harmonyモデルは、シリアライズのメカニズムで使用されています(そして、最終的にはシリアル化されたデータを解釈するエージェントで使用されます)。 しかし、履歴APIを使用するユーザはこれを気にする必要はありません。 コンテンツ管理APIがこの履歴システムの実行を担当します。 DSpace公開APIのユーザは、一般に履歴APIを使用する必要はありません。
DSpaceにおいてアーカイブ上関心のある何かが生じると、HistoryManager
クラスのsaveHistory
メソッドが呼び出されます。
パラメタには、アーカイブ上関心のある何らかのオブジェクトへの参照が含まれています。
オブジェクトを受け付けると、参照により示されるすべてのアーカイブオブジェクトの状態をシリアル化し、Harmony形式のオブジェクトと、オブジェクト間の関係を記述するアソシエーションを作成します。(簡単な例を後で示します。)
各アーカイブオブジェクトは、異なるイベント間で追跡できるようにユニークな識別子を持っていなければならないことに注意してください。これについては、後で「ユニークなID」の項で説明します。
シリアライズ(Harmonyオブジェクトとアソシエーションを持っている)は、(設定によりますが)/dspace/history
ディレクトリにファイルとして永久に保存されます。
history
テーブと historystate
テーブルは、ファイルシステム上にあるシリアライズへの簡単な索引を格納しています。
以下のイベントが履歴レコードとして記録される重要なイベントです。
アーカイブオブジェクトのシリアライズは次の要素からなります。
オブジェクトの履歴を追跡するためには、オブジェクトがユニークな識別子を持っていることが必要不可欠です。 システムのすべてのオブジェクトがハンドルを持っているわけではありませんので、ユニークな識別子とハンドルシステムとの結びつきはあまり強くありません。その代わりに、識別子は以下の要素からなります。
アーカイブオブジェクトがシリアル化されると、オブジェクトIDとMD5チェックサムが記録されます。 別のオブジェクトがシリアル化される際、シリアライズのチェックサムと、そのオブジェクトについての既存のチェックサムとがマッチングされます。そして、チェックサムがすでに存在する場合は、オブジェクトは保存されず、その代わりに、そのオブジェクトへの参照が使用されます。 シリアライズは削除されませんので、参照カウンタは必要ないことに注意してください。
履歴データは当初、照会可能な形では保存されません。
2つの簡単なRDBMSのテーブルが、何が、どこに保存されているかについての基本的な指標を提供します。
history
テーブルは、チェックサムと日付を持つシリアライズの索引です。
history_id
カラムは、シリアライズが格納されているファイルに相当します。
たとえば、履歴IDが123456である場合、シリアライズは次のファイルに格納されていることになります。
/dspace/history/00/12/34/123456
テーブルには、シリアライズが書き込まれた日付と、シリアライズのMD5チェックサムも格納されています。
historystate
テーブルは、指定されたオブジェクトの最も新しいシリアライズを示すために用意されています。
あるアイテムが一括アップロードで、あるコレクションに投稿されたとします。アイテムが最終的にコレクションに追加される際に、アイテム、コレクション、一括アップロードを実行したe-パーソンに対する参照と、一括アップロードで投稿されたという事実を示す何らかの指標を持って、履歴メソッドが呼び出されます。
HistoryManager
は、呼び出されると次の処理を行います。まず、次の新規リソース(すべてユニークな識別子を持ちます)を作成します。
また、次の関係を生成します。
event --atTime--> time event --hasOutput--> state Item --inState--> state state --contains--> Item action --creates--> Item event --hasAction--> action action --usesTool--> DSpace Upload action --hasAgent--> User
履歴コンポーネンツは、関係するすべてのアーカイブオブジェクト(この例では、アイテム、e-パーソン、コレクション)の状態をシリアル化します。 また、生成されたシリアライズにアーカイブオブジェクトを関連させる2つの履歴テーブルにエントリを作成します。
この履歴システムは大部分、未テストの実験状態にあります。
また、さらなるドキュメントを必要としています。
ファイルへの出力であれ、データベーステーブルへの出力であれ、履歴システムにより出力される情報が正確であるかどうかを確定するための本格的な作業はされていません。
特に、historystate
テーブルには正しく出力されているとは思われません。