在做流程的流轉(zhuǎn)歷史時(shí),通常情況下還是以列表的形式表現(xiàn),但是這樣總是感覺(jué)不太直觀,JBPM號(hào)稱(chēng)是面向圖的編程,那么為什么我們不能在流程圖上顯示我們的流轉(zhuǎn)歷史呢,至少我們可以在流程圖上高亮顯示當(dāng)前流程執(zhí)行到了哪個(gè)節(jié)點(diǎn),如果能這樣的話(huà)用戶(hù)可以很輕松而且一目了然的看到流程的流轉(zhuǎn)情況。
我發(fā)現(xiàn)在JBPM自帶的例子中有類(lèi)似的效果,后來(lái)無(wú)意中又在網(wǎng)上發(fā)現(xiàn)了一篇文章《 JBPM圖形化流程監(jiān)控》,作者簡(jiǎn)單的闡述了圖形化流程監(jiān)控的實(shí)現(xiàn)思路,讓我欣喜萬(wàn)分,最終決定一試,呵呵,首先讓我秀一下戰(zhàn)果吧:
圖1:當(dāng)前任務(wù)節(jié)點(diǎn)
圖2:當(dāng)前流程中的活動(dòng)任務(wù)
下面簡(jiǎn)單的說(shuō)說(shuō)實(shí)現(xiàn)思路:
1、首先如果我們想高亮顯示某一任務(wù)節(jié)點(diǎn),我們至少會(huì)知道該任務(wù)的某個(gè)實(shí)例,那么我們可以通過(guò)該taskInstance取得該任務(wù)所在的任務(wù)節(jié)點(diǎn)名稱(chēng)如:String nodeName = taskInstance.getTask().getTaskNode().getName();
2、其次我們使用JBPM的Eclipse插件畫(huà)流程圖的時(shí)候,工具除了生成流程圖之外還會(huì)有一個(gè)gpd.xml,該文件記錄了流程圖的大小及其中的節(jié)點(diǎn)的坐標(biāo)及每個(gè)節(jié)點(diǎn)的長(zhǎng)寬,這就是說(shuō)我們可以用DOM4J來(lái)解析該流程圖,從而得到我們要高亮顯示的那個(gè)節(jié)點(diǎn)的坐標(biāo)及大小。
3、最后我們可以通過(guò)以上兩步得到的信息,以該流程圖中為背景圖案在其上畫(huà)DIV,來(lái)高亮顯示相應(yīng)節(jié)點(diǎn)。
需要說(shuō)明的是,我這種實(shí)現(xiàn)思路跟JBPM自帶例子的思路有一點(diǎn)不同,JBPM是在部署流程定義的時(shí)候把流程定義圖也一樣的放入了數(shù)據(jù)庫(kù),所以他是以IO流的方式來(lái)處理,而我這種是完全在本地解析XML文件。
呵呵,大體思路就是這樣了,不知道我有沒(méi)有說(shuō)明白,不過(guò)不明白不要緊,下面我們就來(lái)看具體的代碼實(shí)現(xiàn),大家都是coder,還是用代碼交流起來(lái)比較方便啊,大家手頭都有g(shù)pd.xml文件的模板,所以這個(gè)文件的代碼就不往上貼了:
1 /**
2 * 功能描述:解析指定Node節(jié)點(diǎn)的x、y坐標(biāo)以及該節(jié)點(diǎn)的width和height<br>
3 * @param root
4 * @param nodeName
5 * @return int[]
6 */
7 private int[] extractBoxConstraint(Element root, String nodeName) {
8 int[] result = new int[4];
9 XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']");
10 Element node = (Element) xPath.selectSingleNode(root);
11 result[0] = Integer.valueOf(node.attribute("x").getValue()).intValue() - 4;
12 result[1] = Integer.valueOf(node.attribute("y").getValue()).intValue() - 4;
13 result[2] = Integer.valueOf(node.attribute("width").getValue()).intValue() + 4;
14 result[3] = Integer.valueOf(node.attribute("height").getValue()).intValue() + 4;
15 return result;
16 }
17
18 /**
19 * 功能描述:獲取gpd文件中流程圖的width和height<br>
20 * @param root
21 * @return int[]
22 */
23 private int[] extractImageDimension(Element root) {
24 int[] result = new int[2];
25 result[0] = Integer.valueOf(root.attribute("width").getValue()).intValue();
26 result[1] = Integer.valueOf(root.attribute("height").getValue()).intValue();
27 return result;
28 }
以上兩個(gè)方法是純DOM4J實(shí)現(xiàn),作用就是解析gpd.xml文件以獲取我們想要得到的信息,這兩段代碼是JBPM例子中帶有的,高亮顯示的具體的應(yīng)用代碼如下:
1 /**
2 * 在流程圖上高亮顯示節(jié)點(diǎn) 功能描述:<br>
3 *
4 * @param taskInstanceId
5 * 任務(wù)實(shí)例ID
6 * @param gpdPath
7 * 流程圖坐標(biāo)文件路徑
8 * @param processImagePath
9 * 流程圖路徑
10 */
11 public String ProcessImageForCurrentTask(long taskInstanceId,String gpdPath,String processImagePath) {
12 StringBuffer sbString = new StringBuffer();
13 try {
14 //初始化dom4j
15 Element rootDiagramElement = new SAXReader().read(gpdPath).getRootElement();
16 //獲取當(dāng)前TaskInstance
17 TaskInstance taskInstance = this.defaultJbpmDAO.findTaskInstance(taskInstanceId);
18 //解析gpd.xml
19 int[] boxConstraint = extractBoxConstraint(rootDiagramElement, taskInstance.getTask().getTaskNode().getName());
20 int[] imageDimension = extractImageDimension(rootDiagramElement);
21 //具體的畫(huà)圖代碼
22 String imageLink = processImagePath;
23 sbString.append("<table border=0 cellspacing=0 cellpadding=0 width=" + imageDimension[0] + " height=" + imageDimension[1] + " style=\"position:relative\">");
24 sbString.append(" <tr>");
25 sbString.append(" <td width=" + imageDimension[0] + " height=" + imageDimension[1] + " style=\"background-image:url(" + imageLink + ")\" valign=top>");
26 sbString.append(" <div style=\"position:absolute;");
27 sbString.append(" left:"+boxConstraint[0]+ "px; top:"+ boxConstraint[1] +"px;width:" + boxConstraint[2] +"px;height:"+ boxConstraint[3] +"px;");
28 sbString.append(" z-index:1; border-color:red; border-width:4; ");
29 sbString.append(" border-style: groove; background-color: transparent;\">");
30 sbString.append(" </div>");
31 sbString.append(" </td>");
32 sbString.append(" </tr>");
33 sbString.append("</table>");
34
35 } catch (Exception e) {
36 e.printStackTrace();
37 }
38 return sbString.toString();
39 }
40
雖然代碼比較多,但是思路很清晰,我也就不羅嗦了,上面是給出了指定的taskInstance的ID,可以用來(lái)高亮顯示指定的任務(wù)節(jié)點(diǎn),如果我們想要顯示指定流程中處于活躍狀態(tài)的任務(wù)的話(huà),可以傳入processInstance的ID,然后得到該流程中的符合條件的任務(wù),循環(huán)的生成DIV就行了,看具體代碼:
1 /**
2 * 功能描述:在流程圖上高亮顯示指定流程中處于活躍狀態(tài)的節(jié)點(diǎn) <br>
3 *
4 * @param taskInstanceId
5 * 任務(wù)實(shí)例ID
6 * @param gpdPath
7 * 流程圖坐標(biāo)文件路徑
8 * @param processImagePath
9 * 流程圖路徑
10 */
11 public String processImage(final long processInstanceId, final String gpdPath, final String processImagePath) {
12 StringBuffer sbString = new StringBuffer();
13 try {
14 Element rootDiagramElement = new SAXReader().read(gpdPath).getRootElement();
15
16 //取得活躍狀態(tài)的任務(wù)
17 List<TaskInstance> activeTaskObjectList = this.defaultJbpmDAO.getTaskInstanceListFormProcess(processInstanceId, TaskStateType.TASK_UNFINISHED);
18 int[] imageDimension = extractImageDimension(rootDiagramElement);
19
20 String imageLink = processImagePath;
21 sbString.append("<table border=0 cellspacing=0 cellpadding=0 width=" + imageDimension[0] + " height=" + imageDimension[1] + " style=\"position:relative\">");
22 sbString.append(" <tr>");
23 sbString.append(" <td width=" + imageDimension[0] + " height=" + imageDimension[1] + " style=\"background-image:url(" + imageLink + ")\" valign=top>");
24 //循環(huán)的畫(huà)DIV,注意此處DIV的相對(duì)布局
25 for (TaskInstance taskInstance : activeTaskObjectList) {
26 int[] boxConstraint = extractBoxConstraint(rootDiagramElement, taskInstance.getTask().getTaskNode().getName());
27 sbString.append(" <div style=\"position:absolute;");
28 sbString.append(" left:" + boxConstraint[0] + "px; top:" + boxConstraint[1] + "px; width:" + boxConstraint[2] + "px;height:" + boxConstraint[3] + "px;");
29 sbString.append(" z-index:1; border-color: red; border-width: 4; ");
30 sbString.append(" border-style: groove; background-color: transparent;\">");
31 sbString.append(" </div>");
32 }
33 sbString.append(" </td>");
34 sbString.append(" </tr>");
35 sbString.append("</table>");
36
37 } catch (Exception e) {
38 e.printStackTrace();
39 }
40 return sbString.toString();
41
42 }
43
呵呵,到這我們的目的就已經(jīng)實(shí)現(xiàn)了,可以看到這樣在頁(yè)面上輸出的是標(biāo)準(zhǔn)的HTML,我們甚至可以加入JS的動(dòng)態(tài)效果,實(shí)現(xiàn)更加強(qiáng)大的功能,希望能對(duì)你有所幫助!
posted on 2008-09-25 13:30
零全零美 閱讀(6493)
評(píng)論(5) 編輯 收藏 所屬分類(lèi):
jbpm