Mxgraph学习(四)

733 阅读3分钟

前言

之前在第二篇文章中详细阐述了如何将mxGraph画布上的内容保存到数据库,那么这篇就记录下后台如何将数据库中的xml文件解析出来,然后进行后台处理。

xml样例

<mxGraphModel>
  <root>
    <mxCell id="0" />
    <mxCell id="1" parent="0" />
    <mxCell id="2" value="初始化百度网页" style="nodeStyle;image=/img/start.f26db4f5.png" parent="1" vertex="1">
      <mxGeometry x="220" y="80" width="130" height="35" as="geometry" />
      <Object name="开始" icon="/img/start.f26db4f5.png" nodeName="start" fullPath="" context="https://www.baidu.com/" operation="" as="data" />
    </mxCell>
    <mxCell id="3" value="输入搜索内容" style="nodeStyle;image=/img/text.ab22920f.png" parent="1" vertex="1">
      <mxGeometry x="220" y="170" width="130" height="35" as="geometry" />
      <Object name="文本框" icon="/img/text.ab22920f.png" nodeName="text" fullPath="/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input" context="hello world" operation="" as="data" />
    </mxCell>
    <mxCell id="4" value="点击百度一下" style="nodeStyle;image=/img/button.144b855d.png" parent="1" vertex="1">
      <mxGeometry x="220" y="250" width="130" height="35" as="geometry" />
      <Object name="按钮" icon="/img/button.144b855d.png" nodeName="button" fullPath="/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input" context="" operation="3" as="data" />
    </mxCell>
    <mxCell id="5" parent="1" source="2" target="3" edge="1">
      <mxGeometry relative="1" as="geometry" />
    </mxCell>
    <mxCell id="6" parent="1" source="3" target="4" edge="1">
      <mxGeometry relative="1" as="geometry" />
    </mxCell>
    <mxCell id="7" value="结束" style="nodeStyle;image=/img/over.61db7b65.png" parent="1" vertex="1">
      <mxGeometry x="220" y="490" width="130" height="35" as="geometry" />
      <Object name="结束" icon="/img/over.61db7b65.png" nodeName="over" fullPath="" context="" operation="" as="data" />
    </mxCell>
    <mxCell id="8" value="延时器" style="nodeStyle;image=/img/delayed.288d27d6.png" vertex="1" parent="1">
      <mxGeometry x="220" y="360" width="130" height="35" as="geometry" />
      <Object name="延时器" icon="/img/delayed.288d27d6.png" nodeName="delayed" fullPath="" context="" operation="20000" as="data" />
    </mxCell>
    <mxCell id="9" edge="1" parent="1" source="4" target="8">
      <mxGeometry relative="1" as="geometry" />
    </mxCell>
    <mxCell id="10" edge="1" parent="1" source="8" target="7">
      <mxGeometry relative="1" as="geometry" />
    </mxCell>
  </root>
</mxGraphModel>

解析xml这里使用的是dom4j. 代码核心类如下图所示:

image.png

GraphParse内容如下

package pers.cz.mxgraph;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * 解析MxGrapth的图形信息
 */
public class GraphParser {

    /**
     * XML 文件
     */
    private final String xml;

    /**
     * 图形信息
     * @param xml
     */
    public GraphParser(String xml) {
        this.xml = xml;
    }

    /**
     * 解析MxGrapth
     * @return 解析
     * @throws ParserConfigurationException 解析配置异常
     * @throws SAXException SAX 异常
     * @throws IOException Io Exception
     */
    public MxGraphModel parse() throws DocumentException {
        //1.创建Reader对象
        SAXReader reader = new SAXReader();
        reader.setEncoding("utf-8");
        //2.加载xml
        Document document = reader.read(new ByteArrayInputStream(xml.getBytes()));
        return new MxGraphModel(document);
    }

}

MxCell如下:

package pers.cz.mxgraph;

import org.dom4j.Element;

import java.util.*;

/**
 * @program: Reids
 * @description: MxCell
 * @author: Cheng Zhi
 * @create: 2023-01-06 10:18
 **/
public class MxCell extends MxElement {

    private static final String ATTR_ID = "id";

    private static final String ATTR_NAME = "value";

    private static final String START_VALUE = "start";

    private static final String START_KEY = "nodeName";

    private Map<String, Object> params;

    private MxGraphModel mxGraphModel;

    public MxCell(Element element) {
        super(element);
    }

    public MxCell(Element element, MxGraphModel mxGraphModel) {
        super(element);
        this.mxGraphModel = mxGraphModel;
    }

    public Integer getId() {
        return Integer.valueOf(getData().get(ATTR_ID));
    }

    public String getName() {

        return getData().get(ATTR_NAME);
    }

    public MxObject getMxObject() {

        return Optional.ofNullable(element.element("Object")).map(object -> new MxObject(object)).orElse(null);
    }

    public Map<String, String> getMxObjectData() {

        return Optional.ofNullable(getMxObject()).map(mxObject -> mxObject.getData()).orElse(new HashMap<>());
    }

    public Map<String, Object> getParams() {
        return params;
    }

    /**
     * 设置自定义参数,用于传递给下个节点
     * @param params
     */
    public void setParams(Map<String, Object> params) {
        this.params = params;
    }

    /**
     * 是否为开始节点
     * @return
     */
    public Boolean isStart() {

        String s = getMxObjectData().get(START_KEY);
        if (s != null && START_VALUE.equals(s)) {
            return true;
        }
        return false;
    }

    /**
     * 获取next节点,因为一个节点可能会有多个子节点
     * @return
     */
    public List<MxCell> getNextCell() {

        int currentId = getId();
        Integer nextId = 0;

        List<MxCell> list = new ArrayList<>();
        mxGraphModel.getMxEdges().stream().filter(mxEdge ->mxEdge.getSourceId() == currentId).forEach((p) -> {
            list.add(mxGraphModel.getMxCell(p.getTargetId()));
        });

        return list;
    }

    /**
     * 判断是否还有下个节点
     * @return
     */
    public boolean hasNext() {

        for (MxEdge mxEdge :mxGraphModel.getMxEdges()) {
            if (mxEdge.getSourceId() == getId()) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取当前节点的所有上游节点的id
     * @return
     */
    public List<Integer> getUpstreamNode() {
        List<Integer> list = new ArrayList<>();
        for (MxEdge mxEdge :mxGraphModel.getMxEdges()) {
            if (mxEdge.getTargetId() == getId()) {
                list.add(mxEdge.getSourceId());
            }
        }

        return list;
    }

    /**
     * 判断当前节点是否有多个上游节点
     * @return
     */
    public boolean hasManyUpstreamMode() {
        if (getUpstreamNode().size() > 1) {
            return true;
        }

        return false;
    }

}

MxEdge内容如下:

package pers.cz.mxgraph;

import org.dom4j.Element;

/**
 * @program: Reids
 * @description: MxEdge
 * @author: Cheng Zhi
 * @create: 2023-01-06 11:32
 **/
public class MxEdge extends MxElement {

    private static final String TRAGET = "target";

    private static final String SOURCE = "source";

    public MxEdge(Element element) {
        super(element);
    }

    public Integer getTargetId() {
        String s = getData().get(TRAGET);
        return Integer.valueOf(s);
    }

    public Integer getSourceId() {
        String s = getData().get(SOURCE);
        return Integer.valueOf(s);
    }
}

MxElement

package pers.cz.mxgraph;

import org.dom4j.Attribute;
import org.dom4j.Element;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: Reids
 * @description: 抽象xml element
 * @author: Cheng Zhi
 * @create: 2023-01-06 10:10
 **/
public abstract class MxElement {

    public Element element;

    private Map<String, String> data = new HashMap<String, String>();

    public MxElement(Element element) {
        this.element = element;
    }

    public List<Attribute> getAttributes() {
        return element.attributes();
    }

    public Map<String, String> getData() {
        List<Attribute> attributes = getAttributes();
        for (Attribute attribute : attributes) {
            data.put(attribute.getName(), attribute.getValue());
        }

        return data;
    }

}

MxGraphModel

package pers.cz.mxgraph;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: Reids
 * @description: MxGraphModel
 * @author: Cheng Zhi
 * @create: 2023-01-06 10:24
 **/
public class MxGraphModel {

    private List<MxCell> mxCells = new ArrayList<>();

    private List<MxObject> mxObjects = new ArrayList<>();

    private List<MxEdge> mxEdges = new ArrayList<>();

    private Map<Integer, MxCell> mxCellMap = new HashMap<Integer, MxCell>();

    private MxCell startCell;

    public MxGraphModel(Document document) {
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.elements();
        readElement(elements);
    }

    /**
     * 递归解析xml
     * @param elements
     */
    private void readElement(List<Element> elements) {

        for (Element element : elements) {
            if (element.getName().equals("mxCell")) {

                // 判断是否为边
                if (isEdge(element)) {
                    MxEdge mxEdge = new MxEdge(element);
                    this.mxEdges.add(mxEdge);
                } else {
                    MxCell mxCell = new MxCell(element, this);
                    if (mxCell.isStart()) {
                        this.startCell = mxCell;
                    }
                    Integer id = mxCell.getId();
                    this.mxCellMap.put(id, mxCell);
                    this.mxCells.add(mxCell);
                }

            }

            if (element.getName().equals("Object")) {
                MxObject mxObject = new MxObject(element);
                this.mxObjects.add(mxObject);
            }

            if (element.elements().size() > 0) {
                readElement(element.elements());
            }
        }
    }

    private Boolean isEdge(Element element) {

        Attribute edge = element.attribute("edge");
        if (edge == null) {
            return false;
        }
        return true;
    }

    public List<MxCell> getMxCells() {
        return mxCells;
    }

    public List<MxObject> getMxObjects() {
        return mxObjects;
    }

    public List<MxEdge> getMxEdges() {
        return mxEdges;
    }

    /**
     * 获取Map描述的节点集合
     * @return
     */
    public Map<Integer, MxCell> getMxCellMap() {
        return mxCellMap;
    }

    /**
     * 获取节点ID对应的节点
     * @param id
     * @return
     */
    public MxCell getMxCell(Integer id) {

        return mxCellMap.get(id);
    }

    /**
     * 获取开始节点
     * @return
     */
    public MxCell getStartCell() {

        if (startCell == null) {
            throw new RuntimeException("不合法的流程");
        }
        return startCell;
    }
}

MxObject

package pers.cz.mxgraph;

import org.dom4j.Element;

/**
 * @program: Reids
 * @description: MxObject
 * @author: Cheng Zhi
 * @create: 2023-01-06 10:55
 **/
public class MxObject extends MxElement {

    private static final String ID = "id";

    public MxObject(Element element) {
        super(element);
    }

    /*public Integer getId() {
        String s = getData().get(ID);
        return Integer.valueOf(s);
    }*/
}

以上就是一个完整的MxGraph导出xml的java解析方式。

预告

下一篇主要介绍一下MxGraph中的通过图形化的拖拽创建起来的流程后台如何运行起来

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第4天,点击查看活动详情