Meine Frage ist sehr einfach. Wie kann ich eine BPMN-Datei analysieren? Gibt es dafür ein Paket in Java? Ich habe einen Beispielcode von googling gefunden, aber es gibt keine main
und es gibt keine Methode, die die BPMN-Datei zu analysieren, um es zu analysieren.Parsen BPMN-Datei
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityBehaviour;
import org.jbpm.bpmn.common.Resource;
import org.jbpm.bpmn.common.ResourceParameter;
import org.jbpm.bpmn.flownodes.BpmnActivity;
import org.jbpm.bpmn.model.BpmnProcessDefinition;
import org.jbpm.bpmn.model.SequenceflowCondition;
import org.jbpm.bpmn.parser.BindingsParser;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.cal.CronExpression;
import org.jbpm.pvm.internal.cal.Duration;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.CompositeElementImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.model.ScopeElementImpl;
import org.jbpm.pvm.internal.model.TimerDefinitionImpl;
import org.jbpm.pvm.internal.model.TransitionImpl;
import org.jbpm.pvm.internal.model.VariableDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
import org.jbpm.pvm.internal.util.CollectionUtil;
import org.jbpm.pvm.internal.util.TagBinding;
import org.jbpm.pvm.internal.util.XmlUtil;
import org.jbpm.pvm.internal.xml.Bindings;
import org.jbpm.pvm.internal.xml.Parse;
import org.jbpm.pvm.internal.xml.Parser;
public class BpmnParser extends Parser {
private static final Log log = Log.getLog(BpmnParser.class.getName());
private static final String[] DEFAULT_ACTIVITIES_RESOURCES = { "jbpm.bpmn.flownodes.xml" };
private static final String CATEGORY_ACTIVITY = "activity";
private static final String[] SCHEMA_RESOURCES = { "BPMN20.xsd", "DiagramDefinition.xsd",
"DiagramInterchange.xsd", "BpmnDi.xsd" };
static BindingsParser bindingsParser = new BindingsParser();
public BpmnParser() {
// initialises bindings
parseBindings();
// Setting BPMN2 xsd schema
setSchemaResources(SCHEMA_RESOURCES);
}
public Object parseDocumentElement(Element documentElement, Parse parse) {
List<ProcessDefinitionImpl> processDefinitions = new ArrayList<ProcessDefinitionImpl>();
parseDefinition(documentElement, parse);
for (Element processElement : XmlUtil.elements(documentElement, "process")) {
ProcessDefinitionImpl processDefinition = parseProcess(processElement, parse);
processDefinitions.add(processDefinition);
}
return processDefinitions;
}
public ProcessDefinitionImpl parseProcess(Element processElement, Parse parse) {
BpmnProcessDefinition processDefinition = new BpmnProcessDefinition();
parse.contextStackPush(processDefinition);
try {
String id = XmlUtil.attribute(processElement, "id", parse);
String name = XmlUtil.attribute(processElement, "name");
if (id != null && !"".equals(id)) {
processDefinition.setName(id);
} else {
parse.addProblem("Process has no or an empty id");
}
if (name != null) {
processDefinition.setKey(name);
}
Element descriptionElement = XmlUtil.element(processElement, "documentation");
if (descriptionElement != null) {
String description = XmlUtil.getContentText(descriptionElement);
processDefinition.setDescription(description);
}
parseResources((Element)processElement.getParentNode(), parse, processDefinition);
parseInterfaces((Element)processElement.getParentNode(), parse, processDefinition);
parseItemDefinitions((Element)processElement.getParentNode(), parse, processDefinition);
parseMessages((Element)processElement.getParentNode(), parse, processDefinition);
parseDataObjects(processElement, parse, processDefinition);
// activities
parseActivities(processElement, parse, processDefinition);
// bind activities to their destinations
parseSequenceFlow(processElement, parse, processDefinition);
} finally {
parse.contextStackPop();
}
return processDefinition;
}
// /////////////////////////////////////////////////////////////////////////////////////////
protected void parseBindings() {
Bindings bindings = new Bindings();
setBindings(bindings);
for (String activityResource : DEFAULT_ACTIVITIES_RESOURCES) {
Enumeration<URL> resourceUrls = getResources(activityResource);
if (resourceUrls.hasMoreElements()) {
while (resourceUrls.hasMoreElements()) {
URL resourceUrl = resourceUrls.nextElement();
log.trace("loading bpmn activities from resource: " + resourceUrl);
List<?> activityBindings = (List<?>) bindingsParser.createParse()
.setUrl(resourceUrl)
.execute()
.checkErrors("bpmn activities from " + resourceUrl.toString())
.getDocumentObject();
for (TagBinding binding: CollectionUtil.checkList(activityBindings, TagBinding.class)) {
binding.setCategory(CATEGORY_ACTIVITY);
bindings.addBinding(binding);
}
}
} else {
log.trace("skipping unavailable activities resource: " + activityResource);
}
}
}
protected Enumeration<URL> getResources(String resourceName) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> resourceUrls;
try {
resourceUrls = classLoader.getResources(resourceName);
if (!resourceUrls.hasMoreElements()) {
resourceUrls = BpmnParser.class.getClassLoader().getResources(resourceName);
}
} catch (Exception e) {
throw new JbpmException("couldn't get resource urls for "+resourceName, e);
}
return resourceUrls;
}
private void parseDataObjects(Element element, Parse parse, BpmnProcessDefinition processDefinition) {
List<VariableDefinitionImpl> variableDefinitions = new ArrayList<VariableDefinitionImpl>();
for (Element dataElement : XmlUtil.elements(element, "dataObject")) {
VariableDefinitionImpl variableDefinition = new VariableDefinitionImpl();
String name = XmlUtil.attribute(dataElement, "id", parse);
variableDefinition.setName(name);
String typeRef = XmlUtil.attribute(dataElement, "itemSubjectRef");
variableDefinition.setTypeName(processDefinition.getType(typeRef));
variableDefinitions.add(variableDefinition);
}
processDefinition.setVariableDefinition(variableDefinitions);
}
public void parseActivities(Element element, Parse parse, CompositeElementImpl compositeElement) {
List<Element> elements = XmlUtil.elements(element);
for (Element nestedElement : elements) {
String tagName = nestedElement.getLocalName();
String name = XmlUtil.attribute(nestedElement, "name");
String id = XmlUtil.attribute(nestedElement, "id", parse);
TagBinding activityBinding = (TagBinding) getBinding(nestedElement, CATEGORY_ACTIVITY);
if (activityBinding == null) {
if (!"sequenceFlow".equals(tagName)) {
log.debug("unrecognized activity: " + tagName);
}
continue;
}
ActivityImpl activity = compositeElement.createActivity();
parse.contextStackPush(activity);
try {
activity.setType(activityBinding.getTagName());
activity.setName(id);
activity.setDescription(name);
if (log.isDebugEnabled()) {
log.debug("Parsing Activity: " + name + "(id=" + id + ")");
}
ActivityBehaviour activityBehaviour = (ActivityBehaviour) activityBinding.parse(nestedElement, parse, this);
activity.setActivityBehaviour(activityBehaviour);
} finally {
parse.contextStackPop();
}
}
}
public void parseSequenceFlow(Element element, Parse parse, BpmnProcessDefinition processDefinition) {
List<Element> transitionElements = XmlUtil.elements(element, "sequenceFlow");
for (Element transitionElement : transitionElements) {
// Parse attributes
String transitionName = XmlUtil.attribute(transitionElement, "name");
String transitionId = XmlUtil.attribute(transitionElement, "id", parse);
String sourceRef = XmlUtil.attribute(transitionElement, "sourceRef", parse);
String targetRef = XmlUtil.attribute(transitionElement, "targetRef", parse);
if (log.isDebugEnabled()) {
log.debug(transitionId + ": " + sourceRef + " -> " + targetRef);
}
// Create new outgoing transition on sourceActivity
ActivityImpl sourceActivity = processDefinition.findActivity(sourceRef);
TransitionImpl transition = null;
if (sourceActivity != null) {
transition = sourceActivity.createOutgoingTransition();
transition.setName(transitionId);
transition.setDescription(transitionName);
} else {
parse.addProblem("SourceRef " + sourceRef + " cannot be found");
}
// Create incoming transition on targetActivity
ActivityImpl destinationActivity = processDefinition.findActivity(targetRef);
if (destinationActivity != null) {
destinationActivity.addIncomingTransition(transition);
} else {
parse.addProblem("TargetRef '" + targetRef + "' cannot be found");
}
// Set default sequence flow if applicable
try {
// If something went wrong parsing the activity, there is no behaviour and an exception is thrown in .getBehaviour()
ActivityBehaviour behaviour = sourceActivity.getActivityBehaviour();
if (behaviour instanceof BpmnActivity) {
BpmnActivity bpmnActivity = (BpmnActivity) behaviour;
String defaultSeqFlow = bpmnActivity.getDefault();
if (bpmnActivity.isDefaultEnabled() && defaultSeqFlow != null) {
if (transitionId.equals(defaultSeqFlow)) {
processDefinition.findActivity(sourceRef).setDefaultOutgoingTransition(transition);
}
} else {
processDefinition.findActivity(sourceRef).setDefaultOutgoingTransition(null);
}
} else {
// Other flownodes do not have default sequenceFlows, so set it to null
processDefinition.findActivity(sourceRef).setDefaultOutgoingTransition(null);
}
} catch (JbpmException je) {
// catch it and only re-throw if not this specific exception.
if (!je.getMessage().contains("no behaviour on")) {
throw je;
}
}
parseConditionOnSequenceFlow(parse, transitionElement, transitionId, transition);
processDefinition.addSequenceFlow(transitionId, transition);
}
}
public void parseConditionOnSequenceFlow(Parse parse, Element transitionElement, String transitionId, TransitionImpl transition) {
Element conditionElement = XmlUtil.element(transitionElement, "conditionExpression");
if (conditionElement != null) {
String type = conditionElement.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "type");
if ("bpmn:tFormalExpression".equals(type) || "tFormalExpression".equals(type)) {
String expr = conditionElement.getTextContent();
String lang = XmlUtil.attribute(conditionElement, "language");
// TODO: add looking up the default language in the document under definitions if lang is null.
if (expr != null) {
expr = expr.trim();
}
SequenceflowCondition condition = new SequenceflowCondition();
condition.setExpression(expr);
condition.setLanguage(lang);
transition.setCondition(condition);
} else {
parse.addProblem("Type of the conditionExpression on sequenceFlow with id=" +
transitionId + " is of onsupported type 'bpmn:tExpression'", transitionElement);
}
}
}
public void parseDefinition(Element documentElement, Parse parse) {
parseImports(documentElement, parse);
}
public TaskDefinitionImpl parseTaskDefinition(Element element, Parse parse, ScopeElementImpl scopeElement) {
TaskDefinitionImpl taskDefinition = new TaskDefinitionImpl();
String taskName = XmlUtil.attribute(element, "name");
taskDefinition.setName(taskName);
BpmnProcessDefinition processDefinition = parse.contextStackFind(BpmnProcessDefinition.class);
if (processDefinition.getTaskDefinition(taskName) != null) {
parse.addProblem("duplicate task name " + taskName, element);
} else {
processDefinition.addTaskDefinitionImpl(taskDefinition);
}
return taskDefinition;
}
/**
* Parses a <timerEventDefinition> element:
* * sets dueDate if 'timeDate' is used
* * sets duedateDescription if a duration expression is used
* * set cronExpression if a cron expression is used
*
* @param timerEventDefinitionElement The XML element that defines the timer definition
* @param activity The activity on which the timer definition must be created
* @param eventId The id of the event on which the timer is defined
*/
public TimerDefinitionImpl parseTimerEventDefinition(Element timerEventDefinitionElement, Parse parse, String eventId) {
Element timeDate = XmlUtil.element(timerEventDefinitionElement, "timeDate");
Element timeCycle = XmlUtil.element(timerEventDefinitionElement, "timeCycle");
if ((timeDate != null && timeCycle != null)
|| (timeDate == null && timeCycle == null)) {
parse.addProblem("timerEventDefinition for event '" + eventId +
"' requires either a timeDate or a timeCycle definition (but not both)");
return null;
}
TimerDefinitionImpl timerDefinition = new TimerDefinitionImpl();
if (timeDate != null) {
parseTimeDate(eventId, parse, timeDate, timerDefinition);
}
if (timeCycle != null) {
parseTimeCycle(eventId, parse, timeCycle, timerDefinition);
}
return timerDefinition;
}
protected void parseTimeDate(String catchEventId, Parse parse, Element timeDate, TimerDefinitionImpl timerDefinition) {
String dueDateTime = timeDate.getTextContent();
String dueDateTimeFormatText = (String) EnvironmentImpl.getFromCurrent("jbpm.duedatetime.format", false);
if (dueDateTimeFormatText==null) {
dueDateTimeFormatText = "dd/MM/yyyy HH:mm:ss";
}
SimpleDateFormat dateFormat = new SimpleDateFormat(dueDateTimeFormatText);
try {
Date duedatetimeDate = dateFormat.parse(dueDateTime);
timerDefinition.setDueDate(duedatetimeDate);
} catch (ParseException e) {
parse.addProblem("couldn't parse timeDate '"+ dueDateTime
+ "' on intermediate catch timer event " + catchEventId, e);
}
}
protected void parseTimeCycle(String catchEventId, Parse parse, Element timeCycle, TimerDefinitionImpl timerDefinition) {
String cycleExpression = timeCycle.getTextContent();
if (Duration.isValidExpression(cycleExpression)) {
timerDefinition.setDueDateDescription(cycleExpression);
} else if (CronExpression.isValidExpression(cycleExpression)) {
timerDefinition.setCronExpression(cycleExpression);
} else {
parse.addProblem("couldn't parse timeDate duration '"+ cycleExpression
+ "' on intermediate catch timer event " + catchEventId);
}
}
public void parseResources(Element documentElement, Parse parse, BpmnProcessDefinition processDefinition) {
for (Element resourceElement : XmlUtil.elements(documentElement, "resource")) {
Resource resource = new Resource();
resource.setId(XmlUtil.attribute(resourceElement, "id"));
resource.setName(XmlUtil.attribute(resourceElement, "name"));
for (Element resourceParameterElement : XmlUtil.elements(documentElement, "resourceParameter")) {
ResourceParameter resourceParameter = new ResourceParameter();
resourceParameter.setId(XmlUtil.attribute(resourceParameterElement, "id"));
resourceParameter.setName(XmlUtil.attribute(resourceParameterElement, "name"));
resourceParameter.setType(QName.valueOf(XmlUtil.attribute(resourceParameterElement, "name")));
resource.getParameters().put(XmlUtil.attribute(resourceParameterElement, "name"), resourceParameter);
}
processDefinition.getResources().put(resource.getName(), resource);
}
}
public void parseInterfaces(Element documentElement, Parse parse, BpmnProcessDefinition processDefinition) {
for (Element interfaceElement : XmlUtil.elements(documentElement, "interface")) {
for (Element operationElement : XmlUtil.elements(interfaceElement, "operation")) {
processDefinition.getOperations().put(XmlUtil.attribute(operationElement, "id"), operationElement);
}
processDefinition.getInterfaces().put(XmlUtil.attribute(interfaceElement, "id"), interfaceElement);
}
}
public void parseMessages(Element documentElement, Parse parse, BpmnProcessDefinition processDefinition) {
for (Element messageElement : XmlUtil.elements(documentElement, "message")) {
processDefinition.getMessages().put(XmlUtil.attribute(messageElement, "id"), messageElement);
}
}
public void parseItemDefinitions(Element documentElement, Parse parse, BpmnProcessDefinition processDefinition) {
for (Element itemDefinitionElement : XmlUtil.elements(documentElement, "itemDefinition")) {
processDefinition.getItemDefinitions().put(XmlUtil.attribute(itemDefinitionElement, "id"), itemDefinitionElement);
}
}
public void parseImports(Element documentElement, Parse parse) {
}
}
Vielen Dank. Das Problem ist nicht, dass alle für bpmn entwickelten Software ihr Modell in eine XML-Datei exportieren können. Für den zukünftigen Benutzer, der die gleiche Frage stellt, habe ich die Lösung gefunden. Sie können 'camunda bpm' verwenden – Mehdi
Wenn Sie die Lösung gefunden haben, posten Sie sie, damit jeder sie sehen kann. – Suncatcher