jbpm4.4根据.jpdl.xml流程定义文件,得到流程图.png

时间:2022-01-07 18:06:57

jbpm4.4根据.jpdl.xml流程定义文件,得到流程图.png

只需将.jpdl.xml文件传过来,就可以根据这个文件解析出来.png图片

先看节点类的定义:
Java代码
  1. public class Node {   
  2.   private String name;   
  3.   private String type;   
  4.   private Rectangle rectangle;   
  5.   private List<Transition> transitions = new ArrayList<Transition>();   
  6.   
  7.   public Node(String name, String type) {   
  8.     this.name = name;   
  9.     this.type = type;   
  10.   }   
  11.   
  12.   public Node(String name, String type, int x, int y, int w, int h) {   
  13.     this.name = name;   
  14.     this.type = type;   
  15.     this.rectangle = new Rectangle(x, y, w, h);   
  16.   }   
  17.   
  18.   public Rectangle getRectangle() {   
  19.     return rectangle;   
  20.   }   
  21.   
  22.   public void setRectangle(Rectangle rectangle) {   
  23.     this.rectangle = rectangle;   
  24.   }   
  25.   
  26.   public String getType() {   
  27.     return type;   
  28.   }   
  29.   
  30.   public void setType(String type) {   
  31.     this.type = type;   
  32.   }   
  33.   
  34.   public String getName() {   
  35.     return name;   
  36.   }   
  37.   
  38.   public void setName(String name) {   
  39.     this.name = name;   
  40.   }   
  41.   
  42.   public void addTransition(Transition transition) {   
  43.     transitions.add(transition);   
  44.   }   
  45.   
  46.   public List<Transition> getTransitions() {   
  47.     return transitions;   
  48.   }   
  49.   
  50.   public void setTransitions(List<Transition> transitions) {   
  51.     this.transitions = transitions;   
  52.   }   
  53.   
  54.   public int getX() {   
  55.     return rectangle.x;   
  56.   }   
  57.   
  58.   public int getY() {   
  59.     return rectangle.y;   
  60.   }   
  61.   
  62.   public int getCenterX() {   
  63.     return (int) rectangle.getCenterX();   
  64.   }   
  65.   
  66.   public int getCenterY() {   
  67.     return (int) rectangle.getCenterY();   
  68.   }   
  69.   
  70.   public int getWitdth() {   
  71.     return rectangle.width;   
  72.   }   
  73.   
  74.   public int getHeight() {   
  75.     return rectangle.height;   
  76.   }   
  77. }  


其次是Transition的定义:
Java代码
  1. public class Transition {   
  2.   private Point labelPosition;   
  3.   private List<Point> lineTrace = new ArrayList<Point>();   
  4.   private String label;   
  5.   private String to;   
  6.   
  7.   public Transition(String label, String to) {   
  8.     this.label = label;   
  9.     this.to = to;   
  10.   }   
  11.   
  12.   public Point getLabelPosition() {   
  13.     return labelPosition;   
  14.   }   
  15.   
  16.   public void setLabelPosition(Point labelPosition) {   
  17.     this.labelPosition = labelPosition;   
  18.   }   
  19.   
  20.   public List<Point> getLineTrace() {   
  21.     return lineTrace;   
  22.   }   
  23.   
  24.   public void setLineTrace(List<Point> lineTrace) {   
  25.     this.lineTrace = lineTrace;   
  26.   }   
  27.   
  28.   public void addLineTrace(Point lineTrace) {   
  29.     if (lineTrace != null) {   
  30.       this.lineTrace.add(lineTrace);   
  31.     }   
  32.   }   
  33.   
  34.   public String getLabel() {   
  35.     return label;   
  36.   }   
  37.   public void setLabel(String label) {   
  38.     this.label = label;   
  39.   }   
  40.   
  41.   public String getTo() {   
  42.     return to;   
  43.   }   
  44.   
  45.   public void setTo(String to) {   
  46.     this.to = to;   
  47.   }   
  48.   
  49. }  


类JpdlModel
Java代码
  1. /**  
  2.  * CopyRight (C) 2006-2009 yy  
  3.  * @author yy  
  4.  * @project jbpm  
  5.  * @version 1.0  
  6.  * @mail yy629_86 at 163 dot com  
  7.  * @date 2009-9-6 下午06:00:14  
  8.  * @description  
  9.  */  
  10. package sofocus.bpm.jbpm.jpdl.model;   
  11.   
  12. import java.awt.Point;   
  13. import java.io.InputStream;   
  14. import java.util.HashMap;   
  15. import java.util.LinkedHashMap;   
  16. import java.util.List;   
  17. import java.util.Map;   
  18.   
  19. import org.dom4j.Element;   
  20. import org.dom4j.io.SAXReader;   
  21.   
  22. public class JpdlModel {   
  23.   private Map<String, Node> nodes = new LinkedHashMap<String, Node>();   
  24.   public static final int RECT_OFFSET_X = -7;   
  25.   public static final int RECT_OFFSET_Y = -8;   
  26.   public static final int DEFAULT_PIC_SIZE = 48;   
  27.   
  28.   private final static Map<String, Object> nodeInfos = new HashMap<String, Object>();   
  29.   static {   
  30.     nodeInfos.put("start""start_event_empty.png");   
  31.     nodeInfos.put("end""end_event_terminate.png");   
  32.     nodeInfos.put("end-cancel""end_event_cancel.png");   
  33.     nodeInfos.put("end-error""end_event_error.png");   
  34.     nodeInfos.put("decision""gateway_exclusive.png");   
  35.     nodeInfos.put("fork""gateway_parallel.png");   
  36.     nodeInfos.put("join""gateway_parallel.png");   
  37.     nodeInfos.put("state"null);   
  38.     nodeInfos.put("hql"null);   
  39.     nodeInfos.put("sql"null);   
  40.     nodeInfos.put("java"null);   
  41.     nodeInfos.put("script"null);   
  42.     nodeInfos.put("task"null);   
  43.     nodeInfos.put("sub-process"null);   
  44.     nodeInfos.put("custom"null);   
  45.   }   
  46.   
  47.   public JpdlModel(InputStream is) throws Exception {   
  48.     this(new SAXReader().read(is).getRootElement());   
  49.   }   
  50.   
  51.   @SuppressWarnings("unchecked")   
  52.   private JpdlModel(Element rootEl) throws Exception {   
  53.     for (Element el : (List<Element>) rootEl.elements()) {   
  54.       String type = el.getQName().getName();   
  55.       if (!nodeInfos.containsKey(type)) { // 不是可展示的节点  
  56.         continue;   
  57.       }   
  58.       String name = null;   
  59.       if (el.attribute("name") != null) {   
  60.         name = el.attributeValue("name");   
  61.       }   
  62.       String[] location = el.attributeValue("g").split(",");   
  63.       int x = Integer.parseInt(location[0]);   
  64.       int y = Integer.parseInt(location[1]);   
  65.       int w = Integer.parseInt(location[2]);   
  66.       int h = Integer.parseInt(location[3]);   
  67.   
  68.       if (nodeInfos.get(type) != null) {   
  69.         w = DEFAULT_PIC_SIZE;   
  70.         h = DEFAULT_PIC_SIZE;   
  71.       } else {   
  72.         x -= RECT_OFFSET_X;   
  73.         y -= RECT_OFFSET_Y;   
  74.         w += (RECT_OFFSET_X + RECT_OFFSET_X);   
  75.         h += (RECT_OFFSET_Y + RECT_OFFSET_Y);   
  76.       }   
  77.       Node node = new Node(name, type, x, y, w, h);   
  78.       parserTransition(node, el);   
  79.       nodes.put(name, node);   
  80.     }   
  81.   }   
  82.   
  83.   @SuppressWarnings("unchecked")   
  84.   private void parserTransition(Node node, Element nodeEl) {   
  85.     for (Element el : (List<Element>) nodeEl.elements("transition")) {   
  86.       String label = el.attributeValue("name");   
  87.       String to = el.attributeValue("to");   
  88.       Transition transition = new Transition(label, to);   
  89.       String g = el.attributeValue("g");   
  90.       if (g != null && g.length() > 0) {   
  91.         if (g.indexOf(":") < 0) {   
  92.           transition.setLabelPosition(getPoint(g));   
  93.         } else {   
  94.           String[] p = g.split(":");   
  95.           transition.setLabelPosition(getPoint(p[1]));   
  96.           String[] lines = p[0].split(";");   
  97.           for (String line : lines) {   
  98.             transition.addLineTrace(getPoint(line));   
  99.           }   
  100.         }   
  101.       }   
  102.       node.addTransition(transition);   
  103.     }   
  104.   }   
  105.   
  106.   private Point getPoint(String exp) {   
  107.     if (exp == null || exp.length() == 0) {   
  108.       return null;   
  109.     }   
  110.     String[] p = exp.split(",");   
  111.     return new Point(Integer.valueOf(p[0]), Integer.valueOf(p[1]));   
  112.   }   
  113.   
  114.   public Map<String, Node> getNodes() {   
  115.     return nodes;   
  116.   }   
  117.     public static Map<String, Object> getNodeInfos() {   
  118.     return nodeInfos;   
  119.   }   
  120. }  


根据JpdlModel绘制出流程图
Java代码
  1. /**  
  2.  * CopyRight (C) 2006-2009 yy  
  3.  * @author yy  
  4.  * @project Jbpm  
  5.  * @version 1.0  
  6.  * @mail yy629_86 at 163 dot com  
  7.  * @date 2009-9-6 下午06:00:14  
  8.  * @description  
  9.  */  
  10. package sofocus.bpm.jbpm.jpdl;   
  11.   
  12. import java.awt.*;   
  13. import java.awt.font.FontRenderContext;   
  14. import java.awt.geom.Rectangle2D;   
  15. import java.awt.image.BufferedImage;   
  16. import java.io.IOException;   
  17. import java.util.List;   
  18. import java.util.Map;   
  19.   
  20. import javax.imageio.ImageIO;   
  21.   
  22. import sofocus.bpm.jbpm.jpdl.model.JpdlModel;   
  23. import sofocus.bpm.jbpm.jpdl.model.Node;   
  24. import sofocus.bpm.jbpm.jpdl.model.Transition;   
  25.   
  26. /**
  27.  * @author yeyong  
  28.  *   
  29.  */  
  30. public class JpdlModelDrawer {   
  31.   public static final int RECT_OFFSET_X = JpdlModel.RECT_OFFSET_X;   
  32.   public static final int RECT_OFFSET_Y = JpdlModel.RECT_OFFSET_Y;   
  33.   public static final int RECT_ROUND = 25;   
  34.   
  35.   public static final int DEFAULT_FONT_SIZE = 12;   
  36.   
  37.   public static final Color DEFAULT_STROKE_COLOR = Color.decode("#03689A");   
  38.   public static final Stroke DEFAULT_STROKE = new BasicStroke(2);   
  39.   
  40.   public static final Color DEFAULT_LINE_STROKE_COLOR = Color.decode("#808080");   
  41.   public static final Stroke DEFAULT_LINE_STROKE = new BasicStroke(1);   
  42.   
  43.   public static final Color DEFAULT_FILL_COLOR = Color.decode("#F6F7FF");   
  44.   
  45.   private final static Map<String, Object> nodeInfos = JpdlModel.getNodeInfos();   
  46.   
  47.   public BufferedImage draw(JpdlModel jpdlModel) throws IOException {   
  48.     Rectangle dimension = getCanvasDimension(jpdlModel);   
  49.     BufferedImage bi = new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB);   
  50.     Graphics2D g2 = bi.createGraphics();   
  51.     g2.setColor(Color.WHITE);   
  52.     g2.fillRect(00, dimension.width, dimension.height);   
  53.     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);   
  54.     Font font = new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE);   
  55.     g2.setFont(font);   
  56.     Map<String, Node> nodes = jpdlModel.getNodes();   
  57.     drawNode(nodes, g2, font);   
  58.     drawTransition(nodes, g2);   
  59.     return bi;   
  60.   }   
  61.   
  62.   /**
  63.    * 获得图片的矩形大小  
  64.    *   
  65.    * @return  
  66.    */  
  67.   private Rectangle getCanvasDimension(JpdlModel jpdlModel) {   
  68.     Rectangle rectangle = new Rectangle();   
  69.     Rectangle rect;   
  70.     for (Node node : jpdlModel.getNodes().values()) {   
  71.       rect = node.getRectangle();   
  72.       if (rect.getMaxX() > rectangle.getMaxX()) {   
  73.         rectangle.width = (int) rect.getMaxX();   
  74.       }   
  75.       if (rect.getMaxY() > rectangle.getMaxY()) {   
  76.         rectangle.height = (int) rect.getMaxY();   
  77.       }   
  78.       for (Transition transition : node.getTransitions()) {   
  79.         List<Point> trace = transition.getLineTrace();   
  80.         for (Point point : trace) {   
  81.           if (rectangle.getMaxX() < point.x) {   
  82.             rectangle.width = point.x;   
  83.           }   
  84.           if (rectangle.getMaxY() < point.y) {   
  85.             rectangle.height = point.y;   
  86.           }   
  87.         }   
  88.       }   
  89.     }   
  90.     rectangle.width += 60;   
  91.     rectangle.height += 20;   
  92.     return rectangle;   
  93.   }   
  94.   
  95.   /**
  96.    * @param g2  
  97.    * @throws IOException  
  98.    */  
  99.   private void drawTransition(Map<String, Node> nodes, Graphics2D g2) throws IOException {   
  100.     g2.setStroke(DEFAULT_LINE_STROKE);   
  101.     g2.setColor(DEFAULT_LINE_STROKE_COLOR);   
  102.     for (Node node : nodes.values()) {   
  103.       for (Transition transition : node.getTransitions()) {   
  104.         String to = transition.getTo();   
  105.         Node toNode = nodes.get(to);   
  106.         List<Point> trace = new LinkedList<Point>(transition.getLineTrace());   
  107.         int len = trace.size() + 2;   
  108.         trace.add(0new Point(node.getCenterX(), node.getCenterY()));   
  109.         trace.add(new Point(toNode.getCenterX(), toNode.getCenterY()));   
  110.         int[] xPoints = new int[len];   
  111.         int[] yPoints = new int[len];   
  112.         for (int i = 0; i < len; i++) {   
  113.           xPoints[i] = trace.get(i).x;   
  114.           yPoints[i] = trace.get(i).y;   
  115.         }   
  116.         final int taskGrow = 4;   
  117.         final int smallGrow = -2;   
  118.         int grow = 0;   
  119.         if (nodeInfos.get(node.getType()) != null) {   
  120.           grow = smallGrow;   
  121.         } else {   
  122.           grow = taskGrow;   
  123.         }   
  124.         Point p = GeometryUtils.getRectangleLineCrossPoint(node.getRectangle(), new Point(xPoints[1],   
  125.             yPoints[1]), grow);   
  126.         if (p != null) {   
  127.           xPoints[0] = p.x;   
  128.           yPoints[0] = p.y;   
  129.         }   
  130.         if (nodeInfos.get(toNode.getType()) != null) {   
  131.           grow = smallGrow;   
  132.         } else {   
  133.           grow = taskGrow;   
  134.         }   
  135.         p = GeometryUtils.getRectangleLineCrossPoint(toNode.getRectangle(), new Point(xPoints[len - 2],   
  136.             yPoints[len - 2]), grow);   
  137.         if (p != null) {   
  138.           xPoints[len - 1] = p.x;   
  139.           yPoints[len - 1] = p.y;   
  140.         }   
  141.         g2.drawPolyline(xPoints, yPoints, len);   
  142.         drawArrow(g2, xPoints[len - 2], yPoints[len - 2], xPoints[len - 1], yPoints[len - 1]);   
  143.         String label = transition.getLabel();   
  144.         if (label != null && label.length() > 0) {   
  145.           int cx, cy;   
  146.           if (len % 2 == 0) {   
  147.             cx = (xPoints[len / 2 - 1] + xPoints[len / 2]) / 2;   
  148.             cy = (yPoints[len / 2 - 1] + yPoints[len / 2]) / 2;   
  149.           } else {   
  150.             cx = xPoints[len / 2];   
  151.             cy = yPoints[len / 2];   
  152.           }   
  153.           Point labelPoint = transition.getLabelPosition();   
  154.           if (labelPoint != null) {   
  155.             cx += labelPoint.x;   
  156.             cy += labelPoint.y;   
  157.           }   
  158.           cy -= RECT_OFFSET_Y + RECT_OFFSET_Y / 2;   
  159.           g2.drawString(label, cx, cy);   
  160.         }   
  161.       }   
  162.     }   
  163.   }   
  164.   
  165.   private void drawArrow(Graphics2D g2, int x1, int y1, int x2, int y2) {   
  166.     final double len = 8.0;   
  167.     double slopy = Math.atan2(y2 - y1, x2 - x1);   
  168.     double cosy = Math.cos(slopy);   
  169.     double siny = Math.sin(slopy);   
  170.     int[] xPoints = { 0, x2, 0 };   
  171.     int[] yPoints = { 0, y2, 0 };   
  172.     double a = len * siny, b = len * cosy;   
  173.     double c = len / 2.0 * siny, d = len / 2.0 * cosy;   
  174.     xPoints[0] = x2 - (int) (b + c);   
  175.     yPoints[0] = y2 - (int) (a - d);   
  176.     xPoints[2] = x2 - (int) (b - c);   
  177.     yPoints[2] = y2 - (int) (d + a);   
  178.        
  179.     g2.fillPolygon(xPoints, yPoints, 3);   
  180.   }   
  181.   
  182.   /**
  183.    * @param g2  
  184.    * @throws IOException  
  185.    */  
  186.   private void drawNode(Map<String, Node> nodes, Graphics2D g2, Font font) throws IOException {   
  187.     for (Node node : nodes.values()) {   
  188.       String name = node.getName();   
  189.       if (nodeInfos.get(node.getType()) != null) {   
  190.         BufferedImage bi2 = ImageIO.read(getClass().getResourceAsStream(   
  191.             "/icons/48/" + nodeInfos.get(node.getType())));   
  192.         g2.drawImage(bi2, node.getX(), node.getY(), null);   
  193.       } else {   
  194.         int x = node.getX();   
  195.         int y = node.getY();   
  196.         int w = node.getWitdth();   
  197.         int h = node.getHeight();   
  198.         g2.setColor(DEFAULT_FILL_COLOR);   
  199.         g2.fillRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);   
  200.         g2.setColor(DEFAULT_STROKE_COLOR);   
  201.         g2.setStroke(DEFAULT_STROKE);   
  202.         g2.drawRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);   
  203.   
  204.         FontRenderContext frc = g2.getFontRenderContext();   
  205.         Rectangle2D r2 = font.getStringBounds(name, frc);   
  206.         int xLabel = (int) (node.getX() + ((node.getWitdth() - r2.getWidth()) / 2));   
  207.         int yLabel = (int) ((node.getY() + ((node.getHeight() - r2.getHeight()) / 2)) - r2.getY());   
  208.         g2.setStroke(DEFAULT_LINE_STROKE);   
  209.         g2.setColor(Color.black);   
  210.         g2.drawString(name, xLabel, yLabel);   
  211.       }   
  212.     }   
  213.   }   
  214. }  


工具类,用来计算一些坐标的
Java代码
  1. /**  
  2.  * CopyRight (C) 2006-2009 yy  
  3.  * @author yy  
  4.  * @project jbpm  
  5.  * @version 1.0  
  6.  * @mail yy629_86 at 163 dot com  
  7.  * @date 2009-9-11 上午06:16:26  
  8.  * @description  
  9.  */  
  10. package sofocus.bpm.jbpm.jpdl;   
  11.   
  12. import java.awt.Point;   
  13. import java.awt.Rectangle;   
  14.   
  15. /**
  16.  * @author yeyong  
  17.  *   
  18.  */  
  19. public class GeometryUtils {   
  20.   /**
  21.    * 获得直线(x1,y1)-(x2,y2)的斜率  
  22.    *   
  23.    * @param x1  
  24.    * @param y1  
  25.    * @param x2  
  26.    * @param y2  
  27.    * @return  
  28.    */  
  29.   public static double getSlope(int x1, int y1, int x2, int y2) {   
  30.     return ((double) y2 - y1) / (x2 - x1);   
  31.   }   
  32.   
  33.   /**
  34.    * 获得直线(x1,y1)-(x2,y2)的y轴截距  
  35.    *   
  36.    * @param x1  
  37.    * @param y1  
  38.    * @param x2  
  39.    * @param y2  
  40.    * @return  
  41.    */  
  42.   public static double getYIntercep(int x1, int y1, int x2, int y2) {   
  43.     return y1 - x1 * getSlope(x1, y1, x2, y2);   
  44.   }   
  45.   /**
  46.    * 获得矩形的中点  
  47.    *   
  48.    * @param rect  
  49.    * @return  
  50.    */  
  51.   public static Point getRectangleCenter(Rectangle rect) {   
  52.     return new Point((int) rect.getCenterX(), (int) rect.getCenterY());   
  53.   }   
  54.   
  55.   /**
  56.    * 获得矩形中心p0与p1的线段和矩形的交点  
  57.    *   
  58.    * @param rectangle  
  59.    * @param p1  
  60.    * @return  
  61.    */  
  62.   public static Point getRectangleLineCrossPoint(Rectangle rectangle, Point p1, int grow) {   
  63.     Rectangle rect = rectangle.getBounds();   
  64.     rect.grow(grow, grow);   
  65.     Point p0 = GeometryUtils.getRectangleCenter(rect);   
  66.   
  67.     if (p1.x == p0.x) {   
  68.       if (p1.y < p0.y) {   
  69.         return new Point(p0.x, rect.y);   
  70.       }   
  71.       return new Point(p0.x, rect.y + rect.height);   
  72.     }   
  73.   
  74.     if (p1.y == p0.y) {   
  75.       if (p1.x < p0.x) {   
  76.         return new Point(rect.x, p0.y);   
  77.       }   
  78.       return new Point(rect.x + rect.width, p0.y);   
  79.     }   
  80.   
  81.     double slope = GeometryUtils.getSlope(p0.x, p0.y, rect.x, rect.y);   
  82.     double slopeLine = GeometryUtils.getSlope(p0.x, p0.y, p1.x, p1.y);   
  83.     double yIntercep = GeometryUtils.getYIntercep(p0.x, p0.y, p1.x, p1.y);   
  84.   
  85.     if (Math.abs(slopeLine) > slope - 1e-2) {   
  86.       if (p1.y < rect.y) {   
  87.         return new Point((int) ((rect.y - yIntercep) / slopeLine), rect.y);   
  88.       } else {   
  89.         return new Point((int) ((rect.y + rect.height - yIntercep) / slopeLine), rect.y + rect.height);   
  90.       }   
  91.     }   
  92.     if (p1.x < rect.x) {   
  93.       return new Point(rect.x, (int) (slopeLine * rect.x + yIntercep));   
  94.     } else {   
  95.       return new Point(rect.x + rect.width, (int) (slopeLine * (rect.x + rect.width) + yIntercep));   
  96.     }   
  97.   }   
  98. }  


测试
Java代码

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();   }

 }