在做流程的流轉歷史時,通常情況下還是以列表的形式表現,但是這樣總是感覺不太直觀,JBPM號稱是面向圖的編程,那么為什么我們不能在流程圖上顯示我們的流轉歷史呢,至少我們可以在流程圖上高亮顯示當前流程執行到了哪個節點,如果能這樣的話用戶可以很輕松而且一目了然的看到流程的流轉情況。
我發現在JBPM自帶的例子中有類似的效果,后來無意中又在網上發現了一篇文章《 JBPM圖形化流程監控》,作者簡單的闡述了圖形化流程監控的實現思路,讓我欣喜萬分,最終決定一試,呵呵,首先讓我秀一下戰果吧:
圖1:當前任務節點
圖2:當前流程中的活動任務
下面簡單的說說實現思路:
1、首先如果我們想高亮顯示某一任務節點,我們至少會知道該任務的某個實例,那么我們可以通過該taskInstance取得該任務所在的任務節點名稱如:String nodeName = taskInstance.getTask().getTaskNode().getName();
2、其次我們使用JBPM的Eclipse插件畫流程圖的時候,工具除了生成流程圖之外還會有一個gpd.xml,該文件記錄了流程圖的大小及其中的節點的坐標及每個節點的長寬,這就是說我們可以用DOM4J來解析該流程圖,從而得到我們要高亮顯示的那個節點的坐標及大小。
3、最后我們可以通過以上兩步得到的信息,以該流程圖中為背景圖案在其上畫DIV,來高亮顯示相應節點。
需要說明的是,我這種實現思路跟JBPM自帶例子的思路有一點不同,JBPM是在部署流程定義的時候把流程定義圖也一樣的放入了數據庫,所以他是以IO流的方式來處理,而我這種是完全在本地解析XML文件。
呵呵,大體思路就是這樣了,不知道我有沒有說明白,不過不明白不要緊,下面我們就來看具體的代碼實現,大家都是coder,還是用代碼交流起來比較方便啊,大家手頭都有gpd.xml文件的模板,所以這個文件的代碼就不往上貼了:
1 /**
2 * 功能描述:解析指定Node節點的x、y坐標以及該節點的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 }
以上兩個方法是純DOM4J實現,作用就是解析gpd.xml文件以獲取我們想要得到的信息,這兩段代碼是JBPM例子中帶有的,高亮顯示的具體的應用代碼如下:
1 /**
2 * 在流程圖上高亮顯示節點 功能描述:<br>
3 *
4 * @param taskInstanceId
5 * 任務實例ID
6 * @param gpdPath
7 * 流程圖坐標文件路徑
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 //獲取當前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 //具體的畫圖代碼
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,可以用來高亮顯示指定的任務節點,如果我們想要顯示指定流程中處于活躍狀態的任務的話,可以傳入processInstance的ID,然后得到該流程中的符合條件的任務,循環的生成DIV就行了,看具體代碼:
1 /**
2 * 功能描述:在流程圖上高亮顯示指定流程中處于活躍狀態的節點 <br>
3 *
4 * @param taskInstanceId
5 * 任務實例ID
6 * @param gpdPath
7 * 流程圖坐標文件路徑
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 //取得活躍狀態的任務
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 //循環的畫DIV,注意此處DIV的相對布局
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
呵呵,到這我們的目的就已經實現了,可以看到這樣在頁面上輸出的是標準的HTML,我們甚至可以加入JS的動態效果,實現更加強大的功能,希望能對你有所幫助!
posted on 2008-09-25 13:30
零全零美 閱讀(6482)
評論(5) 編輯 收藏 所屬分類:
jbpm