5.Bao基礎編その2

今回は、Baoの各メソッドを実行していって見ましょう。

しかし、実行するためには色々前準備が必要で面倒……。というわけで、幸いBuriソースコード中にTestが含まれている(testソースフォルダのorg.seasar.buri.bao.test.FurnitureManagementBaoTest2.java)ので、これを元にします。ただ、このままではちょっと説明しづらいので、コピーして書きなおしてみました。





01 package org.seasar.buri.bao.test;

02 

03 import java.util.Date;

04 import java.util.List;

05 

06 import org.seasar.buri.bao.FurnitureManagementBao;

07 import org.seasar.buri.dto.FurnitureItemDto;

08 import org.seasar.buri.engine.BuriEngine;

09 import org.seasar.extension.unit.S2TestCase;

10 

11 public class FurnitureManagementBaoTest2 extends S2TestCase {

12     private BuriEngine buriEngine_;

13     private FurnitureManagementBao fmBao_;

14 

15     public FurnitureManagementBaoTest2(String arg0) {

16         super(arg0);

17     }

18 

19     protected void setUp() throws Exception {

20         super.setUp();

21         include("org/seasar/buri/bao/test/dicon/FurnitureManagement.dicon");

22     }

23     

24     public void testFMBaoTx() {

25         buriEngine_.getWorkflows().readWorkFlowFromResource("資産管理","FurnitureManagement.xpdl");

26         

27         List datas;

28         //購買備品

29         FurnitureItemDto buyItemDto = new FurnitureItemDto();

30         buyItemDto.setName("T45_001");

31         buyItemDto.setType("PC");

32         buyItemDto.setAcquisitionTypeBuy();

33         buyItemDto.setAcquisition(new Date());

34 

35         //購買備品を登録

36         fmBao_.enterItem(buyItemDto);

37 

38         //リース備品

39         FurnitureItemDto leaseItemDto = new FurnitureItemDto();

40         leaseItemDto.setName("T45_002");

41         leaseItemDto.setType("PC");

42         leaseItemDto.setAcquisitionTypeLease();

43         leaseItemDto.setAcquisition(new Date());        

44 

45         //リース備品を登録

46         fmBao_.enterItem(leaseItemDto);

47 

48         //「利用中」の備品リスト取得

49         datas = fmBao_.getNowUse();

50         System.out.println("「利用中」のデータ" + datas);

51         assertEquals(2, datas.size());

52         

53         //「利用中」の備品の中から、"T45_002"という名前のDTOを取得

54         FurnitureItemDto findDto = new FurnitureItemDto();

55         findDto.setName("T45_002");

56         datas = fmBao_.findNowUse(findDto);

57         System.out.println("名前が「T45_002」のデータ" + datas);

58         assertEquals(1, datas.size());

59         

60         //「利用中」の備品の中から、タイプが"PC"であるDTOを取得

61         findDto = new FurnitureItemDto();

62         findDto.setType("PC");

63         datas = fmBao_.findNowUse(findDto);

64         System.out.println("タイプが「PC」で「利用中」のデータ" + datas);

65         assertEquals(2, datas.size());

66 

67 

68         //購買備品の使用期間終了

69         fmBao_.timeorverItem(buyItemDto.getFurnitureID());

70         

71         //「償却期間終了」の備品リスト取得

72         datas = fmBao_.getEndDepreciation();

73         System.out.println("「償却期間終了」状態のデータ" + datas);

74         assertEquals(1, datas.size());

75 

76 

77         //「利用中」の備品リスト取得

78         datas = fmBao_.getNowUse();

79         System.out.println("「利用中」状態のデータ" + datas);

80         assertEquals(1, datas.size());

81 

82         //リース備品の使用期間終了

83         fmBao_.timeorverItem(leaseItemDto.getFurnitureID());

84         

85         //「リース終了」の備品リスト取得

86         datas = fmBao_.getEndLease();

87         System.out.println("「リース終了」状態のデータ" + datas);

88         assertEquals(1, datas.size());

89 

90         //「利用中」の備品リスト取得

91         datas = fmBao_.getNowUse();

92         System.out.println("「利用中」状態のデータ"+ datas);

93         assertEquals(0, datas.size());

94         

95     }

96 

97 }


まず、このテストケースはS2Unitを利用してます。S2Unitを使っているということは、setUp()でdiconファイルをインクルードさせておくと、フィールド変数にdicon内で定義したコンポーネントが入ってきて、各テストメソッドではそのコンポーネントを利用できる、ということになります。
このソース上では21行目でdiconを読み込んでます。diconの中身はこれ。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
	"http://www.seasar.org/dtd/components21.dtd">
<components>
	<include path="bao.dicon"/>
	<include path="org/seasar/buri/dicon/allTestDao.dicon"/>
	
	<component class="org.seasar.buri.bao.FurnitureManagementBao">
		<aspect>bao.interceptor</aspect>
	</component>
</components>

FurnitureManagementBaoにbao.interceptorというASPECTが適用されてます。FurnitureManagementBaoは単なるインターフェースなので、このbao.interceptorってのがBaoの全挙動をコントロールしているということに。このbao.interceptorの中身を見たい気もしますが、とりあえずおいといて次へ。


testメソッドであるtestFMBaoTx()では、最初にXPDLを読み込んでいます。これと同等のことは、dicon内で定義することもできて、その場合には、buri2.dicon内のWakanagoFlowsImplコンポーネントのところでこう書いておけばOKです。

	<component class="org.seasar.buri.impl.WakanagoFlowsImpl">
		<aspect>BuriInterceptorChain</aspect>
		<initMethod name="readWorkFlowFromResource">
			<arg>"資産管理"</arg>
			<arg>"FurnitureManagement.xpdl"</arg>
		</initMethod>
	</component>

ここまでが準備段階、これでBaoを利用できるようになります。
testメソッドでは、まず、FurnitureManagementDtoのインスタンスを生成し、FurnitureManagementBao#enterItemメソッドを呼び出し、そのインスタンスをBaoに渡します。これでワークフローにDtoを登録したことになります。これでフローが開始されます(28〜46行目)。この例では2つのインスタンスを作っていますが、2つの大きな違いは、最初のものは購買備品(AcquisitionTypeBuyをセットしている)で、2つめがリース備品(AquisitionTypeLeaseをセットしている)ってことです。

さて次に、これらがほんとに登録されたのか参照します。これが48〜51行目。ここで実行しているFurnitureManagementBao#getNowUse()メソッドは、メソッド名が「get」で始まっているので、前回見たとおり、データ取得用のメソッドになります。そして、どんなデータを取得するかは、Baoの定数アノテーションを見れば分かります。FurnitureManagementBao内で、

    public static String getNowUse_ACTIVITY = "利用中";

このように記述されてますので、これは、「利用中」状態のデータを取得するメソッド、ということが分かります。enterItemメソッドでデータを登録すると、まず「利用中」状態になる、ってことです。
でも、ここでフロー定義を思い出してください(下図参照)。定義上では、「利用中」より前に「備品登録」という状態があります。

この「備品登録」はなぜ飛ばされてしまったのでしょうか?その答えは、「備品登録」と「利用中」の2つのプロパティを見比べてみればわかります。「備品登録」の方は、finish modeがAutomatic、「利用中」の方は、manualと定義されてます。Automaticの場合には、その名の通り自動的に終了し、次の状態に移ってしまうのです。一方manualだと、勝手には終了することはなく、そこで待機することになります。

では、さらにテストメソッドの解説を進めていきます。53〜65行目ではFurnitureManagementBaoのfindNowUseメソッドを実行しています。このメソッドは、「find」で始まってるので、データ取得用メソッドです。ですが、このメソッドはFurnitureManagementDtoを引数にしています。この場合引数のDtoは、取得の条件を表すオブジェクトという意味になります。引数のDtoと同一のプロパティを保持するデータのみを取得します。
53〜58行目の場合、nameプロパティが「T45_002」であるDtoのみ取得しているため、返り値は1件のみ。一方、60〜65行目では、typeプロパティが「PC」であるDtoを取得しようとしており、2つとも返ってきていることを確認しています。

さて次は、この「利用中」の状態から、別の状態に遷移させてみましょう。今回のフローでは「利用中」の次は「期間終了」。この遷移のときに呼びだすメソッドとして、FurnitureManagementBaoではtimeorverItemメソッド(timeoverのスペルミス?)が定義されています。このメソッドを呼び出しているのが、68〜93行目。前半の68〜80行目は、timeorverItemメソッドに、購買備品データのIDを渡して呼び出してます。呼び出した結果、「償却期間終了」状態のデータを取得するgetEndDepreciationメソッドでこの購買備品のデータを取得できるようになり、「利用中」状態のデータを取得するgetNowUseメソッドの返り値には、購買備品データが無くなりました。購買備品が「利用中」状態から「償却期間終了」状態へ遷移したのです。そして同様に、82〜93行目ではリース備品に対してtimeorverItemメソッドを呼んでます。こちらは、「利用中」状態(getNowUseで取得できる状態)から「リース終了」状態(getEndLeaseで取得できる状態)へ遷移しています。

同じメソッドを実行したのになぜ遷移先が変わるのか……。これは、フローの定義を見ていく必要があります。
まず、データ遷移用のメソッド、timeorverItemメソッドが呼ばれたことで、「利用中」状態から「期間終了」状態へ遷移します。そして、この「期間終了」Activityの定義では、Finish modeがAutomatic。だから、自動的に次の状態に移ることになります。だけど、今回の場合は、遷移先が2つに分かれているので、どっちに遷移するのかこれだけでは分かりません。そこで、その条件が定義されている必要があります。この定義に関しては、第三回で纏めてたのですが、再掲します。XPDL内「期間終了」ActivityのPostconditionとして、こんな感じの定義が記述されているのです。

遷移 条件
期間終了→償却期間終了 #data.isBuying == true
期間終了→リース終了 #data.isLease == true

#dataというのがDtoインスタンスを示しています。そのインスタンスのisBuyingがtrueなら(購買備品なら)「償却期間終了」Activityへ遷移、isLeaseがtrueなら(リース備品なら)「リース終了」Activityへ遷移する、というのがこの定義の言わんとしているところなのです。

さて、これでFurnitureManagementBaoのメソッドは一通り実行したことに。なんとなく使い方は分かってきたかな……。
要は、Baoの役割は、ワークフロー上のデータを取得するのと、そのデータを遷移させるのと、2つの役割があるよ、ってことっすね。インターフェース定義するだけでこれだけのことが出来るってのは便利便利。
次回は、前回スルーしてたConverterを見てみるかな?、ということで今回はおしまい。