Thursday, March 27, 2014

How to resolve huge merge conflicts?

Let's say you and another company have both modified a single long file, and the automatic resolution by git merge only results in a huge mess of "<<<" sections. You need to take matters in your own hands, and here is how.

Identifying files that need manual resolution

They first appear when you pull or merge:

git pull https://github.com/OtherCompany/CmisSync.git
[...]
Auto-merging CmisSync.Lib/Cmis/Database.cs
CONFLICT (content): Merge conflict in CmisSync.Lib/Cmis/Database.cs
[...]


If you want to test see the list again, just use git status:

git status
[...]
    both modified:      CmisSync.Lib/Cmis/Database.cs
[...]

Getting all necessary data

First, identify the ancestor, the commit from which the two branches have split:

git merge-base gds2-master master
1ae00e720522a8f099e8ec3dae0b34e3a8a603cd

There will be 4 versions involved:
- Ancestor
- Theirs
- My version before the merge
- The result version
Note that we don't keep Git's failed merge attempt.

git show 1ae00e720522a8f099e8ec3dae0b34e3a8a603cd:CmisSync.Lib/Cmis/Database.cs > /tmp/ancestor
git show gds2-master:CmisSync.Lib/Cmis/Database.cs > /tmp/theirs
git show master:CmisSync.Lib/Cmis/Database.cs > CmisSync.Lib/Cmis/Database.cs
cp CmisSync.Lib/Cmis/Database.cs /tmp/original

Merging


Then a three-way merge tool that allows editing.
There does not seem to be any such tool yet, so I use a combination of kdiff3 and meld:

kdiff3 /tmp/ancestor /tmp/theirs CmisSync.Lib/Cmis/Database.cs &
meld /tmp/original CmisSync.Lib/Cmis/Database.cs &

For each of their changes that you want to benefit from:
  1. Copy/paste the change from kdiff3's middle pane to Meld's right pane,
  2. Save,
  3. Refresh in kdiff3.
That's it!
Now you can mark the conflict as solved:

git add CmisSync.Lib/Cmis/Database.cs

Nicolas Raoul

Thursday, March 20, 2014

Alfresco 4.2のコンテンツ一覧表示をカスタマイズしよう

こんにちは。花粉症で目と鼻がやられ気味のおおたにです。

今回はコンテンツ一覧画面の表示内容をカスタマイズするためのメタデータテンプレートという仕組みについて説明します。なお、本エントリではAlfresco Community 4.2.fを使っています。


メタデータテンプレートを使うとどこがカスタマイズできるの?


コンテンツ一覧画面の「詳細表示」「シンプル表示」「ギャラリーの表示」の3形式について、以下の箇所の表示内容をカスタマイズできます。
  • バナー : コンテンツ名の上に条件に応じて表示されるもの。
  • ライン : コンテンツ名の下に表示されるプロパティやソーシャル関連機能などを1行ずつセットにしたもの。
シンプル表示

詳細表示

ギャラリーの表示


そもそもメタデータテンプレートって何?


メタデータテンプレートとは、このバナーやラインの表示セットを定義するものです。特徴は以下のとおりです。
  • 条件によって表示に利用するメタデータテンプレートが変わる。
    • 複数のテンプレートを定義し、それぞれに条件を設定する。
    • コンテンツ一覧を表示する際にコンテンツ毎に条件に一致するメタデータテンプレートを利用して表示を行う。
    • 条件に一致するメタデータテンプレートが存在しない場合は、フォールバック用defaultテンプレートが適用される。
  • 表示内容(バナー、ライン)、表示順序を指定できる。
  • バナーやラインごとに、表示条件、表示対象のビューを指定できる。
    • 表示条件に一致しないバナーやラインは表示されない。
標準の設定はShare設定ファイルの<metadata-templates>セクションで設定されています。

<tomcat_dir>/webapps/share/WEB-INF/classes/alfresco/share-documentlibrary-config.xml
<!--
   Custom Metadata Templates for the Document Library Browse View

   Use view="simple" or view="detailed" to limit the display to one particular view.
-->
<metadata-templates>
   <!-- Default (fallback) -->
   <template id="default">
      <banner index="10" id="lockBanner" evaluator="evaluator.doclib.metadata.hasLockBanner">{lockBanner}</banner>
      <banner index="20" id="syncTransientError" evaluator="evaluator.doclib.metadata.hasSyncTransientErrorBanner">{syncTransientError}</banner>
      <banner index="30" id="syncFailed" evaluator="evaluator.doclib.metadata.hasSyncFailedBanner">{syncFailed}</banner>
      <line index="10" id="date">{date}{size}</line>
      <line index="20" id="description" view="detailed">{description}</line>
      <line index="30" id="tags" view="detailed">{tags}</line>
      <line index="40" id="categories" view="detailed" evaluator="evaluator.doclib.metadata.hasCategories">{categories}</line>
      <line index="50" id="social" view="detailed">{social}</line>
   </template>

   <!-- Working Copies -->
   <template id="isWorkingCopy">
      <evaluator>evaluator.doclib.metadata.isWorkingCopy</evaluator>
      <banner index="10" id="lockBanner" evaluator="evaluator.doclib.metadata.hasLockBanner">{lockBanner}</banner>
      <banner index="20" id="syncTransientError" evaluator="evaluator.doclib.metadata.hasSyncTransientErrorBanner">{syncTransientError}</banner>
      <banner index="30" id="syncFailed" evaluator="evaluator.doclib.metadata.hasSyncFailedBanner">{syncFailed}</banner>
      <line index="10" id="date">{date}{size}</line>
      <line index="20" id="description" view="detailed">{description}</line>
   </template>

   <!-- Dictionary Models -->
   <template id="dictionaryModel">
      <evaluator>evaluator.doclib.metadata.isDictionaryModel</evaluator>
      <banner index="10" id="lockBanner" evaluator="evaluator.doclib.metadata.hasLockBanner">{lockBanner}</banner>
      <banner index="20" id="syncTransientError" evaluator="evaluator.doclib.metadata.hasSyncTransientErrorBanner">{syncTransientError}</banner>
      <banner index="30" id="syncFailed" evaluator="evaluator.doclib.metadata.hasSyncFailedBanner">{syncFailed}</banner>
      <line index="10" id="date">{date}</line>
      <line index="20" id="description" view="detailed">{description}</line>
      <line index="30" id="dictionaryModel" simpleView="true">{modelActive label.modelActive}{modelName label.modelName}{modelDescription label.modelDescription}</line>
   </template>

   <!-- Replication Transfer Targets -->
   <template id="transferTarget">
      <evaluator>evaluator.doclib.metadata.isTransferTarget</evaluator>
      <banner index="10" id="lockBanner" evaluator="evaluator.doclib.metadata.hasLockBanner">{lockBanner}</banner>
      <banner index="20" id="syncTransientError" evaluator="evaluator.doclib.metadata.hasSyncTransientErrorBanner">{syncTransientError}</banner>
      <banner index="30" id="syncFailed" evaluator="evaluator.doclib.metadata.hasSyncFailedBanner">{syncFailed}</banner>
      <line index="10" id="date">{date}</line>
      <line index="20" id="description" view="detailed">{description}</line>
      <line index="30" id="transferTarget" simpleView="true">{trx_enabled label.trx_enabled}{trx_endpointhost label.trx_endpointhost}{trx_endpointport label.trx_endpointport}</line>
   </template>
</metadata-templates>

というわけで、share-config-custom.xmlの<config evaluator="string-compare" condition="DocumentLibrary">セクションで設定を上書きもしくは追加することでメタデータテンプレートをカスタマイズすることができます。


実際にカスタマイズしてみよう


というわけで、実際にメタデータテンプレートをカスタマイズしてみましょう。ここでは、画像ファイルの場合にExifメタデータを表示するというカスタマイズを行ってみます。まずは以下のようなメタデータテンプレートを作成します。defaultテンプレートをベースに、evaluatorとExif用のlineを追加しつつ、description行を削除しています。share-config.custom.xmlに既に同じconfigセクションがある場合は適宜マージしてください。

<tomcat_dir>/shared/classes/alfresco/web-extension/share-config-custom.xml
<alfresco-config>
   <config evaluator="string-compare" condition="DocumentLibrary">
      <metadata-templates>
         <template id="exif">
            <evaluator>evaluator.doclib.indicator.exifMetadata</evaluator>
            <banner index="10" id="lockBanner" evaluator="evaluator.doclib.metadata.hasLockBanner">{lockBanner}</banner>
            <banner index="20" id="syncTransientError" evaluator="evaluator.doclib.metadata.hasSyncTransientErrorBanner">{syncTransientError}</banner>
            <banner index="30" id="syncFailed" evaluator="evaluator.doclib.metadata.hasSyncFailedBanner">{syncFailed}</banner>
            <line index="10" id="date">{date}{size}</line>
            <line index="20" id="exif" view="detailed">{exif_pixelXDimension label.exif_pixelXDimension}{exif_pixelYDimension label.exif_pixelYDimension}{exif_exposureTime label.exif_exposureTime}{exif_fNumber label.exif_fNumber}{exif_isoSpeedRatings label.exif_isoSpeedRatings}</line>
            <line index="30" id="tags" view="detailed">{tags}</line>
            <line index="40" id="categories" view="detailed" evaluator="evaluator.doclib.metadata.hasCategories">{categories}</line>
            <line index="50" id="social" view="detailed">{social}</line>
         </template>
      </metadata-templates>
   </config>
</alfresco-config>

  •  evaluator : テンプレートの利用条件。evaluatorのビーンIDを指定します。ここではexif:exifアスペクトを持つか判定するevaluator.doclib.indicator.exifMetadataを使います。もちろんカスタムevaluatorを定義して設定することもできます。
  •  banner : バナーを定義します。
  •  line : ラインを定義します。exifというlineを追加しています。
  •  バナー、ラインの設定内容は以下のとおりです。
    • index : 小さい順に表示します。
    • view : detailedで詳細表示/ギャラリー表示に、simpleでシンプル表示に、指定しないと全てに表示します。exif行はdetailedを指定しています。
    • evaluator : バナー、ラインの表示条件を指定します。エバリュエータのビーンIDを指定します。
    • 表示内容はレンダラ({}で指定してあるもの)で設定します。
      • 事前定義されたレンダラ {<レンダラ名>} : {date}, {social}など。<tomcat_dir>/webapps/share/components/documentlibrary/documentlist.js で定義されているものを利用できます。必要に応じてレンダラを修正/追加することもできます。
      • プロパティ表示レンダラ {<プロパティ名> <ラベルのメッセージリソースキー} : 指定したプロパティを表示します。プロパティ名はコロン(:)の代わりにアンダーバー(_)を使います。

さらに、今回表示するプロパティ表示レンダラのメッセージリソースが無いので、以下の2ファイルを作成します。

<tomcat_dir>/shared/classes/alfresco/web-extension/custom-messages-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="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
label.exif_pixelXDimension=\u753b\u50cf\u5e45
label.exif_pixelYDimension=\u753b\u50cf\u9ad8
label.exif_exposureTime=\u9732\u5149\u6642\u9593
label.exif_fNumber=F\u5024
label.exif_isoSpeedRatings=ISO\u611f\u5ea6

以上のファイルを追加したら、Alfrescoを再起動します。


動作確認しよう


Alfrescoが正常に起動したら、適当なフォルダに画像ファイルをアップロードしてみましょう。Exif情報を持つ画像ファイルは今回カスタマイズした表示となり、付いていないものはデフォルトの表示になっていればカスタマイズ成功です。

なお、プロパティ表示レンダラは、表示対象のプロパティ値が空の場合にそのプロパティを表示しないのでご注意ください。値が空の場合にも何らかの表示をさせたいという場合は、レンダラを別途定義する必要があります。


さいごに


メタデータテンプレートは、Alfrescoのコンテンツ一覧表示を設定ファイルだけでカスタマイズするとても強力な仕組みです。カスタムエバリュエータと組み合わせることで柔軟に表示内容をカスタマイズすることができるので、是非チャレンジしてみてください。

なお、AlfrescoのHelpにもメタデータテンプレートに関する記載があるので参考にしてください。




Thursday, March 13, 2014

ECM & Business Intelligence: Integration example with Alfresco, Pentaho, CmisSync

Is your company using a server to store all of the company's documents (contracts, manuals, etc)?
If yes, this document server contains a large part of your company's information.
It makes it a good target for Business Intelligence: Using analytics tools to get useful insight about how your company works.

Let's do it with this scenario:
- Employees all have a "Expenses" folder on their computers, where they put their company expenses receipts (picture of train ticket when visiting a client in another city, HTML file of the command confirmation page after buying a cartridge for the company's printer, PDF receipt of a license purchase, etc).
- Employees enter the amount paid for each of these items, to be reimbursed by the company at the end of the month.

We can implement this system easily with Alfresco, Pentaho, CmisSync, thanks to the CMIS standard.

Part 1: Gathering receipt data (aka ECM part)


First, define a "aegif:expense" type on your document server (replace "aegif" with your company's name). Define an "amount" property for this type. (This can be done on any modern document management server, for instance Alfresco or NemakiWare)

Second, how to gather the receipts from each user's laptop?

→ Have each employee use CmisSync, which synchronizes automatically a folder between their local "expenses" folder and their remote "expenses" folder.


On the server side, have a folder rule that applies the "expense" type to any file that the employee puts in this folder.

How can an employee specify the amount associated to each expense file?

→ By using the context menu provided CmisSync Business. This context menu allows employees to edit document metadata. So, for each picture of a receipt they can enter the amount (by the way, this task can easily be outsourced at this point).

Now, all of the data is in your document server.

Part 2: Analyzing the data (aka BI part)


Let's analyze this data with Pentaho, a Business Intelligence suite.
More precisely, we will use Pentaho Data Integration (also known as Spoon)

All modern document management servers offer a CMIS API, which Pentaho can use thanks to the CMIS Input plugin. This plugin can be installed very easily from PDI's Marketplace (free).

Set up a transformation with the CMIS input feeding a table output as seen below:


Set up the CMIS Input step to select the documents you want data about. In our example, we want all docume

The table gets filled with all of the documents' metadata: filename, size, and of course the "amount" property we have defined.

You can then use that data with an OLAP cube and perform drill-downs, or generate reports. To close the loop, you may even want to set up a job to upload generated reports back to the document server.

Conclusion

Bridges are needed between the ECM and Business Intelligence worlds, and the CMIS standard is the most effective way to build them.

I want to thank Francesco Corti for developing Pentaho's CMIS Input plugin and making it Open Source, and Jeff Potts for his answers about the CMIS implementation provided by Alfresco.

I recently did a demo on this topic at the Japan Pentaho User Group, here are my slides (partly in Japanese).
Nicolas Raoul

Wednesday, March 5, 2014

インストーラでインストールしたAlfresco 4.2が起動しない

こんにちは、大谷です。先日の大雪で庭木がぽっきりいっちゃいましたが、なんとか無事にやっております。

今回は、WindowsにインストーラでインストールしたAlfresco 4.2が起動しないことがあったので、その原因と解決方法を紹介します。なお、本エントリでは4.2.eを使っています(というか4.2.eのインストール時にひっかかった…)。

症状


Windowsの端末にインストーラを使ってAlfrescoをインストール(インストールの方法はこちらです)。インストールは成功し、さてAlfrescoを起動してアクセスしてみよう!と思ったら、うまくアクセスできないというかAlfrescoが起動に失敗してるっぽい…

一応Alfrescoインストールディレクトリに出力されてるログを見てみると、そもそもsolr.logしか出力されてなくて、しかもこんなエラーが出てますよ先生
12:10:11,802 ERROR [org.apache.solr.servlet.SolrDispatchFilter] Could not start SOLR. Check solr/home property
java.lang.UnsupportedClassVersionError: org/alfresco/solr/AlfrescoCoreAdminHandler : Unsupported major.minor version 51.0

Unsupported major.minor version 51.0 といえば、JRE1.6をサポートしてないよ!ってエラーですね。Alfrescoは4.2からJRE1.7が必須となっているのですが、AlfrescoをインストールするときにJavaも選んでわざわざ一緒にインストールしたのに何でこれ起きるの!?

解決方法


何がともあれ、Windowsサービスの登録内容を確認してみます。
> cd <alfresco_dir>\tomcat\bin
> tomcat7w.exe //ES//alfrescoTomcat

Javaタブを見てみると、分かりましたよ原因。「Java Virtual Machine」が、Alfrescoと共にインストールされたJREを指してない!多分環境変数JAVA_HOMEかJRE_HOMEあたりを参照して設定してしまってるんですねこれ(筆者はそこで1.6を設定しております)。
というわけで、<alfresco_dir>\java\jre\bin\server\jvm.dll に設定変更してサービスを再起動すると無事動くようになりましたとさ。