前兩篇:
jbpm流程設(shè)計(jì)器(1)
jbpm流程設(shè)計(jì)器(2)
在這一篇已經(jīng)實(shí)現(xiàn)了流程的保存與打開,下面看代碼
首先寫一個(gè)鏈表類來記錄繪制流程圖時(shí)的流程定義
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; //記錄節(jié)點(diǎn)名
private List<FlowProperty> child = null; //記錄子節(jié)點(diǎn)
private Map<String, String> property = null; //節(jié)點(diǎn)屬性
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);
}
//把類轉(zhuǎn)為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");
}
}
把屬性保存在流程節(jié)點(diǎn):
jgraphx的節(jié)點(diǎn)類只有一種mxCell,無論線條還是方形、端點(diǎn),它都是mxCell。mxCell有個(gè)方法setValue(Object value)設(shè)置mxCell的值,而value的toString()的內(nèi)容,就是節(jié)點(diǎn)顯示的文本,我們主要是把流程節(jié)點(diǎn)的屬性通過setValue方法記錄在mxCell上,修改之前的com.workflow.designer.view.GraphView類
public class GraphView extends GraphImpl{




public void inser(Point p, Node n){
this.getGraph().getModel().beginUpdate();
try{
//調(diào)用jgraph插入節(jié)點(diǎn)
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();
}
}



}
把節(jié)點(diǎn)保存為流程jpdl文件實(shí)現(xiàn)類
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();
}
}
打開jpdl流程定義實(shí)現(xiàn)類
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);
}
}
}
下面看效果

啥啥,畫完時(shí)才發(fā)現(xiàn),居然連圖形的刪除功能都忘記沒有實(shí)現(xiàn),一不小心畫錯(cuò)了,就只能。。。。。。
生成的流程定義文件
<?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 領(lǐng)導(dǎo)審核" g="0.0,0.0" to="領(lǐng)導(dǎo)審核" />
</start>
<task name="領(lǐng)導(dǎo)審核" g="160.0,30.0,80.0,40.0">
<transition name="to 財(cái)務(wù)部簽收" g="0.0,0.0" to="財(cái)務(wù)部簽收" />
</task>
<task name="財(cái)務(wù)部簽收" g="160.0,110.0,80.0,40.0">
<transition name="to 結(jié)束" g="0.0,0.0" to="結(jié)束" />
</task>
<end name="結(jié)束" g="180.0,220.0,40.0,40.0" />
</process>
jbpm流程設(shè)計(jì)器(1)
jbpm流程設(shè)計(jì)器(2)
在這一篇已經(jīng)實(shí)現(xiàn)了流程的保存與打開,下面看代碼
首先寫一個(gè)鏈表類來記錄繪制流程圖時(shí)的流程定義




































































把屬性保存在流程節(jié)點(diǎn):
jgraphx的節(jié)點(diǎn)類只有一種mxCell,無論線條還是方形、端點(diǎn),它都是mxCell。mxCell有個(gè)方法setValue(Object value)設(shè)置mxCell的值,而value的toString()的內(nèi)容,就是節(jié)點(diǎn)顯示的文本,我們主要是把流程節(jié)點(diǎn)的屬性通過setValue方法記錄在mxCell上,修改之前的com.workflow.designer.view.GraphView類




























把節(jié)點(diǎn)保存為流程jpdl文件實(shí)現(xiàn)類























































打開jpdl流程定義實(shí)現(xiàn)類





































































































下面看效果

啥啥,畫完時(shí)才發(fā)現(xiàn),居然連圖形的刪除功能都忘記沒有實(shí)現(xiàn),一不小心畫錯(cuò)了,就只能。。。。。。
生成的流程定義文件













jgraphx可以直接生成圖片的,只是本人一時(shí)找不到哪一個(gè)方法是生成圖片的。。。。。。要實(shí)現(xiàn)生成圖片,請(qǐng)自行閱讀API
一般開發(fā)流程設(shè)計(jì)器都是為了簡(jiǎn)化流程的開發(fā),對(duì)于非常非常復(fù)雜的流程或者對(duì)于客戶(非開發(fā)人員)來說,提供可視化的流程流程設(shè)計(jì)器比手工寫流程定義效率和準(zhǔn)確性高很多;不多說,還是自己慢慢體會(huì)。
設(shè)計(jì)器的文章介紹完畢,有興趣的朋友自己繼續(xù)深入研究。另外jgraphx還提供了javascript版,有興趣的可以自行研究使用javascript版開發(fā)流程設(shè)計(jì)器。
后段有時(shí)間的話,會(huì)寫點(diǎn)jbpm4.4入門類的文章或其它。
附件:jgraphxflow.jar.rar