Skip to main content

Introducing Formengine - The New Formbuilder, try for FREE formengine.io.

Scheme generation

We have already mentioned several times that in case Workflow Engine does not find an active scheme in the WorkflowProcessInstance table (object), scheme generation is started. Let's discuss what a scheme generator is and what opportunities for enhancing Workflow Engine's operation it provides. In fact, the IWorkflowGenerator interface is defined by a single method.

public interface IWorkflowGenerator<TSchemeMedium> where TSchemeMedium : class
{
Task<TSchemeMedium> GenerateAsync(string schemeCode);
}

The TSchemeMedium type specifies the type of scheme storing. By default, this is the XElement type; in other words, the scheme is stored in XML. The GenerateAsync method accepts one parameter:

  • schemeCode - scheme name (code);

Each Persistence provider implements the IWorkflowGenerator interface. The following code explains how it functions out-of-the-box:

public async Task<XElement> GenerateAsync(string schemeCode)
{
return await GetSchemeAsync(schemeCode);
}

public async Task<XElement> GetSchemeAsync(string code)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
WorkflowScheme scheme = await WorkflowScheme.SelectByKeyAsync(connection, code);
if (scheme == null || string.IsNullOrEmpty(scheme.Scheme))
throw SchemeNotFoundException.Create(code, SchemeLocation.WorkflowProcessScheme);

return XElement.Parse(scheme.Scheme);
}
}

By default, the generator simply returns the scheme from the WorkflowScheme table (object).

The following use cases may be implemented with the help of a scheme generator:

  • Adjusting of the basic scheme dynamically. It comprises addition of new Activities, Transitions, Actions, etc.
  • Generation of a scheme according to the business data. For example, you have an object where all the successive process stages are specified, and a process scheme is generated on their basis.
  • Template-based generation.
  • Transformation of a scheme created in custom designer into the Workflow Engine scheme.

The following code explains how to add standardized Actions to each Activity of an existing scheme. This example is taken from a real project, though it was tailored a bit.

public class Generator : IWorkflowGenerator<XElement>
{
public async Task<XElement> GenerateAsync(string schemeCode)
{
var processDefinition = await WorkflowInit.Runtime.Builder.GetProcessSchemeForDesignerAsync(schemeCode);

if (processDefinition == null)
{
throw SchemeNotFoundException.Create(schemeCode, SchemeLocation.WorkflowProcessScheme);
}

foreach (var activity in processDefinition.Activities.Where(a => !string.IsNullOrWhiteSpace(a.State)))
{
if (activity.Implementation.All(c => c.ActionName != "SetDocumentState"))
{
activity.AddAction(
ActionDefinitionReference.Create("SetDocumentState", "0", string.Empty));
}

if (activity.IsForSetState)
{
if (activity.Implementation.All(c => c.ActionName != "UpdateHistory"))
{
activity.AddAction(
ActionDefinitionReference.Create("UpdateHistory", "99", string.Empty));
}
if (activity.PreExecutionImplementation.All(c => c.ActionName != "WriteHistory"))
{
activity.AddPreExecutionAction(
ActionDefinitionReference.Create("WriteHistory", "99", string.Empty));
}
}
}

return XElement.Parse(processDefinition.Serialize());
}
}