/*
* Copyright 2014 Effektif GmbH.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.effektif.workflow.api.workflow;
import org.joda.time.LocalDateTime;
import com.effektif.workflow.api.WorkflowEngine;
import com.effektif.workflow.api.bpmn.BpmnReader;
import com.effektif.workflow.api.bpmn.BpmnWriter;
import com.effektif.workflow.api.bpmn.XmlElement;
import com.effektif.workflow.api.model.WorkflowId;
import com.effektif.workflow.api.types.DataType;
/**
* An executable workflow in API format to deploy
* it into the {@link WorkflowEngine}.
*
* From this API format, the workflow can be converted
* to following other formats:
* <ul>
* <li>JSON java format (maps and lists)</li>
* <li>JSON format (String or stream)</li>
* <li>BPMN XML</li>
* <li>DB format</li>
* </ul>
*
* BPMN XML:
* <pre>{@code
* <process id="vacationRequest" name="Vacation request">
* <!-- activities -->
* </process>
* }</pre>
*
* @author Tom Baeyens
*/
public class ExecutableWorkflow extends AbstractWorkflow {
/** @see #sourceWorkflowId(String) */
protected String sourceWorkflowId;
protected LocalDateTime createTime;
protected String creatorId;
@Override
public void readBpmn(BpmnReader r) {
r.startExtensionElements();
name = r.readStringAttributeBpmn("name");
sourceWorkflowId = r.readStringValue("sourceWorkflowId");
createTime = r.readDateValue("createTime");
creatorId = r.readStringValue("creatorId");
enableCases = Boolean.valueOf(r.readStringValue("enableCases"));
// TODO move access control in a property?
// for (XmlElement nestedElemenet : r.readElementsEffektif("access")) {
// r.startElement(nestedElemenet);
// access = new AccessControlList();
// access.readBpmn(r);
// r.endElement();
// }
for (XmlElement nestedElement: r.readElementsEffektif("variable")) {
r.startElement(nestedElement);
Variable variable = new Variable();
variable.readBpmn(r);
variable(variable);
r.endElement();
}
for (XmlElement nestedElement: r.readElementsEffektif("trigger")) {
r.startElement(nestedElement);
trigger = r.readTriggerEffektif();
r.endElement();
}
r.endExtensionElements();
super.readBpmn(r);
}
/**
* Writes workflow-level BPMN, implemented here instead of partly in {@link AbstractWorkflow} (for superclass fields)
* because there can only be one <code>process/extensionElements</code> element in the output.
*/
@Override
public void writeBpmn(BpmnWriter w) {
super.writeBpmn(w);
w.startExtensionElements();
w.writeStringValue("sourceWorkflowId", "value", sourceWorkflowId);
w.writeStringValue("creatorId", "value", creatorId);
w.writeStringValue("enableCases", "value", enableCases);
if (createTime != null) {
w.startElementEffektif("createTime");
w.writeDateAttributeEffektif("value", createTime);
w.endElement();
}
// TODO move access control in a property?
// if (access != null) {
// access.writeBpmn(w);
// }
if (variables != null) {
for (Variable variable : variables) {
variable.writeBpmn(w);
}
}
if (trigger != null) {
trigger.writeBpmn(w);
}
w.endExtensionElements();
}
/** refers to the id in the source (or authoring) form of this workflow.
* @see #sourceWorkflowId(String) */
public String getSourceWorkflowId() {
return this.sourceWorkflowId;
}
/** refers to the id in the source (or authoring) form of this workflow.
* @see #sourceWorkflowId(String) */
public void setSourceWorkflowId(String source) {
this.sourceWorkflowId = source;
}
/** refers to the id in the source (or authoring) form of this workflow.
* Authoring and source mean that there is some file or form that gets edited
* and changes. Then a snapshot of this sourceform gets deployed as an executable workflow.
* Workflows are authored in some editor. Either a file editor or the Effektif product editor.
* The 3 sources where a workflow could be created are:
* 1) The Java API. You could deploy a workflow with the same value {@link #sourceWorkflowId(String)}
* multiple times.
* 2) A BPMN-file. When parsing a BPMN-file, then the sourceWorkflowId is set to the
* id attribute of the process element.
* 3) The Effektif product editor. In that case, the workflows you see in the tool
* are in fact editor workflows. You'll find the editor workflow id as the sourceWorkflowId
* in the deployed processes.*/
public ExecutableWorkflow sourceWorkflowId(String sourceWorkflowId) {
this.sourceWorkflowId = sourceWorkflowId;
return this;
}
public LocalDateTime getCreateTime() {
return this.createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public ExecutableWorkflow createTime(LocalDateTime createTime) {
this.createTime = createTime;
return this;
}
public String getCreatorId() {
return this.creatorId;
}
public void setCreatorId(String id) {
this.creatorId = id;
}
public ExecutableWorkflow creatorId(String id) {
this.creatorId = id;
return this;
}
/** add an activity to the workflow */
@Override
public ExecutableWorkflow activity(Activity activity) {
super.activity(activity);
return this;
}
/** add an activity to the workflow */
@Override
public ExecutableWorkflow activity(String id, Activity activity) {
super.activity(id, activity);
return this;
}
/** add a transition to this workflow where the id is specified in the transition */
@Override
public ExecutableWorkflow transition(Transition transition) {
super.transition(transition);
return this;
}
/** add a transition to this workflow and set the given id. */
@Override
public ExecutableWorkflow transition(String id, Transition transition) {
super.transition(id, transition);
return this;
}
/** add a variable to this workflow and set the given id. */
@Override
public ExecutableWorkflow variable(String id, DataType type) {
super.variable(id, type);
return this;
}
/** add a timer to this workflow. */
@Override
public ExecutableWorkflow timer(Timer timer) {
super.timer(timer);
return this;
}
/** sets the id of this workflow.
* The id is not really used during execution. */
@Override
public ExecutableWorkflow id(WorkflowId id) {
super.id(id);
return this;
}
@Override
public ExecutableWorkflow name(String name) {
super.name(name);
return this;
}
@Override
public ExecutableWorkflow description(String description) {
super.description(description);
return this;
}
@Override
public ExecutableWorkflow property(String key, Object value) {
super.property(key, value);
return this;
}
@Override
public ExecutableWorkflow propertyOpt(String key, Object value) {
super.propertyOpt(key, value);
return this;
}
@Override
public ExecutableWorkflow trigger(Trigger trigger) {
super.trigger(trigger);
return this;
}
@Override
public ExecutableWorkflow variable(Variable variable) {
super.variable(variable);
return this;
}
}