前两篇:
jbpm流程设计器(1)
jbpm流程设计器(2)
在这一篇已经实现了流程的保存与打开,下面看代码
首先写一个链表类来记录绘制流程图时的流程定义
把属性保存在流程节点:
jgraphx的节点类只有一种mxCell,无论线条还是方形、端点,它都是mxCell。mxCell有个方法setValue(Object value)设置mxCell的值,而value的toString()的内容,就是节点显示的文本,我们主要是把流程节点的属性通过setValue方法记录在mxCell上,修改之前的com.workflow.designer.view.GraphView类
把节点保存为流程jpdl文件实现类
打开jpdl流程定义实现类
下面看效果
啥啥,画完时才发现,居然连图形的删除功能都忘记没有实现,一不小心画错了,就只能。。。。。。
生成的流程定义文件
jbpm流程设计器(1)
jbpm流程设计器(2)
在这一篇已经实现了流程的保存与打开,下面看代码
首先写一个链表类来记录绘制流程图时的流程定义
package
com.workflow.designer.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class FlowProperty implements Serializable {
private String type = null; //记录节点名
private List<FlowProperty> child = null; //记录子节点
private Map<String, String> property = null; //节点属性
public FlowProperty(String type){
this.type = type;
this.child = new ArrayList<FlowProperty>();
this.property = new Hashtable<String, String>();
}
public void addChild(FlowProperty fp){
child.add(fp);
}
public List<FlowProperty> getChild(){
return child;
}
public void addProperty(String key, String value){
property.put(key, value);
}
public String getProperty(String key){
return property.get(key);
}
//把类转为jpdl的流程定义文本
public String toJpdl(){
StringBuilder sb = new StringBuilder();
sb.append("<").append(type);
Iterator<Entry<String, String>> it = property.entrySet().iterator();
while(it.hasNext()){
sb.append(" ");
Entry<String, String> e = it.next();
sb.append(e.getKey()).append("=\"").append(e.getValue()).append("\"");
}
if(child.size() > 0){
sb.append(">\n");
for(FlowProperty fp:child){
sb.append(fp.toJpdl());
}
sb.append("\n</").append(type).append(">");
}
else{
sb.append(" />");
}
return sb.toString();
}
public String getType() {
return type;
}
public String toString(){
return this.getProperty("name") == null ? "" : getProperty("name");
}
}
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class FlowProperty implements Serializable {
private String type = null; //记录节点名
private List<FlowProperty> child = null; //记录子节点
private Map<String, String> property = null; //节点属性
public FlowProperty(String type){
this.type = type;
this.child = new ArrayList<FlowProperty>();
this.property = new Hashtable<String, String>();
}
public void addChild(FlowProperty fp){
child.add(fp);
}
public List<FlowProperty> getChild(){
return child;
}
public void addProperty(String key, String value){
property.put(key, value);
}
public String getProperty(String key){
return property.get(key);
}
//把类转为jpdl的流程定义文本
public String toJpdl(){
StringBuilder sb = new StringBuilder();
sb.append("<").append(type);
Iterator<Entry<String, String>> it = property.entrySet().iterator();
while(it.hasNext()){
sb.append(" ");
Entry<String, String> e = it.next();
sb.append(e.getKey()).append("=\"").append(e.getValue()).append("\"");
}
if(child.size() > 0){
sb.append(">\n");
for(FlowProperty fp:child){
sb.append(fp.toJpdl());
}
sb.append("\n</").append(type).append(">");
}
else{
sb.append(" />");
}
return sb.toString();
}
public String getType() {
return type;
}
public String toString(){
return this.getProperty("name") == null ? "" : getProperty("name");
}
}
把属性保存在流程节点:
jgraphx的节点类只有一种mxCell,无论线条还是方形、端点,它都是mxCell。mxCell有个方法setValue(Object value)设置mxCell的值,而value的toString()的内容,就是节点显示的文本,我们主要是把流程节点的属性通过setValue方法记录在mxCell上,修改之前的com.workflow.designer.view.GraphView类
public
class
GraphView
extends
GraphImpl
{
public void inser(Point p, Node n){
this.getGraph().getModel().beginUpdate();
try{
//调用jgraph插入节点
Object v1 = graph.insertVertex(parent, null, n.getLabel(), p.getX() - 5, p.getY() - 5, n.getWidth(),
n.getHeight(), n.getShape());
mxCell cell = (mxCell)v1;
mxGeometry g = cell.getGeometry();
Rectangle r = g.getRectangle();
cell.setConnectable(false);
FlowProperty fp = new FlowProperty(n.getType());
fp.addProperty("name", n.getLabel());
fp.addProperty("g", r.getX() + "," + r.getY() + "," + r.getWidth() + "," + r.getHeight());
cell.setValue(fp);
}
finally{
graph.getModel().endUpdate();
}
}
}
public void inser(Point p, Node n){
this.getGraph().getModel().beginUpdate();
try{
//调用jgraph插入节点
Object v1 = graph.insertVertex(parent, null, n.getLabel(), p.getX() - 5, p.getY() - 5, n.getWidth(),
n.getHeight(), n.getShape());
mxCell cell = (mxCell)v1;
mxGeometry g = cell.getGeometry();
Rectangle r = g.getRectangle();
cell.setConnectable(false);
FlowProperty fp = new FlowProperty(n.getType());
fp.addProperty("name", n.getLabel());
fp.addProperty("g", r.getX() + "," + r.getY() + "," + r.getWidth() + "," + r.getHeight());
cell.setValue(fp);
}
finally{
graph.getModel().endUpdate();
}
}
}
把节点保存为流程jpdl文件实现类
package
com.workflow.designer.jpdl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import com.mxgraph.model.mxCell;
import com.mxgraph.view.mxGraph;
import com.workflow.designer.util.FlowProperty;
public class SaveJpdl implements Serializable {
private mxGraph graph = null;
private String fileName = null;
public SaveJpdl(){
}
public void save(String fileName, mxGraph graph){
this.fileName = fileName;
this.graph = graph;
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"GBK\"?>\n");
sb.append(this.toJpdl());
try{
FileOutputStream fos = new FileOutputStream(new File(fileName));
fos.write(sb.toString().getBytes("GBK"));
fos.flush();
fos.close();
}
catch(Exception e){
e.printStackTrace();
}
}
private String toJpdl(){
Object parent = graph.getDefaultParent();
Object[] ocjectCells = graph.getChildCells(parent);
FlowProperty process = new FlowProperty("process");
process.addProperty("name", "process");
process.addProperty("xmlns", "http://jbpm.org/4.4/jpdl");
for(Object objectCell:ocjectCells){
if(objectCell instanceof mxCell){
mxCell cell = (mxCell)objectCell;
if(cell.isEdge() == false){
Object objectValue = cell.getValue();
if(objectValue != null && objectValue instanceof FlowProperty){
FlowProperty flowNode = (FlowProperty)objectValue;
process.addChild(flowNode);
}
}
}
}
return process.toJpdl();
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import com.mxgraph.model.mxCell;
import com.mxgraph.view.mxGraph;
import com.workflow.designer.util.FlowProperty;
public class SaveJpdl implements Serializable {
private mxGraph graph = null;
private String fileName = null;
public SaveJpdl(){
}
public void save(String fileName, mxGraph graph){
this.fileName = fileName;
this.graph = graph;
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"GBK\"?>\n");
sb.append(this.toJpdl());
try{
FileOutputStream fos = new FileOutputStream(new File(fileName));
fos.write(sb.toString().getBytes("GBK"));
fos.flush();
fos.close();
}
catch(Exception e){
e.printStackTrace();
}
}
private String toJpdl(){
Object parent = graph.getDefaultParent();
Object[] ocjectCells = graph.getChildCells(parent);
FlowProperty process = new FlowProperty("process");
process.addProperty("name", "process");
process.addProperty("xmlns", "http://jbpm.org/4.4/jpdl");
for(Object objectCell:ocjectCells){
if(objectCell instanceof mxCell){
mxCell cell = (mxCell)objectCell;
if(cell.isEdge() == false){
Object objectValue = cell.getValue();
if(objectValue != null && objectValue instanceof FlowProperty){
FlowProperty flowNode = (FlowProperty)objectValue;
process.addChild(flowNode);
}
}
}
}
return process.toJpdl();
}
}
打开jpdl流程定义实现类
package
com.workflow.designer.jpdl;
import java.io.File;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.view.mxGraph;
import com.workflow.designer.model.FlowNode;
import com.workflow.designer.model.Node;
import com.workflow.designer.util.FlowProperty;
import com.workflow.designer.util.Logger;
import com.workflow.designer.util.ObjectXml;
public class OpenJpdl {
private mxGraph graph = null;
private String fileName = null;
public OpenJpdl(){
}
public void open(String fileName, mxGraph graph){
this.fileName = fileName;
this.graph = graph;
Object parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
try {
File f = new File(fileName);
SAXReader reader = new SAXReader();
Document doc = reader.read(f);
Element root = doc.getRootElement();
FlowProperty process = new FlowProperty("process");
parseJpdl(root, process);
List<FlowProperty> list = process.getChild();
ObjectXml ox = new ObjectXml();
Map<String, Object> cellMap = new Hashtable<String, Object>();
for(FlowProperty node:list){
String type = node.getType();
Node n = ox.getNode(type);
String g = node.getProperty("g");
int[] r = toRectangle(g);
Object v = graph.insertVertex(parent, null, node, r[0], r[1], r[2],
r[3], n.getShape());
cellMap.put(node.getProperty("name"), v);
}
for(FlowProperty node:list){
List<FlowProperty> edges = node.getChild();
if(edges.size() > 0){
int size = edges.size();
for(int h = 0; h < size; h++){
FlowProperty edge = edges.get(0);
if(edge.getType().equals("transition")){
Object s = cellMap.get(node.getProperty("name"));
Object t = cellMap.get(edge.getProperty("to"));
Object v = graph.insertEdge(parent, null, "", s, t);
edges.remove(edge);
}
}
}
}
//Logger.debug(process.toJpdl());
}catch (Exception e) {
e.printStackTrace();
}
finally{
graph.getModel().endUpdate();
}
}
private int[] toRectangle(String g){
int[] r ;
String[] str = g.split(",");
r = new int[str.length];
for(int i = 0; i < str.length; i++){
r[i] = Float.valueOf(str[i]).intValue();
}
return r;
}
public void parseJpdl(Element element, FlowProperty fp){
for ( Iterator a = element.attributeIterator(); a.hasNext(); ) {
Attribute attribute = (Attribute) a.next();
fp.addProperty(attribute.getName(), attribute.getValue());
}
for ( Iterator a = element.elementIterator(); a.hasNext(); ) {
Element e = (Element) a.next();
FlowProperty flowNode = new FlowProperty(e.getName());
parseJpdl(e, flowNode);
fp.addChild(flowNode);
}
}
}
import java.io.File;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.view.mxGraph;
import com.workflow.designer.model.FlowNode;
import com.workflow.designer.model.Node;
import com.workflow.designer.util.FlowProperty;
import com.workflow.designer.util.Logger;
import com.workflow.designer.util.ObjectXml;
public class OpenJpdl {
private mxGraph graph = null;
private String fileName = null;
public OpenJpdl(){
}
public void open(String fileName, mxGraph graph){
this.fileName = fileName;
this.graph = graph;
Object parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
try {
File f = new File(fileName);
SAXReader reader = new SAXReader();
Document doc = reader.read(f);
Element root = doc.getRootElement();
FlowProperty process = new FlowProperty("process");
parseJpdl(root, process);
List<FlowProperty> list = process.getChild();
ObjectXml ox = new ObjectXml();
Map<String, Object> cellMap = new Hashtable<String, Object>();
for(FlowProperty node:list){
String type = node.getType();
Node n = ox.getNode(type);
String g = node.getProperty("g");
int[] r = toRectangle(g);
Object v = graph.insertVertex(parent, null, node, r[0], r[1], r[2],
r[3], n.getShape());
cellMap.put(node.getProperty("name"), v);
}
for(FlowProperty node:list){
List<FlowProperty> edges = node.getChild();
if(edges.size() > 0){
int size = edges.size();
for(int h = 0; h < size; h++){
FlowProperty edge = edges.get(0);
if(edge.getType().equals("transition")){
Object s = cellMap.get(node.getProperty("name"));
Object t = cellMap.get(edge.getProperty("to"));
Object v = graph.insertEdge(parent, null, "", s, t);
edges.remove(edge);
}
}
}
}
//Logger.debug(process.toJpdl());
}catch (Exception e) {
e.printStackTrace();
}
finally{
graph.getModel().endUpdate();
}
}
private int[] toRectangle(String g){
int[] r ;
String[] str = g.split(",");
r = new int[str.length];
for(int i = 0; i < str.length; i++){
r[i] = Float.valueOf(str[i]).intValue();
}
return r;
}
public void parseJpdl(Element element, FlowProperty fp){
for ( Iterator a = element.attributeIterator(); a.hasNext(); ) {
Attribute attribute = (Attribute) a.next();
fp.addProperty(attribute.getName(), attribute.getValue());
}
for ( Iterator a = element.elementIterator(); a.hasNext(); ) {
Element e = (Element) a.next();
FlowProperty flowNode = new FlowProperty(e.getName());
parseJpdl(e, flowNode);
fp.addChild(flowNode);
}
}
}
下面看效果
啥啥,画完时才发现,居然连图形的删除功能都忘记没有实现,一不小心画错了,就只能。。。。。。
生成的流程定义文件
<?
xml version="1.0" encoding="GBK"
?>
< process name ="process" xmlns ="http://jbpm.org/4.4/jpdl" >
< start name ="开始" g ="48.0,28.0,40.0,40.0" >
< transition name ="to 领导审核" g ="0.0,0.0" to ="领导审核" />
</ start >
< task name ="领导审核" g ="160.0,30.0,80.0,40.0" >
< transition name ="to 财务部签收" g ="0.0,0.0" to ="财务部签收" />
</ task >
< task name ="财务部签收" g ="160.0,110.0,80.0,40.0" >
< transition name ="to 结束" g ="0.0,0.0" to ="结束" />
</ task >
< end name ="结束" g ="180.0,220.0,40.0,40.0" />
</ process >
< process name ="process" xmlns ="http://jbpm.org/4.4/jpdl" >
< start name ="开始" g ="48.0,28.0,40.0,40.0" >
< transition name ="to 领导审核" g ="0.0,0.0" to ="领导审核" />
</ start >
< task name ="领导审核" g ="160.0,30.0,80.0,40.0" >
< transition name ="to 财务部签收" g ="0.0,0.0" to ="财务部签收" />
</ task >
< task name ="财务部签收" g ="160.0,110.0,80.0,40.0" >
< transition name ="to 结束" g ="0.0,0.0" to ="结束" />
</ task >
< end name ="结束" g ="180.0,220.0,40.0,40.0" />
</ process >
jgraphx可以直接生成图片的,只是本人一时找不到哪一个方法是生成图片的。。。。。。要实现生成图片,请自行阅读API
一般开发流程设计器都是为了简化流程的开发,对于非常非常复杂的流程或者对于客户(非开发人员)来说,提供可视化的流程流程设计器比手工写流程定义效率和准确性高很多;不多说,还是自己慢慢体会。
设计器的文章介绍完毕,有兴趣的朋友自己继续深入研究。另外jgraphx还提供了javascript版,有兴趣的可以自行研究使用javascript版开发流程设计器。
后段有时间的话,会写点jbpm4.4入门类的文章或其它。
附件:jgraphxflow.jar.rar