JBPM实践之:在流程图上高亮显示指定的任务节点

  在做流程的流转历史时,通常情况下还是以列表的形式表现,但是这样总是感觉不太直观,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文件的模板,所以这个文件的代码就不往上贴了:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  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例子中带有的,高亮显示的具体的应用代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  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就行了,看具体代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  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的动态效果,实现更加强大的功能,希望能对你有所帮助!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值