jbpm4.4根据.jpdl.xml流程定义文件,得到流程图.png
先看节点类的定义:
- publicclassNode{
- privateStringname;
- privateStringtype;
- privateRectanglerectangle;
- privateList<Transition>transitions=newArrayList<Transition>();
- publicNode(Stringname,Stringtype){
- this.name=name;
- this.type=type;
- }
- publicNode(Stringname,Stringtype,intx,inty,intw,inth){
- this.name=name;
- this.type=type;
- this.rectangle=newRectangle(x,y,w,h);
- }
- publicRectanglegetRectangle(){
- returnrectangle;
- }
- publicvoidsetRectangle(Rectanglerectangle){
- this.rectangle=rectangle;
- }
- publicStringgetType(){
- returntype;
- }
- publicvoidsetType(Stringtype){
- this.type=type;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicvoidaddTransition(Transitiontransition){
- transitions.add(transition);
- }
- publicList<Transition>getTransitions(){
- returntransitions;
- }
- publicvoidsetTransitions(List<Transition>transitions){
- this.transitions=transitions;
- }
- publicintgetX(){
- returnrectangle.x;
- }
- publicintgetY(){
- returnrectangle.y;
- }
- publicintgetCenterX(){
- return(int)rectangle.getCenterX();
- }
- publicintgetCenterY(){
- return(int)rectangle.getCenterY();
- }
- publicintgetWitdth(){
- returnrectangle.width;
- }
- publicintgetHeight(){
- returnrectangle.height;
- }
- }
其次是Transition的定义:
- publicclassTransition{
- privatePointlabelPosition;
- privateList<Point>lineTrace=newArrayList<Point>();
- privateStringlabel;
- privateStringto;
- publicTransition(Stringlabel,Stringto){
- this.label=label;
- this.to=to;
- }
- publicPointgetLabelPosition(){
- returnlabelPosition;
- }
- publicvoidsetLabelPosition(PointlabelPosition){
- this.labelPosition=labelPosition;
- }
- publicList<Point>getLineTrace(){
- returnlineTrace;
- }
- publicvoidsetLineTrace(List<Point>lineTrace){
- this.lineTrace=lineTrace;
- }
- publicvoidaddLineTrace(PointlineTrace){
- if(lineTrace!=null){
- this.lineTrace.add(lineTrace);
- }
- }
- publicStringgetLabel(){
- returnlabel;
- }
- publicvoidsetLabel(Stringlabel){
- this.label=label;
- }
- publicStringgetTo(){
- returnto;
- }
- publicvoidsetTo(Stringto){
- this.to=to;
- }
- }
类JpdlModel
- /**
- *CopyRight(C)2006-2009yy
- *@authoryy
- *@projectjbpm
- *@version1.0
- *@mailyy629_86at163dotcom
- *@date2009-9-6下午06:00:14
- *@description
- */
- packagesofocus.bpm.jbpm.jpdl.model;
- importjava.awt.Point;
- importjava.io.InputStream;
- importjava.util.HashMap;
- importjava.util.LinkedHashMap;
- importjava.util.List;
- importjava.util.Map;
- importorg.dom4j.Element;
- importorg.dom4j.io.SAXReader;
- publicclassJpdlModel{
- privateMap<String,Node>nodes=newLinkedHashMap<String,Node>();
- publicstaticfinalintRECT_OFFSET_X=-7;
- publicstaticfinalintRECT_OFFSET_Y=-8;
- publicstaticfinalintDEFAULT_PIC_SIZE=48;
- privatefinalstaticMap<String,Object>nodeInfos=newHashMap<String,Object>();
- static{
- nodeInfos.put("start","start_event_empty.png");
- nodeInfos.put("end","end_event_terminate.png");
- nodeInfos.put("end-cancel","end_event_cancel.png");
- nodeInfos.put("end-error","end_event_error.png");
- nodeInfos.put("decision","gateway_exclusive.png");
- nodeInfos.put("fork","gateway_parallel.png");
- nodeInfos.put("join","gateway_parallel.png");
- nodeInfos.put("state",null);
- nodeInfos.put("hql",null);
- nodeInfos.put("sql",null);
- nodeInfos.put("java",null);
- nodeInfos.put("script",null);
- nodeInfos.put("task",null);
- nodeInfos.put("sub-process",null);
- nodeInfos.put("custom",null);
- }
- publicJpdlModel(InputStreamis)throwsException{
- this(newSAXReader().read(is).getRootElement());
- }
- @SuppressWarnings("unchecked")
- privateJpdlModel(ElementrootEl)throwsException{
- for(Elementel:(List<Element>)rootEl.elements()){
- Stringtype=el.getQName().getName();
- if(!nodeInfos.containsKey(type)){//不是可展示的节点
- continue;
- }
- Stringname=null;
- if(el.attribute("name")!=null){
- name=el.attributeValue("name");
- }
- String[]location=el.attributeValue("g").split(",");
- intx=Integer.parseInt(location[0]);
- inty=Integer.parseInt(location[1]);
- intw=Integer.parseInt(location[2]);
- inth=Integer.parseInt(location[3]);
- if(nodeInfos.get(type)!=null){
- w=DEFAULT_PIC_SIZE;
- h=DEFAULT_PIC_SIZE;
- }else{
- x-=RECT_OFFSET_X;
- y-=RECT_OFFSET_Y;
- w+=(RECT_OFFSET_X+RECT_OFFSET_X);
- h+=(RECT_OFFSET_Y+RECT_OFFSET_Y);
- }
- Nodenode=newNode(name,type,x,h);
- parserTransition(node,el);
- nodes.put(name,node);
- }
- }
- @SuppressWarnings("unchecked")
- privatevoidparserTransition(Nodenode,ElementnodeEl){
- for(Elementel:(List<Element>)nodeEl.elements("transition")){
- Stringlabel=el.attributeValue("name");
- Stringto=el.attributeValue("to");
- Transitiontransition=newTransition(label,to);
- Stringg=el.attributeValue("g");
- if(g!=null&&g.length()>0){
- if(g.indexOf(":")<0){
- transition.setLabelPosition(getPoint(g));
- }else{
- String[]p=g.split(":");
- transition.setLabelPosition(getPoint(p[1]));
- String[]lines=p[0].split(";");
- for(Stringline:lines){
- transition.addLineTrace(getPoint(line));
- }
- }
- }
- node.addTransition(transition);
- }
- }
- privatePointgetPoint(Stringexp){
- if(exp==null||exp.length()==0){
- returnnull;
- }
- String[]p=exp.split(",");
- returnnewPoint(Integer.valueOf(p[0]),Integer.valueOf(p[1]));
- }
- publicMap<String,Node>getNodes(){
- returnnodes;
- }
- publicstaticMap<String,Object>getNodeInfos(){
- returnnodeInfos;
- }
- }
根据JpdlModel绘制出流程图
- /**
- *CopyRight(C)2006-2009yy
- *@authoryy
- *@projectJbpm
- *@version1.0
- *@mailyy629_86at163dotcom
- *@date2009-9-6下午06:00:14
- *@description
- */
- packagesofocus.bpm.jbpm.jpdl;
- importjava.awt.*;
- importjava.awt.font.FontRenderContext;
- importjava.awt.geom.Rectangle2D;
- importjava.awt.image.BufferedImage;
- importjava.io.IOException;
- importjava.util.List;
- importjava.util.Map;
- importjavax.imageio.ImageIO;
- importsofocus.bpm.jbpm.jpdl.model.JpdlModel;
- importsofocus.bpm.jbpm.jpdl.model.Node;
- importsofocus.bpm.jbpm.jpdl.model.Transition;
- /**
- *@authoryeyong
- *
- */
- publicclassJpdlModelDrawer{
- publicstaticfinalintRECT_OFFSET_X=JpdlModel.RECT_OFFSET_X;
- publicstaticfinalintRECT_OFFSET_Y=JpdlModel.RECT_OFFSET_Y;
- publicstaticfinalintRECT_ROUND=25;
- publicstaticfinalintDEFAULT_FONT_SIZE=12;
- publicstaticfinalColorDEFAULT_STROKE_COLOR=Color.decode("#03689A");
- publicstaticfinalStrokeDEFAULT_STROKE=newBasicStroke(2);
- publicstaticfinalColorDEFAULT_LINE_STROKE_COLOR=Color.decode("#808080");
- publicstaticfinalStrokeDEFAULT_LINE_STROKE=newBasicStroke(1);
- publicstaticfinalColorDEFAULT_FILL_COLOR=Color.decode("#F6F7FF");
- privatefinalstaticMap<String,Object>nodeInfos=JpdlModel.getNodeInfos();
- publicBufferedImagedraw(JpdlModeljpdlModel)throwsIOException{
- Rectangledimension=getCanvasDimension(jpdlModel);
- BufferedImagebi=newBufferedImage(dimension.width,dimension.height,BufferedImage.TYPE_INT_ARGB);
- Graphics2Dg2=bi.createGraphics();
- g2.setColor(Color.WHITE);
- g2.fillRect(0,0,dimension.width,dimension.height);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
- Fontfont=newFont("宋体",Font.PLAIN,DEFAULT_FONT_SIZE);
- g2.setFont(font);
- Map<String,Node>nodes=jpdlModel.getNodes();
- drawNode(nodes,g2,font);
- drawTransition(nodes,g2);
- returnbi;
- }
- /**
- *获得图片的矩形大小
- *
- *@return
- */
- privateRectanglegetCanvasDimension(JpdlModeljpdlModel){
- Rectanglerectangle=newRectangle();
- Rectanglerect;
- for(Nodenode:jpdlModel.getNodes().values()){
- rect=node.getRectangle();
- if(rect.getMaxX()>rectangle.getMaxX()){
- rectangle.width=(int)rect.getMaxX();
- }
- if(rect.getMaxY()>rectangle.getMaxY()){
- rectangle.height=(int)rect.getMaxY();
- }
- for(Transitiontransition:node.getTransitions()){
- List<Point>trace=transition.getLineTrace();
- for(Pointpoint:trace){
- if(rectangle.getMaxX()<point.x){
- rectangle.width=point.x;
- }
- if(rectangle.getMaxY()<point.y){
- rectangle.height=point.y;
- }
- }
- }
- }
- rectangle.width+=60;
- rectangle.height+=20;
- returnrectangle;
- }
- /**
- *@paramg2
- *@throwsIOException
- */
- privatevoiddrawTransition(Map<String,Node>nodes,Graphics2Dg2)throwsIOException{
- g2.setStroke(DEFAULT_LINE_STROKE);
- g2.setColor(DEFAULT_LINE_STROKE_COLOR);
- for(Nodenode:nodes.values()){
- for(Transitiontransition:node.getTransitions()){
- Stringto=transition.getTo();
- NodetoNode=nodes.get(to);
- List<Point>trace=newLinkedList<Point>(transition.getLineTrace());
- intlen=trace.size()+2;
- trace.add(0,newPoint(node.getCenterX(),node.getCenterY()));
- trace.add(newPoint(toNode.getCenterX(),toNode.getCenterY()));
- int[]xPoints=newint[len];
- int[]yPoints=newint[len];
- for(inti=0;i<len;i++){
- xPoints[i]=trace.get(i).x;
- yPoints[i]=trace.get(i).y;
- }
- finalinttaskGrow=4;
- finalintsmallGrow=-2;
- intgrow=0;
- if(nodeInfos.get(node.getType())!=null){
- grow=smallGrow;
- }else{
- grow=taskGrow;
- }
- Pointp=GeometryUtils.getRectangleLineCrossPoint(node.getRectangle(),newPoint(xPoints[1],
- yPoints[1]),grow);
- if(p!=null){
- xPoints[0]=p.x;
- yPoints[0]=p.y;
- }
- if(nodeInfos.get(toNode.getType())!=null){
- grow=smallGrow;
- }else{
- grow=taskGrow;
- }
- p=GeometryUtils.getRectangleLineCrossPoint(toNode.getRectangle(),newPoint(xPoints[len-2],
- yPoints[len-2]),grow);
- if(p!=null){
- xPoints[len-1]=p.x;
- yPoints[len-1]=p.y;
- }
- g2.drawPolyline(xPoints,yPoints,len);
- drawArrow(g2,xPoints[len-2],yPoints[len-2],xPoints[len-1],yPoints[len-1]);
- Stringlabel=transition.getLabel();
- if(label!=null&&label.length()>0){
- intcx,cy;
- if(len%2==0){
- cx=(xPoints[len/2-1]+xPoints[len/2])/2;
- cy=(yPoints[len/2-1]+yPoints[len/2])/2;
- }else{
- cx=xPoints[len/2];
- cy=yPoints[len/2];
- }
- PointlabelPoint=transition.getLabelPosition();
- if(labelPoint!=null){
- cx+=labelPoint.x;
- cy+=labelPoint.y;
- }
- cy-=RECT_OFFSET_Y+RECT_OFFSET_Y/2;
- g2.drawString(label,cx,cy);
- }
- }
- }
- }
- privatevoiddrawArrow(Graphics2Dg2,intx1,inty1,intx2,inty2){
- finaldoublelen=8.0;
- doubleslopy=Math.atan2(y2-y1,x2-x1);
- doublecosy=Math.cos(slopy);
- doublesiny=Math.sin(slopy);
- int[]xPoints={0,x2,0};
- int[]yPoints={0,y2,0};
- doublea=len*siny,b=len*cosy;
- doublec=len/2.0*siny,d=len/2.0*cosy;
- xPoints[0]=x2-(int)(b+c);
- yPoints[0]=y2-(int)(a-d);
- xPoints[2]=x2-(int)(b-c);
- yPoints[2]=y2-(int)(d+a);
- g2.fillPolygon(xPoints,3);
- }
- /**
- *@paramg2
- *@throwsIOException
- */
- privatevoiddrawNode(Map<String,Graphics2Dg2,Fontfont)throwsIOException{
- for(Nodenode:nodes.values()){
- Stringname=node.getName();
- if(nodeInfos.get(node.getType())!=null){
- BufferedImagebi2=ImageIO.read(getClass().getResourceAsStream(
- "/icons/48/"+nodeInfos.get(node.getType())));
- g2.drawImage(bi2,node.getX(),node.getY(),null);
- }else{
- intx=node.getX();
- inty=node.getY();
- intw=node.getWitdth();
- inth=node.getHeight();
- g2.setColor(DEFAULT_FILL_COLOR);
- g2.fillRoundRect(x,h,RECT_ROUND,RECT_ROUND);
- g2.setColor(DEFAULT_STROKE_COLOR);
- g2.setStroke(DEFAULT_STROKE);
- g2.drawRoundRect(x,RECT_ROUND);
- FontRenderContextfrc=g2.getFontRenderContext();
- Rectangle2Dr2=font.getStringBounds(name,frc);
- intxLabel=(int)(node.getX()+((node.getWitdth()-r2.getWidth())/2));
- intyLabel=(int)((node.getY()+((node.getHeight()-r2.getHeight())/2))-r2.getY());
- g2.setStroke(DEFAULT_LINE_STROKE);
- g2.setColor(Color.black);
- g2.drawString(name,xLabel,yLabel);
- }
- }
- }
- }
工具类,用来计算一些坐标的
- /**
- *CopyRight(C)2006-2009yy
- *@authoryy
- *@projectjbpm
- *@version1.0
- *@mailyy629_86at163dotcom
- *@date2009-9-11上午06:16:26
- *@description
- */
- packagesofocus.bpm.jbpm.jpdl;
- importjava.awt.Point;
- importjava.awt.Rectangle;
- /**
- *@authoryeyong
- *
- */
- publicclassGeometryUtils{
- /**
- *获得直线(x1,y1)-(x2,y2)的斜率
- *
- *@paramx1
- *@paramy1
- *@paramx2
- *@paramy2
- *@return
- */
- publicstaticdoublegetSlope(intx1,inty2){
- return((double)y2-y1)/(x2-x1);
- }
- /**
- *获得直线(x1,y2)的y轴截距
- *
- *@paramx1
- *@paramy1
- *@paramx2
- *@paramy2
- *@return
- */
- publicstaticdoublegetYIntercep(intx1,inty2){
- returny1-x1*getSlope(x1,y1,y2);
- }
- /**
- *获得矩形的中点
- *
- *@paramrect
- *@return
- */
- publicstaticPointgetRectangleCenter(Rectanglerect){
- returnnewPoint((int)rect.getCenterX(),(int)rect.getCenterY());
- }
- /**
- *获得矩形中心p0与p1的线段和矩形的交点
- *
- *@paramrectangle
- *@paramp1
- *@return
- */
- publicstaticPointgetRectangleLineCrossPoint(Rectanglerectangle,Pointp1,intgrow){
- Rectanglerect=rectangle.getBounds();
- rect.grow(grow,grow);
- Pointp0=GeometryUtils.getRectangleCenter(rect);
- if(p1.x==p0.x){
- if(p1.y<p0.y){
- returnnewPoint(p0.x,rect.y);
- }
- returnnewPoint(p0.x,rect.y+rect.height);
- }
- if(p1.y==p0.y){
- if(p1.x<p0.x){
- returnnewPoint(rect.x,p0.y);
- }
- returnnewPoint(rect.x+rect.width,p0.y);
- }
- doubleslope=GeometryUtils.getSlope(p0.x,p0.y,rect.x,rect.y);
- doubleslopeLine=GeometryUtils.getSlope(p0.x,p1.x,p1.y);
- doubleyIntercep=GeometryUtils.getYIntercep(p0.x,p1.y);
- if(Math.abs(slopeLine)>slope-1e-2){
- if(p1.y<rect.y){
- returnnewPoint((int)((rect.y-yIntercep)/slopeLine),rect.y);
- }else{
- returnnewPoint((int)((rect.y+rect.height-yIntercep)/slopeLine),rect.y+rect.height);
- }
- }
- if(p1.x<rect.x){
- returnnewPoint(rect.x,(int)(slopeLine*rect.x+yIntercep));
- }else{
- returnnewPoint(rect.x+rect.width,(int)(slopeLine*(rect.x+rect.width)+yIntercep));
- }
- }
- }
测试
public static void main(String[] args) { // TODO Auto-generated method stub try { File file = new File("D:/test.jpdl.xml"); InputStream is = new FileInputStream(file); JpdlModel jpdlModel = new JpdlModel (is); ImageIO.write(new JpdlModelDrawer().draw(jpdlModel),"png",new File("D:/test.png")); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
}