2008年11月8日土曜日

ようやく策定されたECMのための共通言語 CMIS(2/3) (Insight Now!より転載)

少し間があいてしまいましたが、CMIS(Content Management Interoperability Service)の内容紹介を続けたいと思います。前稿では、CMISがどのような利用のシーンを前提として策定されているのか、という話題を中心にご紹介しました。本稿では続くメソッドレベルでのAPIの解説の前提知識となるデータモデルについてご説明します。



CMISではいわゆるフルスペックのECM製品で取り扱われるオブジェクト群のすべてが規格化されているわけではありません。たとえば追加開発用のインターフェースに使われるトランジェント(永続化対象外)なエンティティや、ユーザプロファイルのような管理目的のエンティティ、ヴァーチャル文書やビジネスプロセスそして購読などの付加価値的な機能であつかわれるエンティティもスコープ外になっています。それでも、データの格納先として求められるリポジトリの構成要素については一通り網羅されていますし、その構成要素間の複雑な関係性も表現できるようになっています。まずは最上位の概念である"リポジトリ"からはじめて、4つの基本オブジェクトタイプを説明します。個々の構成要素である"文書""フォルダ"、その関係性を表現する"関連"、標準的なサービス(アクセス制限など)を表現する"ポリシ”の4つがCMISにおける基本オブジェクトタイプです。それからさらに追加のオブジェクトタイプの定義方法を紹介するまでを本稿の範囲としたいと思います。



リポジトリ



ECM製品毎にリポジトリの実装方法は様々です。したがって、CMISにおいては最上位概念であるリポジトリについてもすべての機能を網羅することを求めてはいません。例えば以下に挙げる機能は"オプショナルな"ものとして取り扱われます。また、当該リポジトリがこれらの機能をサポートしているかどうかは、getRepositoryInfoサービスによって通知されなければなりません。
・文書(あるいはフォルダに格納可能なその他のオブジェクト)を複数のフォルダに格納する機能。マルチファイリング。
・文書(あるいはフォルダに格納可能なその他のオブジェクト)をどのフォルダにも格納しないまま保持する機能。アンファイリング。
・文書の特定のバージョン(群)だけをフォルダに格納する機能。バージョン指定ファイリング。
・チェックアウトされた文書のワーキングコピーを更新する機能。ワーキングコピー編集。
・最新版ではない文書もスコープに含めた検索機能。全バージョン検索。
・チェックアウトされた文書のワーキングコピーもスコープに含めた検索機能。ワーキングコピー検索。
・検索クエリのサポート。「なし」「メタデータのみ」「全文検索のみ」「両方」
・クエリにおけるジョインのサポート。「なし」「インナージョインのみ」「インナージョインおよびアウタージョイン」
・全文検索サポート。「なし」「全文検索のみ」「全文検索と属性情報の組み合わせ」



これら機能のサポート状況だけでなくgetRepositoryInfoサービスからは関連するその他のリポジトリへのリンクを得ることもできるようになっています(規格上はMAYと表現)。CMISにおいてはリポジトリは単一のものではなく、いくつものリポジトリが併存する状況が前提となっています。getRepositoriesサービスによってアクセスの対象となりえるリポジトリの一覧が取得できます。上記の関連する他のリポジトリの一覧というのは、そのサブセットになります。また、getRepositoryInfoサービス以外でもgetTypesサービスやgetTypeDefinitionを利用してリポジトリについての情報を取得することもできます。



基本オブジェクトタイプ



CMISの基本オブジェクトタイプは、文書・フォルダ・関連・ポリシの4つです。文書はリポジトリに格納されるもっとも基本的な構成要素です。フォルダは文書をはじめとする「格納可能なオブジェクト」の集合のコンテナです。関連は2つの独立したオブジェクト(インスタンス)を繋ぐ関係性を定義します。ポリシは1つ以上の「コントロール可能なオブジェクト」に「適用」される管理目的のポリシを表現します。文書とフォルダとポリシの3つは独立したオブジェクトとして位置づけられているため、関連の対象となります。



また、各オブジェクトはオブジェクトIDというユニークな識別子を持ちます。このIDはタイプによらずリポジトリ内でユニークであることが保証されていなければなりません。また、必須ではありませんが、このIDは「永続的」であることが望ましいとされています。(永続的とは、すくなくともそのオブジェクトのライフスパンが終わるまでの間は不変である、ということを意味します。そのオブジェクトが消滅した後で同一のIDが新しい別のオブジェクトにアサインされる可能性については特に規定されていません)。さらに内部的なIDだけでなく、URIを割り振ることもできます(これも必須ではありません。MAYと表現されています)。ただし、URI自体の検証や外部接続性等々についての細かい規定はCMISの対象外となります。



各オブジェクトには属性が定義されます。属性は必ず名前をもちますが、厳密な順番付けは必要としません。(ただし、同一リポジトリの同一クラスの属性のセットについては常に一貫した順番で取得できることが求められています)属性には、String(文字列 xsd:string)・Decimal(小数 xsd:decimal)・Integer(整数 xsd:integer)・Boolean(真偽値 xsd:boolean)・DateTime(日付 xsd:dateTime)・URI(URI xsd:URI)などの型が用意されています。また、ID(xsd:string)とXML(xs:any)とHTML(xs:any)という3つ独自の属性型も定義されています。IDがxsd:idではないことに注意してください。XMLとHTMLはそれぞれのマークアップ言語の断片を格納します。



文書



リポジトリの最も基本的な構成要素です。格納可能で独立したオブジェクトです。他の基本オブジェクト型とは違い、いわゆるファイルの実体にあたるContentStreamをもっています。ContentStreamはバイナリのデータ列で、その最大長はリポジトリの実装に依存します(特に規定はありません)。また、各ContentStreamにはMIMEタイプが設定されます。ContentStream自体には名前はつかず、文書オブジェクトを経由することになります。



CMISではContentStreamに対するCRUD操作のサービスも定義されています。setContentStreamサービスは文書オブジェクトに対して新しいContentStreamを割り当てる、あるいは既存のContentStreamを置き換えるという操作を行います。getContentStreamでは対象の文書オブジェクトのContentStreamを取得します。削除はdeleteContentStreamサービスです。さらに、編集後の文書をチェックインするcheckInサービスによってもContentStreamは更新されます。以上が、ContentStreamを直接操作することになるメソッドのすべてです。属性取得のgetPropertiesや検索クエリ経由ではContentStreamそのものを取得することはできません。また、setContentStreamやdeleteContentStreamの操作はそのContentStreamを保持している文書オブジェクトそのものについての更新行為とみなされるため最終更新日を保管する属性LastModificationDateの値も更新されます。



フォルダ



フォルダは他のオブジェクト(主に文書オブジェクトとサブフォルダになるフォルダオブジェクト)をリポジトリの階層構造を構成する基本要素です。それ自身も格納可能なオブジェクトであり、独立したオブジェクトでもあります。文書オブジェクトとは異なり、ContentStreamを持ちませんしバージョン管理の対象にもなりません。フォルダは親となるそのフォルダ自身を格納しているフォルダと、子となる「格納可能なオブジェクト」の集合から構成されます。



CMISのフォルダには他の基本オブジェクトにはない2つの制約がかけられています。1つは「全体のルートであるRoot Folder以外のフォルダオブジェクトは、必ずただ1つの親フォルダを持つ」、もう1つは「循環する包含関係は成立しない。自分自身を子孫にもつフォルダは作成できない」というものです。この2つからの帰結として、フォルダオブジェクトはリポジトリ内にツリー構造を構築することになります。(この制約は他の格納可能なオブジェクトには設定されていません。マルチファイリングが可能なリポジトリでは、複数のフォルダに格納される文書が存在しえますし、アンファイリングをサポートするリポジトリにはどのフォルダにも格納されない文書というものがありえます)



格納するオブジェクトのタイプに制限をかけることも可能です。フォルダオブジェクトにはAllowedChildObjectTypeIDsという復数の値を持ちうる属性が定義されており、そこに格納を許可する格納可能なオブジェクトのタイプの集合をセットします。この属性が設定されていない場合はすべての格納可能なオブジェクトのタイプが許可されたことになります。(オブジェクトタイプによる格納制限の機能をもたないリポジトリ製品の場合はこの値を設定しないことで整合をとります)



フォルダオブジェクトに対してもCRUD操作のメソッドが提供されています。オブジェクトをフォルダに格納するaddObjectToFolderサービス。フォルダからオブジェクトを取り除くremoveObjectサービス。オブジェクトの移動をさせるmoveObjectサービス。ツリー構造毎取り除くdeleteTreeサービス(アンファイリングのサポートがあれば取り除かれたサブツリーを保持されるが、そうでない場合は予め格納されているオブジェクトを削除する必要がある)。フォルダ構造のナビゲートして各種ノードの情報を取得するためのgetChildren、getDescendants、getFolderParent、getObjectParentなどのサービスがあります。ツリー構造のトラバースが深さ優先か幅優先かはリポジトリ製品の実装に依存します。ページング機能についても特に規定はありません。



フォルダの階層構造によるパスは"/"区切りで表現されます。また、文書オブジェクト自体はパス表現を持ちません。



関連



関連は、独立したオブジェクトではなく、ContentStreamを持たず、バージョン管理もされず、クエリの対象外で、格納可能でもありませんが、コントロール可能なオブジェクトです。つまり、関連の関連はつくれず、フォルダに格納されることもありませんが、ポリシの適用は受ける可能性があります。関連は、文書・フォルダ・ポリシなどの独立したオブジェクトを2つ、ソースオブジェクトとターゲットオブジェクトとして指定する形でそれらの関係性を表現するオブジェクトとして作成されます。関連は対象のオブジェクトを「汚染しません」。対象のオブジェクトに対して関連を設定したり、その関連の状態を変更しても、それらのオブジェクト自体が更新されたとはみなされません。(結果としてLastModificationDateの値も変わりません)



1つのオブジェクトに複数の関連を設定することもできますし、同じソースオブジェクトとターゲットオブジェクトの間に別の関連をさらに設定することも可能です。関連づけされているオブジェクトが削除された場合に関連を自動削除するかどうかについてはリポジトリの実装依存となります。また、関連自体にもタイプ付けが可能であり、アプリケーション独自の属性が割り当てられる可能性があります。



関連についてもベーシックなCRUD操作のサービスが提供されます。生成はcreateRelationshipサービスで行い、削除にはdeleteObjectサービスを使います。関連独自の操作としてはgetRelationshipsサービスを使って対象のオブジェクトに設定されている関連のセットを取り出すという方法も提供されています。



ポリシ



ポリシはアクセスコントロールリストや有効期限管理などの管理的な操作に関する情報を表現するオブジェクトです。しかし管理的な操作の詳細定義はCMISのスコープ外であるため、ここでは基本的なモデルだけが定義されています。詳細の機能はリポジトリ製品に依存しますが、このポリシオブジェクトを使うことでそれぞれの機能を識別するための文字列をハンドリングすることができるようになっています。



ポリシオブジェクトの生成、管理だけでなく、個々のオブジェクトにそれらのポリシを適用するための仕組みも定義されています。ポリシを適用できるオブジェクトを、「コントロール可能なオブジェクト」と呼びます。ポリシとそれらのオブジェクトの関係は多対多です。1つのポリシを複数のオブジェクトに適用することも、1つのオブジェクトに複数のポリシを適用することもできます。ポリシの適用は関連の設定と異なり対象のオブジェクトの状態を変更します。



ポリシのCRUD操作についても基本的なサービスが提供されています。createPolicyサービスで作成し、deleteObjectサービスで削除できます。独自の操作としてはポリシの適用を行うapplyPolicyサービス、適用済みのポリシを取り外すremovePolicyサービス、適用されているポリシのリストを取得するgetAppliedPoliciesサービスなどがあります。



��文責 Ishii Akinori ITC)