jbpm4.4根据.jpdl.xml流程定义文件,得到流程图.png
先看节点类的定义:
- public class Node {
- private String name;
- private String type;
- private Rectangle rectangle;
- private List<Transition> transitions = new ArrayList<Transition>();
- public Node(String name, String type) {
- this.name = name;
- this.type = type;
- }
- public Node(String name, String type, int x, int y, int w, int h) {
- this.name = name;
- this.type = type;
- this.rectangle = new Rectangle(x, y, w, h);
- }
- public Rectangle getRectangle() {
- return rectangle;
- }
- public void setRectangle(Rectangle rectangle) {
- this.rectangle = rectangle;
- }
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void addTransition(Transition transition) {
- transitions.add(transition);
- }
- public List<Transition> getTransitions() {
- return transitions;
- }
- public void setTransitions(List<Transition> transitions) {
- this.transitions = transitions;
- }
- public int getX() {
- return rectangle.x;
- }
- public int getY() {
- return rectangle.y;
- }
- public int getCenterX() {
- return (int) rectangle.getCenterX();
- }
- public int getCenterY() {
- return (int) rectangle.getCenterY();
- }
- public int getWitdth() {
- return rectangle.width;
- }
- public int getHeight() {
- return rectangle.height;
- }
- }
其次是Transition的定义:
- public class Transition {
- private Point labelPosition;
- private List<Point> lineTrace = new ArrayList<Point>();
- private String label;
- private String to;
- public Transition(String label, String to) {
- this.label = label;
- this.to = to;
- }
- public Point getLabelPosition() {
- return labelPosition;
- }
- public void setLabelPosition(Point labelPosition) {
- this.labelPosition = labelPosition;
- }
- public List<Point> getLineTrace() {
- return lineTrace;
- }
- public void setLineTrace(List<Point> lineTrace) {
- this.lineTrace = lineTrace;
- }
- public void addLineTrace(Point lineTrace) {
- if (lineTrace != null) {
- this.lineTrace.add(lineTrace);
- }
- }
- public String getLabel() {
- return label;
- }
- public void setLabel(String label) {
- this.label = label;
- }
- public String getTo() {
- return to;
- }
- public void setTo(String to) {
- this.to = to;
- }
- }
类JpdlModel
- /**
- * CopyRight (C) 2006-2009 yy
- * @author yy
- * @project jbpm
- * @version 1.0
- * @mail yy629_86 at 163 dot com
- * @date 2009-9-6 下午06:00:14
- * @description
- */
- package sofocus.bpm.jbpm.jpdl.model;
- import java.awt.Point;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- public class JpdlModel {
- private Map<String, Node> nodes = new LinkedHashMap<String, Node>();
- public static final int RECT_OFFSET_X = -7;
- public static final int RECT_OFFSET_Y = -8;
- public static final int DEFAULT_PIC_SIZE = 48;
- private final static Map<String, Object> nodeInfos = new HashMap<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);
- }
- public JpdlModel(InputStream is) throws Exception {
- this(new SAXReader().read(is).getRootElement());
- }
- @SuppressWarnings("unchecked")
- private JpdlModel(Element rootEl) throws Exception {
- for (Element el : (List<Element>) rootEl.elements()) {
- String type = el.getQName().getName();
- if (!nodeInfos.containsKey(type)) { // 不是可展示的节点
- continue;
- }
- String name = null;
- if (el.attribute("name") != null) {
- name = el.attributeValue("name");
- }
- String[] location = el.attributeValue("g").split(",");
- int x = Integer.parseInt(location[0]);
- int y = Integer.parseInt(location[1]);
- int w = Integer.parseInt(location[2]);
- int h = 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);
- }
- Node node = new Node(name, type, x, y, w, h);
- parserTransition(node, el);
- nodes.put(name, node);
- }
- }
- @SuppressWarnings("unchecked")
- private void parserTransition(Node node, Element nodeEl) {
- for (Element el : (List<Element>) nodeEl.elements("transition")) {
- String label = el.attributeValue("name");
- String to = el.attributeValue("to");
- Transition transition = new Transition(label, to);
- String g = 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 (String line : lines) {
- transition.addLineTrace(getPoint(line));
- }
- }
- }
- node.addTransition(transition);
- }
- }
- private Point getPoint(String exp) {
- if (exp == null || exp.length() == 0) {
- return null;
- }
- String[] p = exp.split(",");
- return new Point(Integer.valueOf(p[0]), Integer.valueOf(p[1]));
- }
- public Map<String, Node> getNodes() {
- return nodes;
- }
- public static Map<String, Object> getNodeInfos() {
- return nodeInfos;
- }
- }
根据JpdlModel绘制出流程图
- /**
- * CopyRight (C) 2006-2009 yy
- * @author yy
- * @project Jbpm
- * @version 1.0
- * @mail yy629_86 at 163 dot com
- * @date 2009-9-6 下午06:00:14
- * @description
- */
- package sofocus.bpm.jbpm.jpdl;
- import java.awt.*;
- import java.awt.font.FontRenderContext;
- import java.awt.geom.Rectangle2D;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import java.util.List;
- import java.util.Map;
- import javax.imageio.ImageIO;
- import sofocus.bpm.jbpm.jpdl.model.JpdlModel;
- import sofocus.bpm.jbpm.jpdl.model.Node;
- import sofocus.bpm.jbpm.jpdl.model.Transition;
- /**
- * @author yeyong
- *
- */
- public class JpdlModelDrawer {
- public static final int RECT_OFFSET_X = JpdlModel.RECT_OFFSET_X;
- public static final int RECT_OFFSET_Y = JpdlModel.RECT_OFFSET_Y;
- public static final int RECT_ROUND = 25;
- public static final int DEFAULT_FONT_SIZE = 12;
- public static final Color DEFAULT_STROKE_COLOR = Color.decode("#03689A");
- public static final Stroke DEFAULT_STROKE = new BasicStroke(2);
- public static final Color DEFAULT_LINE_STROKE_COLOR = Color.decode("#808080");
- public static final Stroke DEFAULT_LINE_STROKE = new BasicStroke(1);
- public static final Color DEFAULT_FILL_COLOR = Color.decode("#F6F7FF");
- private final static Map<String, Object> nodeInfos = JpdlModel.getNodeInfos();
- public BufferedImage draw(JpdlModel jpdlModel) throws IOException {
- Rectangle dimension = getCanvasDimension(jpdlModel);
- BufferedImage bi = new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2 = bi.createGraphics();
- g2.setColor(Color.WHITE);
- g2.fillRect(0, 0, dimension.width, dimension.height);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- Font font = new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE);
- g2.setFont(font);
- Map<String, Node> nodes = jpdlModel.getNodes();
- drawNode(nodes, g2, font);
- drawTransition(nodes, g2);
- return bi;
- }
- /**
- * 获得图片的矩形大小
- *
- * @return
- */
- private Rectangle getCanvasDimension(JpdlModel jpdlModel) {
- Rectangle rectangle = new Rectangle();
- Rectangle rect;
- for (Node node : 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 (Transition transition : node.getTransitions()) {
- List<Point> trace = transition.getLineTrace();
- for (Point point : 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;
- return rectangle;
- }
- /**
- * @param g2
- * @throws IOException
- */
- private void drawTransition(Map<String, Node> nodes, Graphics2D g2) throws IOException {
- g2.setStroke(DEFAULT_LINE_STROKE);
- g2.setColor(DEFAULT_LINE_STROKE_COLOR);
- for (Node node : nodes.values()) {
- for (Transition transition : node.getTransitions()) {
- String to = transition.getTo();
- Node toNode = nodes.get(to);
- List<Point> trace = new LinkedList<Point>(transition.getLineTrace());
- int len = trace.size() + 2;
- trace.add(0, new Point(node.getCenterX(), node.getCenterY()));
- trace.add(new Point(toNode.getCenterX(), toNode.getCenterY()));
- int[] xPoints = new int[len];
- int[] yPoints = new int[len];
- for (int i = 0; i < len; i++) {
- xPoints[i] = trace.get(i).x;
- yPoints[i] = trace.get(i).y;
- }
- final int taskGrow = 4;
- final int smallGrow = -2;
- int grow = 0;
- if (nodeInfos.get(node.getType()) != null) {
- grow = smallGrow;
- } else {
- grow = taskGrow;
- }
- Point p = GeometryUtils.getRectangleLineCrossPoint(node.getRectangle(), new Point(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(), new Point(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]);
- String label = transition.getLabel();
- if (label != null && label.length() > 0) {
- int cx, 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];
- }
- Point labelPoint = transition.getLabelPosition();
- if (labelPoint != null) {
- cx += labelPoint.x;
- cy += labelPoint.y;
- }
- cy -= RECT_OFFSET_Y + RECT_OFFSET_Y / 2;
- g2.drawString(label, cx, cy);
- }
- }
- }
- }
- private void drawArrow(Graphics2D g2, int x1, int y1, int x2, int y2) {
- final double len = 8.0;
- double slopy = Math.atan2(y2 - y1, x2 - x1);
- double cosy = Math.cos(slopy);
- double siny = Math.sin(slopy);
- int[] xPoints = { 0, x2, 0 };
- int[] yPoints = { 0, y2, 0 };
- double a = len * siny, b = len * cosy;
- double c = 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, yPoints, 3);
- }
- /**
- * @param g2
- * @throws IOException
- */
- private void drawNode(Map<String, Node> nodes, Graphics2D g2, Font font) throws IOException {
- for (Node node : nodes.values()) {
- String name = node.getName();
- if (nodeInfos.get(node.getType()) != null) {
- BufferedImage bi2 = ImageIO.read(getClass().getResourceAsStream(
- "/icons/48/" + nodeInfos.get(node.getType())));
- g2.drawImage(bi2, node.getX(), node.getY(), null);
- } else {
- int x = node.getX();
- int y = node.getY();
- int w = node.getWitdth();
- int h = node.getHeight();
- g2.setColor(DEFAULT_FILL_COLOR);
- g2.fillRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);
- g2.setColor(DEFAULT_STROKE_COLOR);
- g2.setStroke(DEFAULT_STROKE);
- g2.drawRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);
- FontRenderContext frc = g2.getFontRenderContext();
- Rectangle2D r2 = font.getStringBounds(name, frc);
- int xLabel = (int) (node.getX() + ((node.getWitdth() - r2.getWidth()) / 2));
- int yLabel = (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-2009 yy
- * @author yy
- * @project jbpm
- * @version 1.0
- * @mail yy629_86 at 163 dot com
- * @date 2009-9-11 上午06:16:26
- * @description
- */
- package sofocus.bpm.jbpm.jpdl;
- import java.awt.Point;
- import java.awt.Rectangle;
- /**
- * @author yeyong
- *
- */
- public class GeometryUtils {
- /**
- * 获得直线(x1,y1)-(x2,y2)的斜率
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @return
- */
- public static double getSlope(int x1, int y1, int x2, int y2) {
- return ((double) y2 - y1) / (x2 - x1);
- }
- /**
- * 获得直线(x1,y1)-(x2,y2)的y轴截距
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @return
- */
- public static double getYIntercep(int x1, int y1, int x2, int y2) {
- return y1 - x1 * getSlope(x1, y1, x2, y2);
- }
- /**
- * 获得矩形的中点
- *
- * @param rect
- * @return
- */
- public static Point getRectangleCenter(Rectangle rect) {
- return new Point((int) rect.getCenterX(), (int) rect.getCenterY());
- }
- /**
- * 获得矩形中心p0与p1的线段和矩形的交点
- *
- * @param rectangle
- * @param p1
- * @return
- */
- public static Point getRectangleLineCrossPoint(Rectangle rectangle, Point p1, int grow) {
- Rectangle rect = rectangle.getBounds();
- rect.grow(grow, grow);
- Point p0 = GeometryUtils.getRectangleCenter(rect);
- if (p1.x == p0.x) {
- if (p1.y < p0.y) {
- return new Point(p0.x, rect.y);
- }
- return new Point(p0.x, rect.y + rect.height);
- }
- if (p1.y == p0.y) {
- if (p1.x < p0.x) {
- return new Point(rect.x, p0.y);
- }
- return new Point(rect.x + rect.width, p0.y);
- }
- double slope = GeometryUtils.getSlope(p0.x, p0.y, rect.x, rect.y);
- double slopeLine = GeometryUtils.getSlope(p0.x, p0.y, p1.x, p1.y);
- double yIntercep = GeometryUtils.getYIntercep(p0.x, p0.y, p1.x, p1.y);
- if (Math.abs(slopeLine) > slope - 1e-2) {
- if (p1.y < rect.y) {
- return new Point((int) ((rect.y - yIntercep) / slopeLine), rect.y);
- } else {
- return new Point((int) ((rect.y + rect.height - yIntercep) / slopeLine), rect.y + rect.height);
- }
- }
- if (p1.x < rect.x) {
- return new Point(rect.x, (int) (slopeLine * rect.x + yIntercep));
- } else {
- return new Point(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(); }
}