OSWorkFlow深入淺出(6)---Step2詳解

在上一下節中,我們曾寫道講解了step的prefunction以及postfunction,其實都是標籤層面的講解,因爲在後文中我們將要詳細描述Function組建,這在osworkflow中佔有非常重要的位置,上一節中還有兩個step非常重要的概念,那就是split和join,我們在本節中詳細說明。

先來說說split和join的作用是什麼,我們不妨來看看如下的狀態圖。


通過上圖可以看出當請假條直接上司審批之後,還需要兩個部門領導人審批,只有兩個領導審批通過之後,最終到最高領導處審批,最高領導審批通過纔算成功!

通過上面的文字描述和圖示,我們不難看出有兩個非常重要的概念,那就是拆分和聯合,也就是split和join,這種情況也是一個流程引擎中必須具備的功能。

針對上面的流程圖,我們不難寫出配置文件,配置文件如下所示!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd">
<workflow>
	<initial-actions>
		<action id="100" name="請假初始化">
			<results>
				<unconditional-result old-status="Finished"
					status="Underway" step="1" owner="step" />
			</results>
		</action>
	</initial-actions>
	<steps>
		<step id="1" name="員工請假">
			<actions>
				<action id="1" name="請假">
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" step="2" />
					</results>
				</action>
			</actions>
		</step>
		<step id="2" name="直接上司審批">
			<actions>
				<action id="2" name="上司審批">
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" split="1" />
					</results>
				</action>
			</actions>
		</step>
		<step id="4" name="部門領導A審批">
			<actions>
				<action id="4" name="領導A審批">
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" join="1" />
					</results>
				</action>
			</actions>
		</step>
		<step id="5" name="部門領導B審批">
			<actions>
				<action id="5" name="領導B審批">
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" join="1" />
					</results>
				</action>
			</actions>
		</step>
		<step id="6" name="最高領導審批">
			<actions>
				<action id="6" name="最高領導審批" finish="true">
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" step="6" />
					</results>
				</action>
			</actions>
		</step>
	</steps>
	<splits>
		<split id="1">
			<unconditional-result old-status="Finished"
				status="Underway" step="4" />
			<unconditional-result old-status="Finished"
				status="Underway" step="5" />
		</split>
	</splits>

	<joins>
		<join id="1">
			<conditions type="AND">
				<condition type="beanshell">
					<arg name="script"><![CDATA[
"Finished".equals(jn.getStep(4).getStatus())
                    && "Finished".equals(jn.getStep(5).getStatus())
          ]]></arg>
				</condition>
			</conditions>
			<unconditional-result old-status="Finished"
				status="Underway" step="6" />
		</join>
	</joins>
</workflow>
 對照着上文中的描述,我們將xml寫了出來,其中在joins中有一個非常重要的上下文常量,叫做jn,其中jn是JoinNodes對象的一個實例,在該示例中提供了若干個方法,其中有一個方法getStep,可以通過他獲取step的實例對象,在後文中講解源碼的時候都會講解到,耐心等待吧。

寫完了配置文件,就直接單元測試唄,看看我們的流程是否行得通!

@Test
	public void testJoinAndSplit()
	{
		long id ;
		try {
			id = wf.initialize("joinsplit", 100, null);
			List currentSteps = wf.getCurrentSteps(id);
			/*系統初始化之後只有一個step可以執行,那就是step,也就是請假單發起的步驟*/
			Assert.assertEquals(1, currentSteps.size());
			Assert.assertEquals(1,((SimpleStep)currentSteps.get(0)).getId());
			/*執行請假申請流程*/
			wf.doAction(id, 1, Collections.EMPTY_MAP);
			/*接下來應該到直接上級*/
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(1, currentSteps.size());
			/*直接上級的step爲2*/
			Assert.assertEquals(2,((SimpleStep)currentSteps.get(0)).getId());
			/*獲取執行歷史*/
			List historySteps = wf.getHistorySteps(id);
			/*只有一個執行歷史*/
			Assert.assertEquals(1, currentSteps.size());
			/*直接上級審批通過*/
			wf.doAction(id, 2, Collections.EMPTY_MAP);
			
			/*接下來應該到了兩位部門領導哪裏,因此需要執行的步驟應該有兩個纔對*/
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(2, currentSteps.size());
			
			/*部門領導A審批*/
			wf.doAction(id, 4, Collections.EMPTY_MAP);
			/*部門領導B審批*/
			wf.doAction(id, 5, Collections.EMPTY_MAP);
			
			/*接下來應該到了最高領導哪裏,因此需要執行的步驟應該有1個纔對*/
			
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(1, currentSteps.size());
			/*最高領導審批*/
			wf.doAction(id, 6, Collections.EMPTY_MAP);
			/*流程執行完畢*/
			Assert.assertEquals(WorkflowEntry.COMPLETED, wf.getEntryState(id));
			
			historySteps = wf.getHistorySteps(id);
			Assert.assertEquals(5, historySteps.size());
		} catch (InvalidActionException e) {
			e.printStackTrace();
		} catch (InvalidRoleException e) {
			e.printStackTrace();
		} catch (InvalidInputException e) {
			e.printStackTrace();
		} catch (InvalidEntryStateException e) {
			e.printStackTrace();
		} catch (WorkflowException e) {
			e.printStackTrace();
		}
	}
	

執行單元測試,順利通過,並且我們的期望都得到了正確的驗證,通過上面的例子,您是不是對join和split標籤有了一個比較清楚的認識呢?如果不瞭解標籤如何配置,我給您的建議是直接打開dtd文件,非常直觀,如下所示

joins標籤:

<!ELEMENT join (conditions, unconditional-result)>
<!ATTLIST join
	id CDATA #REQUIRED
>
<!--
A list of join elements.

Used in: workflow
-->
<!ELEMENT joins (join*)>
Splits標籤
<!ELEMENT split (unconditional-result+)>
<!ATTLIST split
	id CDATA #REQUIRED
>
<!--
List of split elements.

Used in: workflow
-->
<!ELEMENT splits (split+)>
好了,本節的內容描述完畢!下節再見!

發佈了32 篇原創文章 · 獲贊 21 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章