Wednesday, April 9, 2014

Alfrescoにカスタムindicatorを追加しよう(evaluatorも追加するよ)の巻

こんにちは。最近よく全身筋肉痛になる大谷です。

先日、弊社の花見兼BBQがあって家族を連れて行ったのですが、娘と遊んだり抱っこしたりしてたら見事に筋肉痛になりました。運動不足の賜物なので、もうそろそろ何がしかの運動を再開しないとまずいなと気持ちを新たにしている年度明けです。

前置きはさておき、今回はAlfrescoのindicatorとevaluatorを紹介したいと思います。以下の記述は現時点での最新バージョンであるAlfresco Community Edition 4.2.fに基づいています。


indicatorとは?


indicatorとはドキュメントの左上に表示されるアイコンのことで、ドキュメントの状況に応じてアイコンの表示/非表示を制御することができます。例えば標準のAlfrescoでは、ワークフローが回っているドキュメントや、特定のアスペクト(EXIF等)が付いているドキュメントにアイコンが表示されます。



デフォルトのindicatorは、以下のファイルの<indicators>セクションで定義されています。

<tomcat_dir>/webapps/share/WEB-INF/classes/alfresco/share-documentlibrary-config.xml
<indicators>
   <!-- Being edited by current user -->
   <indicator id="editing" index="10">
      <evaluator>evaluator.doclib.indicator.editing</evaluator>
   </indicator>
   <!-- Locked by current user -->
   <indicator id="lock-owner" index="10">
      <evaluator>evaluator.doclib.indicator.lockOwner</evaluator>
   </indicator>
   <!-- Locked with owner identified by cm:owner property -->
   <indicator id="locked" index="10" icon="lock-owner-16.png">
      <evaluator>evaluator.doclib.indicator.lockedOwner</evaluator>
      <labelParam index="0">{jsNode.properties.owner.displayName}</labelParam>
      <labelParam index="1">{jsNode.properties.owner.userName}</labelParam>
   </indicator>
   <!-- Locked with owner identified by cm:lockOwner property -->
   <indicator id="nodeLock" index="10" icon="lock-owner-16.png" label="status.locked">
      <evaluator>evaluator.doclib.indicator.nodeLocked</evaluator>
      <labelParam index="0">{jsNode.properties.cm_lockOwner.displayName}</labelParam>
      <labelParam index="1">{jsNode.properties.cm_lockOwner.userName}</labelParam>
      <override>locked</override>
   </indicator>
   <!-- Google Docs Editing -->
   <indicator id="google-docs-editing" index="10">
      <evaluator>evaluator.doclib.indicator.googleDocsEditing</evaluator>
      <override>editing</override>
   </indicator>
   ...

カスタムindicatorを追加したい場合は、このような設定を追加する必要があります。


evaluatorとは?


evaluatorとは、このindicatorやドキュメントアクションの表示条件を指定するものです。条件に応じてtrueもしくはfalseを返すというシンプルなもので、indicatorやアクションなど、Alfresco Shareの様々な場所で、条件指定のパラメータとして利用されています。実際に、デフォルトで定義されているindicatorを見てみても、evaluatorセクションにてどのevaluatorを使うかが指定されています。

デフォルトで利用可能なevaluatorは、以下のファイルで定義されています。

<tomcat_dir>/webapps/share/WEB-INF/classes/alfresco/slingshot-documentlibrary-context.xml
<!-- Being edited by the current user -->
<bean id="evaluator.doclib.indicator.editing" class="org.alfresco.web.evaluator.doclib.indicator.EditingEvaluator" />
<!-- Locked by the current user -->
<bean id="evaluator.doclib.indicator.lockOwner" class="org.alfresco.web.evaluator.doclib.indicator.LockOwnerEvaluator" />
<!-- Locked by another user -->
<bean id="evaluator.doclib.indicator.locked" class="org.alfresco.web.evaluator.doclib.indicator.LockedEvaluator" />
<!-- Locked by another user, indicated by cm:owner property (no cm:lockOwner) -->
<bean id="evaluator.doclib.indicator.lockedOwner" class="org.alfresco.web.evaluator.ChainedMatchAllEvaluator">
   <property name="evaluators">
      <list>
         <ref bean="evaluator.doclib.indicator.locked" />
         <ref bean="evaluator.doclib.indicator.hasOwner" />
         <ref bean="evaluator.doclib.indicator.noLockOwner" />
      </list>
   </property>
</bean>
...

独自のevaluatorを定義するにはこのような設定を追加する必要がありますが、具体的には以下の2通りの方法があります。
  1. 既存のevaluatorを利用してカスタムevaluatorを定義する
    • evaluator bean定義においてparent属性で親evaluatorを指定する
    • propertyセクションでプロパティを指定する
  2. カスタムevaluatorクラスを作成する
    •  org.alfresco.web.evaluator.BaseEvaluatorクラスを継承し、boolean evaluate()をoverrideして条件判定ロジックを記述する
    • このカスタムevaluatorクラスについてのevaluator bean定義を追加する
1.は、既存のevaluatorで実現可能な条件判定を行う場合に利用でき、xmlの設定を追加するだけで実現することができます。例えば、特定のタイプやアスペクト、属性値を判定したり、複数の条件の組み合わせで判定する場合などに利用できます。


カスタムindicatorを追加しよう


というわけで、早速カスタムindicatorを追加してみようと思います。今回のサンプルでは、更新日から1日以内のドキュメントにアイコンを表示するようなindicatorを作ります。

1. indicatorを定義する


まず、indicatorを定義します。定義は以下のとおり、share-config-custom.xmlに記述します。

<tomcat_dir>/shared/classes/alfresco/web-extension/share-config-custom.xml
<alfresco-config>
   <config evaluator="string-compare" condition="DocumentLibrary">
      <indicators>
         <indicator id="new-arrival" index="5">
            <evaluator>evaluator.doclib.custom.newArrival</evaluator>
         </indicator>
      </indicators>
   </config>
</alfresco-config>

Alfrescoをインストーラでインストールした場合などは既にshare-config-custom.xmlが存在すると思うので、その時は上記内容をマージしてください。

まず、indicatorセクションでは以下の属性を指定できます。
  • index :indicatorアイコンの表示順序。index値の小さいものから順に表示されます。
  • icon : アイコンファイル。省略すると、/res/components/documentlibrary/indicators/{id}-16.png が使われます。
  • label :アイコンのツールチップラベルのリソースキー。省略すると、status.{id}が使われます。
また、indicatorセクション内ではevaluatorセクションで表示条件を指定します。ここで指定するのはevaluatorのクラス名ではなくbean idです。evaluator.doclib.custom.newArrivalはデフォルトでは定義されていないevalutorですが、後ほど説明します。その他にも設定可能な項目がありますが、詳しくはAlfrescoのHelpを参考にしてください。

上記の例ではicon属性が省略されているため、new-arrival-16.pngという画像ファイルが表示されます。当然デフォルトでは入っていないので、以下のディレクトリに適当な画像(16x16)を追加してください。

<tomcat_dir>/webapps/share/components/documentlibrary/indicators/new-arrival-16.png

2. メッセージリソースを追加する


次に、ツールチップ用のメッセージリソースを追加します。先ほどの定義ではlabel属性も省略されていたので、リソースキーはstatus.new-arrivalとなります。必要なのは以下の2ファイル、メッセージファイルを読み込むためのbean定義ファイルとメッセージファイル本体です。

<tomcat_dir>/shared/classes/alfresco/web-extension/custom-slingshot-application-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>
   <bean id="evaluator.doclib.custom.newArrival" class="jp.aegif.alfresco.sample.CustomEvaluator"/>
   <bean id="share.custom.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
      <property name="resourceBundles">
         <list>
            <value>alfresco.messages.custom-messages</value>
         </list>
      </property>
   </bean>
</beans>


<tomcat_dir>/shared/classes/alfresco/messages/custom-messages.properties
# status.new-arrival=新着
status.new-arrival=\u65b0\u7740

1つ目のファイルのファイル名は*-context.xmlであれば何でも構いません(Alfrescoが自動的に読み込んでくれます)。evaluator.doclib.custom.newArrivalというidのbean定義については、後ほど説明するので今は無視してください。

3. evaluatorを追加する


最後にevaluatorを追加します。今回は更新日(cm:modifiedプロパティ)から1日未満か否かを判別するevaluatorが必要ですが、デフォルトで定義されているevaluatorだけでは実現できないため、カスタムevaluatorを作成します。

前述のとおり、org.alfresco.web.evaluator.BaseEvaluatorクラスを継承し、boolean evaluate()をoverrideして条件判定ロジックを記述します。以下にサンプルコードを記載します。

package jp.aegif.alfresco.sample;

import java.util.Date;
import org.alfresco.web.evaluator.BaseEvaluator;
import org.json.simple.JSONObject;
import org.springframework.extensions.surf.util.ISO8601DateFormat;

public class CustomEvaluator extends BaseEvaluator {
    @Override
    public boolean evaluate(JSONObject jsonObject) {
        String modifiedDateString = (String)((JSONObject)getProperty(jsonObject, "cm:modified")).get("iso8601");
        Date modifiedDate = ISO8601DateFormat.parse(modifiedDateString);
        Date now = new Date();
        if (now.getTime() - modifiedDate.getTime() < 24*60*60*1000) {
            return true;
        }
        return false;
    }
}

jsonObjectにドキュメントのメタデータ等が入っているので、そこからcm:modifiedプロパティの値を取得し、現在の時刻と比較します。コンパイルしたらjarでパッケージングするなどして、Alfresco Shareのクラスパス上にコピーします(<tomcat_dir>/webapps/share/WEB-INF/lib/ 等)

また、このクラスを新しいevaluatorとしてAlfrescoに認識させるためのbean定義を記述する必要がありますが、それが前述のevaluator.doclib.custom.newArrival beanになります。

以上でカスタムindicatorの準備は完了です。


動作確認しよう


では、実際に動作確認をしてみましょう。カスタムモジュールを配置したら、Alfrescoを再起動します。
Alfrescoが起動したら、リポジトリもしくはサイトのドキュメントライブラリにアクセスしてみましょう。ファイルをアップロードすると、更新から1日経っていないドキュメントに新着アイコンが表示されるはずです。もちろん、1日以上経ったドキュメントには新着アイコンが表示されません。


というわけで、今回はindicatorとevaluatorのカスタマイズについて紹介しました。比較的簡単に追加できますので、みなさんも是非挑戦してみてください。なお、ここで紹介したコードはこちらにありますので必要に応じて参照いただければと思います。

No comments: