2009年6月17日水曜日

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

2/3を公開してからかなり時間がたってしまいました。申し訳ありません。
#実は1度にまとめて書いているので、単純なアップロード作業のミスなのですが・・・



リポジトリのモデルや基本となるオブジェクトタイプについてはすでにご説明しているので、本稿では独自のオブジェクトタイプの実装に関する規程と、各オブジェクトに対する操作をとりまとめたサービスについてご紹介したいと思います。



カスタムオブジェクトタイプ



オブジェクトタイプは属性の組み合わせによって定義されます。CMISにおけるオブジェクトは強い型付けがなされ、未定義の属性をインスタンスレベルで後から追加するという仕組みはありません。(JCRにおけるResidual属性、WebDAVにおけるDead属性にあたるものはサポートされません。定義にない属性が検出された場合は例外として扱います)



オブジェクトタイプ自体のユニークネスを確保するため、システムからユニークな識別子をタイプIDとして割り当てます。また、オブジェクトタイプの定義にも継承による階層構造を利用できます。継承の仕組みは以下のルールに従います。



・ルートタイプは親タイプをもたない。ルートでないタイプは必ず1つだけ親タイプを持つ。
・オブジェクトタイプは(それ自体オブジェクト型のものを含む)属性の集合として定義される。属性のオブジェクト型には継承機能は適用されない。
・サブタイプには親タイプで定義されている属性がすべて適用される。何かの理由で親の属性の一部を継承したくない場合は、定義ではなく値を未設定とする。
・クエリにタイプ名を使った場合は子孫タイプのすべてが対象となる。
・ルートタイプは基本オブジェクトタイプである文書・フォルダ・関連・ポリシの4つのみ。



さらにすべてのオブジェクトタイプに共通する属性がいくつか定義されています。



・ObjectTypeId オブジェクトタイプの識別子。リポジトリ内でユニークでなければならない。
・ObjectTypeQueryName SQLクエリ内でのテーブル名。
・ObjectTypeDisplayName アプリケーションに表示される名前。
・ParentTypeId 親タイプのID。
・RootTypeQueryName ルートタイプのテーブル名。
・Description アプリケーションによるタイプの説明。使いかたなど。
・Creatable 当該オブジェクトタイプのオブジェクトを新規作成可能かどうかを判別するフラグ。
・Queryable クエリで使えるかどうかを判別するフラグ。関連クラスには適用できない。
・Controllable ポリシを適用可能かどうか判別するフラグ。
・IncludeInSuperTypeQuery 親タイプを指定したクエリの対象とするかを判別するフラグ。



文書タイプのサブタイプを定義するために、追加で以下が定義されています。



・Fileable フォルダに格納できるかどうかを判別するフラグ。関連の場合はFalse。
・Versionable バージョン管理の対象かどうかを判別するフラグ。
・ContentStreamAllowed ContentStreamを持てるかどうかを表現する。"持てない""持てる""必須"の3段階。



関連タイプ向けにも追加で以下が定義されています。
・AllowedSourceTypes ソースオブジェクトとして許可されるタイプのID。
・AllowedTargetTypes ターゲットオブジェクトとして許可されるタイプのID。



さらにカスタムの属性を定義するために、各属性項目自体が持つ属性の規定があります。



・PropertyName 属性の名前。SQLクエリのカラム名としても利用。
・PropertyId リポジトリ内でユニークなID。
・DisplayName アプリケーションで表示される名前。
・Description アプリケーションによる属性の説明。使いかたなど。
・IsInherited 親タイプですでに定義されていたかどうか。
・PropertyType 属性値のタイプ。
・Cardinality 単一の値を持つか、複数の値を持つか。
・Choices オプショナルの属性で、アプリケーションが値選択式のUIを利用できるようにする。
・OpenChoice Choices利用時に自由記入を可能にする。
・Required 必須項目にする。
・DefaultValue デフォルト値を設定。
・Updatability 属性値の変更可能性。「読み取り専用」「変更可」「チェックアウト時変更可」の3つがある。
・Queryable クエリに利用できるかどうか。
・Orderable 整列可能かどうか。
・Precision 小数値向け。精度。
・MinValue 整数値向け。最小値。
・MaxValue 整数値向け。最大値。
・MaximumLength 文字列向け。最大長。
・SchemaURI XML属性向け。スキーマのURI。
・Encoding XML属性向け。エンコーディング情報。



以上の項目を組み合わせて新しいオブジェクトタイプを作成することができます。






クエリ



CMISで定義されているクエリ文法はSQL-92を下敷きにしたものになっています。また、データ操作については特に規定されておらず、読み取り専用の「リレーショナルビュー」という位置づけのものになります。



コンテンツリポジトリの情報を組み合わせたヴァーチャルなテーブルを想定し、そこへのSELECT文による問い合わせを行うためのルールが整備されている、という状況です。具体的には、オブジェクトタイプ(とその派生タイプ)毎にテーブルが作成され、行は個別のオブジェクトを、列は属性を表現する形になります。(値がセットされていなかったり、継承を受けていない属性の値はNULLになります)



基本的には属性値のテーブルになるので、ContentStream自体への直接的なアクセス手段はこのCMIS SQLの枠組みでは定義されていません。Object IDを取得したあとでメソッド経由でアクセスすることになります。



演算子や複数の値を持ち得る属性と単一の値しかない属性の違いによる振る舞いの違いについて仕様書上には幾つかの言及があるのですが、ここでは割愛させて頂くとして、4つほど特徴的な構文(述語、関数)があるのでそれらについてだけ簡単に紹介したいと思います。



・CONTAINS([識別子],<検索文字列>) 全文検索による条件づけ。
・SCORE() 全文検索によるスコアの取得。
・IN_FOLDER([識別子],<フォルダのID>) 対象フォルダに格納されている、という条件を表現。
・IN_TREE([識別子],<フォルダのID>) 対象フォルダもしくはそのサブ(子孫)フォルダに格納されている、という条件を表現。



サービス



・共通サービス要素
 特にメソッドは定義されず、例外などが整備されています。例えば以下の例外はCMISサービス全体で共有され、各サービスともに発生させる可能性があります。
 InvalidArgmentException 引数が不正
  ConstraintViolationException 制約が満たされていない
  ObjectNotFoundException オブジェクトが見つからない
 PermissionDeniedException 権限が不十分
 OperationNotSupportedException オペレーションがサポート(許可)されていない
 RuntimeException (随時発生)
 その他特定のサービスからしかあがらないような例外も定義されています。
 ContentAlreadyExistsException 作成しようとした文書がすでに存在している
 FilterNotValidExeption プロパティフィルタの条件にあわない(属性値を取得するメソッドは、対象属性を制限する"プロパティフィルタ”という文字列を受け取ることがあります。プロパティフィルタの実体はワイルドカードである*か属性名をカンマで繋げた文字列です)
 StorageException 容量不足などのストレージエラー
 StreamNotSupportedException 対象のタイプはContentStreamをサポートしていない
 UpdateConfilctException 更新の失敗(ロックをせずに複数ユーザの更新が重複しそうになった場合など)
 VersioningException 版管理上の不整合(対象がすでに最新版でなくなっているなど)



・リポジトリサービス
 getRepositories 対象サービスエンドポイントのアクセス可能なリポジトリのリストを取得
 getRepositoryInfo リポジトリの情報を取得。名前、URI、対応している機能など
 getTypes リポジトリ内に定義されているオブジェクトタイプの一覧を取得
 getTypeDefinition 個別のオブジェクトタイプの定義を取得



・ナビゲーションサービス
 getDescendants リポジトリのツリー上子孫となるオブジェクトの一覧を取得
 getChildren ツリー上直下の子となるオブジェクトの一覧を取得
 getFolderParent 格納されているフォルダを取得。オプションによって祖先フォルダすべての一覧も取得可能
 getObjectObjectParents 対象オブジェクトを格納しているフォルダの一覧を取得(マルチファイリング)
 getCheckedoutDocuments チェックアウトされている文書の一覧を取得



・オブジェクトサービス
 createDocument 文書を作成
 createFolder フォルダを作成
 createRelationship 関連を作成
 createPolicy ポリシを作成
 getAllowableActions 対象オブジェクトに対して実行可能なCMISサービスコールの一覧を取得
 getProperties 属性の一覧を取得
 getContentStream ContentStream(ファイル実体)を取得
 updateProperties 属性を更新
 moveObject オブジェクトを(リポジトリのツリー上で)移動
 deleteObject オブジェクトを削除
 deleteTree サブツリーごとオブジェクトを削除
 setContentStream ContentStreamを割当
 deleteContentStream ContentStreamを削除



・マルチファイリングサービス
 addObjectToFolder 対象オブジェクトをさらに別のフォルダに格納
 removeObjectFromFolder フォルダから対象オブジェクトを削除(撤回)



・ディスカバリサービス
 query CMIS SQLの実行



・バージョン管理サービス
 checkOut チェックアウト
 cancelCheckOut チェックアウトの取り消し
 checkIn チェックイン
 getPropertiesOfLatestVersion 最新バージョンの属性一覧を取得
 getAllVersions すべてのバージョンを取得
 deleteAllVersions すべてのバージョンを削除



・関連サービス
 getRelationships 関連の一覧の取得



・ポリシサービス
 applyPolicy ポリシの適用
 removePolicy ポリシの削除
 getAppliedPolicies 適用済みポリシ一覧の取得



機会があれば次は実際にCMISを使った開発の簡単なチュートリアルなどを紹介したいと思います。



��文責 Ishii Akinori ITC)